瀏覽代碼

Merge remote-tracking branch 'upstream/dev' into playwright

Rory 2 月之前
父節點
當前提交
40d4db97e6
共有 100 個文件被更改,包括 3047 次插入1018 次删除
  1. 66 2
      backend/open_webui/config.py
  2. 48 3
      backend/open_webui/main.py
  3. 18 0
      backend/open_webui/models/users.py
  4. 3 9
      backend/open_webui/retrieval/vector/dbs/opensearch.py
  5. 72 0
      backend/open_webui/retrieval/web/bocha.py
  6. 32 16
      backend/open_webui/retrieval/web/google_pse.py
  7. 2 5
      backend/open_webui/retrieval/web/jina_search.py
  8. 6 2
      backend/open_webui/routers/audio.py
  9. 92 0
      backend/open_webui/routers/configs.py
  10. 16 20
      backend/open_webui/routers/files.py
  11. 46 69
      backend/open_webui/routers/images.py
  12. 12 14
      backend/open_webui/routers/ollama.py
  13. 18 0
      backend/open_webui/routers/retrieval.py
  14. 1 1
      backend/open_webui/routers/users.py
  15. 7 5
      backend/open_webui/storage/provider.py
  16. 148 0
      backend/open_webui/utils/code_interpreter.py
  17. 86 10
      backend/open_webui/utils/middleware.py
  18. 1 1
      backend/open_webui/utils/misc.py
  19. 14 5
      backend/open_webui/utils/oauth.py
  20. 6 6
      backend/open_webui/utils/payload.py
  21. 7 5
      backend/open_webui/utils/pdf_generator.py
  22. 3 1
      backend/open_webui/utils/response.py
  23. 1 1
      backend/requirements.txt
  24. 1 1
      pyproject.toml
  25. 114 0
      src/lib/apis/configs/index.ts
  26. 97 1
      src/lib/apis/index.ts
  27. 78 22
      src/lib/apis/openai/index.ts
  28. 7 3
      src/lib/components/AddConnectionModal.svelte
  29. 2 2
      src/lib/components/admin/Evaluations/Feedbacks.svelte
  30. 34 8
      src/lib/components/admin/Functions.svelte
  31. 36 0
      src/lib/components/admin/Settings.svelte
  32. 5 2
      src/lib/components/admin/Settings/Audio.svelte
  33. 166 0
      src/lib/components/admin/Settings/CodeInterpreter.svelte
  34. 62 13
      src/lib/components/admin/Settings/Connections.svelte
  35. 1 1
      src/lib/components/admin/Settings/Connections/OllamaConnection.svelte
  36. 2 1
      src/lib/components/admin/Settings/Connections/OpenAIConnection.svelte
  37. 39 19
      src/lib/components/admin/Settings/Evaluations.svelte
  38. 1 1
      src/lib/components/admin/Settings/General.svelte
  39. 20 4
      src/lib/components/admin/Settings/Models.svelte
  40. 25 5
      src/lib/components/admin/Settings/Models/Manage/ManageOllama.svelte
  41. 25 5
      src/lib/components/admin/Settings/Pipelines.svelte
  42. 14 0
      src/lib/components/admin/Settings/WebSearch.svelte
  43. 12 9
      src/lib/components/chat/Chat.svelte
  44. 18 6
      src/lib/components/chat/MessageInput.svelte
  45. 17 2
      src/lib/components/chat/MessageInput/CallOverlay.svelte
  46. 2 0
      src/lib/components/chat/Messages/Citations.svelte
  47. 17 2
      src/lib/components/chat/Messages/CodeBlock.svelte
  48. 115 63
      src/lib/components/chat/Messages/ResponseMessage.svelte
  49. 207 201
      src/lib/components/chat/Messages/UserMessage.svelte
  50. 33 3
      src/lib/components/chat/ModelSelector/Selector.svelte
  51. 2 2
      src/lib/components/chat/Navbar.svelte
  52. 8 2
      src/lib/components/chat/Settings/Account.svelte
  53. 162 16
      src/lib/components/chat/Settings/Audio.svelte
  54. 152 0
      src/lib/components/chat/Settings/Connections.svelte
  55. 83 0
      src/lib/components/chat/Settings/Connections/Connection.svelte
  56. 44 2
      src/lib/components/chat/SettingsModal.svelte
  57. 2 2
      src/lib/components/chat/ShareChatModal.svelte
  58. 2 1
      src/lib/components/common/Collapsible.svelte
  59. 28 6
      src/lib/components/workspace/Models.svelte
  60. 2 2
      src/lib/components/workspace/Prompts.svelte
  61. 2 2
      src/lib/components/workspace/Tools.svelte
  62. 10 3
      src/lib/i18n/locales/ar-BH/translation.json
  63. 10 3
      src/lib/i18n/locales/bg-BG/translation.json
  64. 10 3
      src/lib/i18n/locales/bn-BD/translation.json
  65. 29 22
      src/lib/i18n/locales/ca-ES/translation.json
  66. 10 3
      src/lib/i18n/locales/ceb-PH/translation.json
  67. 10 3
      src/lib/i18n/locales/cs-CZ/translation.json
  68. 10 3
      src/lib/i18n/locales/da-DK/translation.json
  69. 10 3
      src/lib/i18n/locales/de-DE/translation.json
  70. 10 3
      src/lib/i18n/locales/dg-DG/translation.json
  71. 10 3
      src/lib/i18n/locales/el-GR/translation.json
  72. 10 3
      src/lib/i18n/locales/en-GB/translation.json
  73. 9 3
      src/lib/i18n/locales/en-US/translation.json
  74. 307 301
      src/lib/i18n/locales/es-ES/translation.json
  75. 10 3
      src/lib/i18n/locales/eu-ES/translation.json
  76. 10 3
      src/lib/i18n/locales/fa-IR/translation.json
  77. 10 3
      src/lib/i18n/locales/fi-FI/translation.json
  78. 10 3
      src/lib/i18n/locales/fr-CA/translation.json
  79. 10 3
      src/lib/i18n/locales/fr-FR/translation.json
  80. 10 3
      src/lib/i18n/locales/he-IL/translation.json
  81. 10 3
      src/lib/i18n/locales/hi-IN/translation.json
  82. 10 3
      src/lib/i18n/locales/hr-HR/translation.json
  83. 10 3
      src/lib/i18n/locales/hu-HU/translation.json
  84. 10 3
      src/lib/i18n/locales/id-ID/translation.json
  85. 10 3
      src/lib/i18n/locales/ie-GA/translation.json
  86. 10 3
      src/lib/i18n/locales/it-IT/translation.json
  87. 10 3
      src/lib/i18n/locales/ja-JP/translation.json
  88. 10 3
      src/lib/i18n/locales/ka-GE/translation.json
  89. 10 3
      src/lib/i18n/locales/ko-KR/translation.json
  90. 10 3
      src/lib/i18n/locales/lt-LT/translation.json
  91. 10 3
      src/lib/i18n/locales/ms-MY/translation.json
  92. 10 3
      src/lib/i18n/locales/nb-NO/translation.json
  93. 10 3
      src/lib/i18n/locales/nl-NL/translation.json
  94. 10 3
      src/lib/i18n/locales/pa-IN/translation.json
  95. 10 3
      src/lib/i18n/locales/pl-PL/translation.json
  96. 10 3
      src/lib/i18n/locales/pt-BR/translation.json
  97. 10 3
      src/lib/i18n/locales/pt-PT/translation.json
  98. 10 3
      src/lib/i18n/locales/ro-RO/translation.json
  99. 10 3
      src/lib/i18n/locales/ru-RU/translation.json
  100. 10 3
      src/lib/i18n/locales/sk-SK/translation.json

+ 66 - 2
backend/open_webui/config.py

@@ -683,6 +683,17 @@ Path(UPLOAD_DIR).mkdir(parents=True, exist_ok=True)
 CACHE_DIR = f"{DATA_DIR}/cache"
 CACHE_DIR = f"{DATA_DIR}/cache"
 Path(CACHE_DIR).mkdir(parents=True, exist_ok=True)
 Path(CACHE_DIR).mkdir(parents=True, exist_ok=True)
 
 
+
+####################################
+# DIRECT CONNECTIONS
+####################################
+
+ENABLE_DIRECT_CONNECTIONS = PersistentConfig(
+    "ENABLE_DIRECT_CONNECTIONS",
+    "direct.enable",
+    os.environ.get("ENABLE_DIRECT_CONNECTIONS", "True").lower() == "true",
+)
+
 ####################################
 ####################################
 # OLLAMA_BASE_URL
 # OLLAMA_BASE_URL
 ####################################
 ####################################
@@ -1326,6 +1337,54 @@ Your task is to synthesize these responses into a single, high-quality response.
 Responses from models: {{responses}}"""
 Responses from models: {{responses}}"""
 
 
 
 
+####################################
+# Code Interpreter
+####################################
+
+ENABLE_CODE_INTERPRETER = PersistentConfig(
+    "ENABLE_CODE_INTERPRETER",
+    "code_interpreter.enable",
+    os.environ.get("ENABLE_CODE_INTERPRETER", "True").lower() == "true",
+)
+
+CODE_INTERPRETER_ENGINE = PersistentConfig(
+    "CODE_INTERPRETER_ENGINE",
+    "code_interpreter.engine",
+    os.environ.get("CODE_INTERPRETER_ENGINE", "pyodide"),
+)
+
+CODE_INTERPRETER_PROMPT_TEMPLATE = PersistentConfig(
+    "CODE_INTERPRETER_PROMPT_TEMPLATE",
+    "code_interpreter.prompt_template",
+    os.environ.get("CODE_INTERPRETER_PROMPT_TEMPLATE", ""),
+)
+
+CODE_INTERPRETER_JUPYTER_URL = PersistentConfig(
+    "CODE_INTERPRETER_JUPYTER_URL",
+    "code_interpreter.jupyter.url",
+    os.environ.get("CODE_INTERPRETER_JUPYTER_URL", ""),
+)
+
+CODE_INTERPRETER_JUPYTER_AUTH = PersistentConfig(
+    "CODE_INTERPRETER_JUPYTER_AUTH",
+    "code_interpreter.jupyter.auth",
+    os.environ.get("CODE_INTERPRETER_JUPYTER_AUTH", ""),
+)
+
+CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = PersistentConfig(
+    "CODE_INTERPRETER_JUPYTER_AUTH_TOKEN",
+    "code_interpreter.jupyter.auth_token",
+    os.environ.get("CODE_INTERPRETER_JUPYTER_AUTH_TOKEN", ""),
+)
+
+
+CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = PersistentConfig(
+    "CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD",
+    "code_interpreter.jupyter.auth_password",
+    os.environ.get("CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD", ""),
+)
+
+
 DEFAULT_CODE_INTERPRETER_PROMPT = """
 DEFAULT_CODE_INTERPRETER_PROMPT = """
 #### Tools Available
 #### Tools Available
 
 
@@ -1336,9 +1395,8 @@ DEFAULT_CODE_INTERPRETER_PROMPT = """
    - When coding, **always aim to print meaningful outputs** (e.g., results, tables, summaries, or visuals) to better interpret and verify the findings. Avoid relying on implicit outputs; prioritize explicit and clear print statements so the results are effectively communicated to the user.  
    - When coding, **always aim to print meaningful outputs** (e.g., results, tables, summaries, or visuals) to better interpret and verify the findings. Avoid relying on implicit outputs; prioritize explicit and clear print statements so the results are effectively communicated to the user.  
    - After obtaining the printed output, **always provide a concise analysis, interpretation, or next steps to help the user understand the findings or refine the outcome further.**  
    - After obtaining the printed output, **always provide a concise analysis, interpretation, or next steps to help the user understand the findings or refine the outcome further.**  
    - If the results are unclear, unexpected, or require validation, refine the code and execute it again as needed. Always aim to deliver meaningful insights from the results, iterating if necessary.  
    - If the results are unclear, unexpected, or require validation, refine the code and execute it again as needed. Always aim to deliver meaningful insights from the results, iterating if necessary.  
-   - If a link is provided for an image, audio, or any file, include it in the response exactly as given to ensure the user has access to the original resource.  
+   - **If a link to an image, audio, or any file is provided in markdown format in the output, ALWAYS regurgitate word for word, explicitly display it as part of the response to ensure the user can access it easily, do NOT change the link.**
    - All responses should be communicated in the chat's primary language, ensuring seamless understanding. If the chat is multilingual, default to English for clarity.
    - All responses should be communicated in the chat's primary language, ensuring seamless understanding. If the chat is multilingual, default to English for clarity.
-   - **If a link to an image, audio, or any file is provided in markdown format, ALWAYS regurgitate explicitly display it as part of the response to ensure the user can access it easily, do NOT change the link.**
 
 
 Ensure that the tools are effectively utilized to achieve the highest-quality analysis for the user."""
 Ensure that the tools are effectively utilized to achieve the highest-quality analysis for the user."""
 
 
@@ -1691,6 +1749,12 @@ MOJEEK_SEARCH_API_KEY = PersistentConfig(
     os.getenv("MOJEEK_SEARCH_API_KEY", ""),
     os.getenv("MOJEEK_SEARCH_API_KEY", ""),
 )
 )
 
 
+BOCHA_SEARCH_API_KEY = PersistentConfig(
+    "BOCHA_SEARCH_API_KEY",
+    "rag.web.search.bocha_search_api_key",
+    os.getenv("BOCHA_SEARCH_API_KEY", ""),
+)
+
 SERPSTACK_API_KEY = PersistentConfig(
 SERPSTACK_API_KEY = PersistentConfig(
     "SERPSTACK_API_KEY",
     "SERPSTACK_API_KEY",
     "rag.web.search.serpstack_api_key",
     "rag.web.search.serpstack_api_key",

+ 48 - 3
backend/open_webui/main.py

@@ -97,6 +97,16 @@ from open_webui.config import (
     OPENAI_API_BASE_URLS,
     OPENAI_API_BASE_URLS,
     OPENAI_API_KEYS,
     OPENAI_API_KEYS,
     OPENAI_API_CONFIGS,
     OPENAI_API_CONFIGS,
+    # Direct Connections
+    ENABLE_DIRECT_CONNECTIONS,
+    # Code Interpreter
+    ENABLE_CODE_INTERPRETER,
+    CODE_INTERPRETER_ENGINE,
+    CODE_INTERPRETER_PROMPT_TEMPLATE,
+    CODE_INTERPRETER_JUPYTER_URL,
+    CODE_INTERPRETER_JUPYTER_AUTH,
+    CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
+    CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
     # Image
     # Image
     AUTOMATIC1111_API_AUTH,
     AUTOMATIC1111_API_AUTH,
     AUTOMATIC1111_BASE_URL,
     AUTOMATIC1111_BASE_URL,
@@ -183,6 +193,7 @@ from open_webui.config import (
     EXA_API_KEY,
     EXA_API_KEY,
     KAGI_SEARCH_API_KEY,
     KAGI_SEARCH_API_KEY,
     MOJEEK_SEARCH_API_KEY,
     MOJEEK_SEARCH_API_KEY,
+    BOCHA_SEARCH_API_KEY,
     GOOGLE_PSE_API_KEY,
     GOOGLE_PSE_API_KEY,
     GOOGLE_PSE_ENGINE_ID,
     GOOGLE_PSE_ENGINE_ID,
     GOOGLE_DRIVE_CLIENT_ID,
     GOOGLE_DRIVE_CLIENT_ID,
@@ -325,7 +336,11 @@ class SPAStaticFiles(StaticFiles):
             return await super().get_response(path, scope)
             return await super().get_response(path, scope)
         except (HTTPException, StarletteHTTPException) as ex:
         except (HTTPException, StarletteHTTPException) as ex:
             if ex.status_code == 404:
             if ex.status_code == 404:
-                return await super().get_response("index.html", scope)
+                if path.endswith(".js"):
+                    # Return 404 for javascript files
+                    raise ex
+                else:
+                    return await super().get_response("index.html", scope)
             else:
             else:
                 raise ex
                 raise ex
 
 
@@ -392,6 +407,14 @@ app.state.config.OPENAI_API_CONFIGS = OPENAI_API_CONFIGS
 
 
 app.state.OPENAI_MODELS = {}
 app.state.OPENAI_MODELS = {}
 
 
+########################################
+#
+# DIRECT CONNECTIONS
+#
+########################################
+
+app.state.config.ENABLE_DIRECT_CONNECTIONS = ENABLE_DIRECT_CONNECTIONS
+
 ########################################
 ########################################
 #
 #
 # WEBUI
 # WEBUI
@@ -517,6 +540,7 @@ app.state.config.GOOGLE_PSE_ENGINE_ID = GOOGLE_PSE_ENGINE_ID
 app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY
 app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY
 app.state.config.KAGI_SEARCH_API_KEY = KAGI_SEARCH_API_KEY
 app.state.config.KAGI_SEARCH_API_KEY = KAGI_SEARCH_API_KEY
 app.state.config.MOJEEK_SEARCH_API_KEY = MOJEEK_SEARCH_API_KEY
 app.state.config.MOJEEK_SEARCH_API_KEY = MOJEEK_SEARCH_API_KEY
+app.state.config.BOCHA_SEARCH_API_KEY = BOCHA_SEARCH_API_KEY
 app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY
 app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY
 app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
 app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS
 app.state.config.SERPER_API_KEY = SERPER_API_KEY
 app.state.config.SERPER_API_KEY = SERPER_API_KEY
@@ -574,6 +598,24 @@ app.state.EMBEDDING_FUNCTION = get_embedding_function(
     app.state.config.RAG_EMBEDDING_BATCH_SIZE,
     app.state.config.RAG_EMBEDDING_BATCH_SIZE,
 )
 )
 
 
+########################################
+#
+# CODE INTERPRETER
+#
+########################################
+
+app.state.config.ENABLE_CODE_INTERPRETER = ENABLE_CODE_INTERPRETER
+app.state.config.CODE_INTERPRETER_ENGINE = CODE_INTERPRETER_ENGINE
+app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = CODE_INTERPRETER_PROMPT_TEMPLATE
+
+app.state.config.CODE_INTERPRETER_JUPYTER_URL = CODE_INTERPRETER_JUPYTER_URL
+app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = CODE_INTERPRETER_JUPYTER_AUTH
+app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = (
+    CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
+)
+app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = (
+    CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
+)
 
 
 ########################################
 ########################################
 #
 #
@@ -759,6 +801,7 @@ app.include_router(openai.router, prefix="/openai", tags=["openai"])
 app.include_router(pipelines.router, prefix="/api/v1/pipelines", tags=["pipelines"])
 app.include_router(pipelines.router, prefix="/api/v1/pipelines", tags=["pipelines"])
 app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
 app.include_router(tasks.router, prefix="/api/v1/tasks", tags=["tasks"])
 app.include_router(images.router, prefix="/api/v1/images", tags=["images"])
 app.include_router(images.router, prefix="/api/v1/images", tags=["images"])
+
 app.include_router(audio.router, prefix="/api/v1/audio", tags=["audio"])
 app.include_router(audio.router, prefix="/api/v1/audio", tags=["audio"])
 app.include_router(retrieval.router, prefix="/api/v1/retrieval", tags=["retrieval"])
 app.include_router(retrieval.router, prefix="/api/v1/retrieval", tags=["retrieval"])
 
 
@@ -1017,15 +1060,17 @@ async def get_app_config(request: Request):
             "enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
             "enable_websocket": ENABLE_WEBSOCKET_SUPPORT,
             **(
             **(
                 {
                 {
+                    "enable_direct_connections": app.state.config.ENABLE_DIRECT_CONNECTIONS,
                     "enable_channels": app.state.config.ENABLE_CHANNELS,
                     "enable_channels": app.state.config.ENABLE_CHANNELS,
                     "enable_web_search": app.state.config.ENABLE_RAG_WEB_SEARCH,
                     "enable_web_search": app.state.config.ENABLE_RAG_WEB_SEARCH,
-                    "enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
+                    "enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER,
                     "enable_image_generation": app.state.config.ENABLE_IMAGE_GENERATION,
                     "enable_image_generation": app.state.config.ENABLE_IMAGE_GENERATION,
+                    "enable_autocomplete_generation": app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
                     "enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
                     "enable_community_sharing": app.state.config.ENABLE_COMMUNITY_SHARING,
                     "enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
                     "enable_message_rating": app.state.config.ENABLE_MESSAGE_RATING,
-                    "enable_autocomplete_generation": app.state.config.ENABLE_AUTOCOMPLETE_GENERATION,
                     "enable_admin_export": ENABLE_ADMIN_EXPORT,
                     "enable_admin_export": ENABLE_ADMIN_EXPORT,
                     "enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
                     "enable_admin_chat_access": ENABLE_ADMIN_CHAT_ACCESS,
+                    "enable_google_drive_integration": app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
                 }
                 }
                 if user is not None
                 if user is not None
                 else {}
                 else {}

+ 18 - 0
backend/open_webui/models/users.py

@@ -271,6 +271,24 @@ class UsersTable:
         except Exception:
         except Exception:
             return None
             return None
 
 
+    def update_user_settings_by_id(self, id: str, updated: dict) -> Optional[UserModel]:
+        try:
+            with get_db() as db:
+                user_settings = db.query(User).filter_by(id=id).first().settings
+
+                if user_settings is None:
+                    user_settings = {}
+
+                user_settings.update(updated)
+
+                db.query(User).filter_by(id=id).update({"settings": user_settings})
+                db.commit()
+
+                user = db.query(User).filter_by(id=id).first()
+                return UserModel.model_validate(user)
+        except Exception:
+            return None
+
     def delete_user_by_id(self, id: str) -> bool:
     def delete_user_by_id(self, id: str) -> bool:
         try:
         try:
             # Remove User from Groups
             # Remove User from Groups

+ 3 - 9
backend/open_webui/retrieval/vector/dbs/opensearch.py

@@ -120,18 +120,12 @@ class OpenSearchClient:
             return None
             return None
 
 
         query_body = {
         query_body = {
-            "query": {
-                "bool": {
-                    "filter": []
-                }
-            },
+            "query": {"bool": {"filter": []}},
             "_source": ["text", "metadata"],
             "_source": ["text", "metadata"],
         }
         }
 
 
         for field, value in filter.items():
         for field, value in filter.items():
-            query_body["query"]["bool"]["filter"].append({
-                "term": {field: value}
-            })
+            query_body["query"]["bool"]["filter"].append({"term": {field: value}})
 
 
         size = limit if limit else 10
         size = limit if limit else 10
 
 
@@ -139,7 +133,7 @@ class OpenSearchClient:
             result = self.client.search(
             result = self.client.search(
                 index=f"{self.index_prefix}_{collection_name}",
                 index=f"{self.index_prefix}_{collection_name}",
                 body=query_body,
                 body=query_body,
-                size=size
+                size=size,
             )
             )
 
 
             return self._result_to_get_result(result)
             return self._result_to_get_result(result)

+ 72 - 0
backend/open_webui/retrieval/web/bocha.py

@@ -0,0 +1,72 @@
+import logging
+from typing import Optional
+
+import requests
+import json
+from open_webui.retrieval.web.main import SearchResult, get_filtered_results
+from open_webui.env import SRC_LOG_LEVELS
+
+log = logging.getLogger(__name__)
+log.setLevel(SRC_LOG_LEVELS["RAG"])
+
+def _parse_response(response):
+    result = {}
+    if "data" in response:
+        data = response["data"]
+        if "webPages" in data:
+            webPages = data["webPages"]
+            if "value" in webPages:
+                result["webpage"] = [
+                    {
+                        "id": item.get("id", ""),
+                        "name": item.get("name", ""),
+                        "url": item.get("url", ""),
+                        "snippet": item.get("snippet", ""),
+                        "summary": item.get("summary", ""),
+                        "siteName": item.get("siteName", ""),
+                        "siteIcon": item.get("siteIcon", ""),
+                        "datePublished": item.get("datePublished", "") or item.get("dateLastCrawled", ""),
+                    }
+                    for item in webPages["value"]
+                ]
+    return result
+
+
+def search_bocha(
+    api_key: str, query: str, count: int, filter_list: Optional[list[str]] = None
+) -> list[SearchResult]:
+    """Search using Bocha's Search API and return the results as a list of SearchResult objects.
+
+    Args:
+        api_key (str): A Bocha Search API key
+        query (str): The query to search for
+    """
+    url = "https://api.bochaai.com/v1/web-search?utm_source=ollama"
+    headers = {
+        "Authorization": f"Bearer {api_key}",
+        "Content-Type": "application/json"
+    }
+    
+    payload = json.dumps({
+        "query": query,
+        "summary": True,
+        "freshness": "noLimit",
+        "count": count
+    })
+
+    response = requests.post(url, headers=headers, data=payload, timeout=5)
+    response.raise_for_status()
+    results = _parse_response(response.json())
+    print(results)
+    if filter_list:
+        results = get_filtered_results(results, filter_list)
+
+    return [
+        SearchResult(
+            link=result["url"], 
+            title=result.get("name"), 
+            snippet=result.get("summary")
+        )
+        for result in results.get("webpage", [])[:count]  
+    ]
+

+ 32 - 16
backend/open_webui/retrieval/web/google_pse.py

@@ -8,7 +8,6 @@ from open_webui.env import SRC_LOG_LEVELS
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 log.setLevel(SRC_LOG_LEVELS["RAG"])
 log.setLevel(SRC_LOG_LEVELS["RAG"])
 
 
-
 def search_google_pse(
 def search_google_pse(
     api_key: str,
     api_key: str,
     search_engine_id: str,
     search_engine_id: str,
@@ -17,34 +16,51 @@ def search_google_pse(
     filter_list: Optional[list[str]] = None,
     filter_list: Optional[list[str]] = None,
 ) -> list[SearchResult]:
 ) -> list[SearchResult]:
     """Search using Google's Programmable Search Engine API and return the results as a list of SearchResult objects.
     """Search using Google's Programmable Search Engine API and return the results as a list of SearchResult objects.
+    Handles pagination for counts greater than 10.
 
 
     Args:
     Args:
         api_key (str): A Programmable Search Engine API key
         api_key (str): A Programmable Search Engine API key
         search_engine_id (str): A Programmable Search Engine ID
         search_engine_id (str): A Programmable Search Engine ID
         query (str): The query to search for
         query (str): The query to search for
+        count (int): The number of results to return (max 100, as PSE max results per query is 10 and max page is 10)
+        filter_list (Optional[list[str]], optional): A list of keywords to filter out from results. Defaults to None.
+
+    Returns:
+        list[SearchResult]: A list of SearchResult objects.
     """
     """
     url = "https://www.googleapis.com/customsearch/v1"
     url = "https://www.googleapis.com/customsearch/v1"
-
     headers = {"Content-Type": "application/json"}
     headers = {"Content-Type": "application/json"}
-    params = {
-        "cx": search_engine_id,
-        "q": query,
-        "key": api_key,
-        "num": count,
-    }
-
-    response = requests.request("GET", url, headers=headers, params=params)
-    response.raise_for_status()
-
-    json_response = response.json()
-    results = json_response.get("items", [])
+    all_results = []
+    start_index = 1  # Google PSE start parameter is 1-based
+
+    while count > 0:
+        num_results_this_page = min(count, 10)  # Google PSE max results per page is 10
+        params = {
+            "cx": search_engine_id,
+            "q": query,
+            "key": api_key,
+            "num": num_results_this_page,
+            "start": start_index,
+        }
+        response = requests.request("GET", url, headers=headers, params=params)
+        response.raise_for_status()
+        json_response = response.json()
+        results = json_response.get("items", [])
+        if results: # check if results are returned. If not, no more pages to fetch.
+            all_results.extend(results)
+            count -= len(results) # Decrement count by the number of results fetched in this page.
+            start_index += 10 # Increment start index for the next page
+        else:
+            break # No more results from Google PSE, break the loop
+
     if filter_list:
     if filter_list:
-        results = get_filtered_results(results, filter_list)
+        all_results = get_filtered_results(all_results, filter_list)
+
     return [
     return [
         SearchResult(
         SearchResult(
             link=result["link"],
             link=result["link"],
             title=result.get("title"),
             title=result.get("title"),
             snippet=result.get("snippet"),
             snippet=result.get("snippet"),
         )
         )
-        for result in results
+        for result in all_results
     ]
     ]

+ 2 - 5
backend/open_webui/retrieval/web/jina_search.py

@@ -25,13 +25,10 @@ def search_jina(api_key: str, query: str, count: int) -> list[SearchResult]:
         "Accept": "application/json",
         "Accept": "application/json",
         "Content-Type": "application/json",
         "Content-Type": "application/json",
         "Authorization": api_key,
         "Authorization": api_key,
-        "X-Retain-Images": "none"
+        "X-Retain-Images": "none",
     }
     }
 
 
-    payload = {
-        "q": query,
-        "count": count if count <= 10 else 10
-    }
+    payload = {"q": query, "count": count if count <= 10 else 10}
 
 
     url = str(URL(jina_search_endpoint))
     url = str(URL(jina_search_endpoint))
     response = requests.post(url, headers=headers, json=payload)
     response = requests.post(url, headers=headers, json=payload)

+ 6 - 2
backend/open_webui/routers/audio.py

@@ -560,10 +560,14 @@ def transcribe(request: Request, file_path):
 
 
             # Extract transcript from Deepgram response
             # Extract transcript from Deepgram response
             try:
             try:
-                transcript = response_data["results"]["channels"][0]["alternatives"][0].get("transcript", "")
+                transcript = response_data["results"]["channels"][0]["alternatives"][
+                    0
+                ].get("transcript", "")
             except (KeyError, IndexError) as e:
             except (KeyError, IndexError) as e:
                 log.error(f"Malformed response from Deepgram: {str(e)}")
                 log.error(f"Malformed response from Deepgram: {str(e)}")
-                raise Exception("Failed to parse Deepgram response - unexpected response format")
+                raise Exception(
+                    "Failed to parse Deepgram response - unexpected response format"
+                )
             data = {"text": transcript.strip()}
             data = {"text": transcript.strip()}
 
 
             # Save transcript
             # Save transcript

+ 92 - 0
backend/open_webui/routers/configs.py

@@ -36,6 +36,98 @@ async def export_config(user=Depends(get_admin_user)):
     return get_config()
     return get_config()
 
 
 
 
+############################
+# Direct Connections Config
+############################
+
+
+class DirectConnectionsConfigForm(BaseModel):
+    ENABLE_DIRECT_CONNECTIONS: bool
+
+
+@router.get("/direct_connections", response_model=DirectConnectionsConfigForm)
+async def get_direct_connections_config(request: Request, user=Depends(get_admin_user)):
+    return {
+        "ENABLE_DIRECT_CONNECTIONS": request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
+    }
+
+
+@router.post("/direct_connections", response_model=DirectConnectionsConfigForm)
+async def set_direct_connections_config(
+    request: Request,
+    form_data: DirectConnectionsConfigForm,
+    user=Depends(get_admin_user),
+):
+    request.app.state.config.ENABLE_DIRECT_CONNECTIONS = (
+        form_data.ENABLE_DIRECT_CONNECTIONS
+    )
+    return {
+        "ENABLE_DIRECT_CONNECTIONS": request.app.state.config.ENABLE_DIRECT_CONNECTIONS,
+    }
+
+
+############################
+# CodeInterpreterConfig
+############################
+class CodeInterpreterConfigForm(BaseModel):
+    ENABLE_CODE_INTERPRETER: bool
+    CODE_INTERPRETER_ENGINE: str
+    CODE_INTERPRETER_PROMPT_TEMPLATE: Optional[str]
+    CODE_INTERPRETER_JUPYTER_URL: Optional[str]
+    CODE_INTERPRETER_JUPYTER_AUTH: Optional[str]
+    CODE_INTERPRETER_JUPYTER_AUTH_TOKEN: Optional[str]
+    CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD: Optional[str]
+
+
+@router.get("/code_interpreter", response_model=CodeInterpreterConfigForm)
+async def get_code_interpreter_config(request: Request, user=Depends(get_admin_user)):
+    return {
+        "ENABLE_CODE_INTERPRETER": request.app.state.config.ENABLE_CODE_INTERPRETER,
+        "CODE_INTERPRETER_ENGINE": request.app.state.config.CODE_INTERPRETER_ENGINE,
+        "CODE_INTERPRETER_PROMPT_TEMPLATE": request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE,
+        "CODE_INTERPRETER_JUPYTER_URL": request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
+        "CODE_INTERPRETER_JUPYTER_AUTH": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH,
+        "CODE_INTERPRETER_JUPYTER_AUTH_TOKEN": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
+        "CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
+    }
+
+
+@router.post("/code_interpreter", response_model=CodeInterpreterConfigForm)
+async def set_code_interpreter_config(
+    request: Request, form_data: CodeInterpreterConfigForm, user=Depends(get_admin_user)
+):
+    request.app.state.config.ENABLE_CODE_INTERPRETER = form_data.ENABLE_CODE_INTERPRETER
+    request.app.state.config.CODE_INTERPRETER_ENGINE = form_data.CODE_INTERPRETER_ENGINE
+    request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = (
+        form_data.CODE_INTERPRETER_PROMPT_TEMPLATE
+    )
+
+    request.app.state.config.CODE_INTERPRETER_JUPYTER_URL = (
+        form_data.CODE_INTERPRETER_JUPYTER_URL
+    )
+
+    request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = (
+        form_data.CODE_INTERPRETER_JUPYTER_AUTH
+    )
+
+    request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = (
+        form_data.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
+    )
+    request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = (
+        form_data.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
+    )
+
+    return {
+        "ENABLE_CODE_INTERPRETER": request.app.state.config.ENABLE_CODE_INTERPRETER,
+        "CODE_INTERPRETER_ENGINE": request.app.state.config.CODE_INTERPRETER_ENGINE,
+        "CODE_INTERPRETER_PROMPT_TEMPLATE": request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE,
+        "CODE_INTERPRETER_JUPYTER_URL": request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
+        "CODE_INTERPRETER_JUPYTER_AUTH": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH,
+        "CODE_INTERPRETER_JUPYTER_AUTH_TOKEN": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN,
+        "CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD": request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD,
+    }
+
+
 ############################
 ############################
 # SetDefaultModels
 # SetDefaultModels
 ############################
 ############################

+ 16 - 20
backend/open_webui/routers/files.py

@@ -3,30 +3,22 @@ import os
 import uuid
 import uuid
 from pathlib import Path
 from pathlib import Path
 from typing import Optional
 from typing import Optional
-from pydantic import BaseModel
-import mimetypes
 from urllib.parse import quote
 from urllib.parse import quote
 
 
-from open_webui.storage.provider import Storage
-
+from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile, status
+from fastapi.responses import FileResponse, StreamingResponse
+from open_webui.constants import ERROR_MESSAGES
+from open_webui.env import SRC_LOG_LEVELS
 from open_webui.models.files import (
 from open_webui.models.files import (
     FileForm,
     FileForm,
     FileModel,
     FileModel,
     FileModelResponse,
     FileModelResponse,
     Files,
     Files,
 )
 )
-from open_webui.routers.retrieval import process_file, ProcessFileForm
-
-from open_webui.config import UPLOAD_DIR
-from open_webui.env import SRC_LOG_LEVELS
-from open_webui.constants import ERROR_MESSAGES
-
-
-from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status, Request
-from fastapi.responses import FileResponse, StreamingResponse
-
-
+from open_webui.routers.retrieval import ProcessFileForm, process_file
+from open_webui.storage.provider import Storage
 from open_webui.utils.auth import get_admin_user, get_verified_user
 from open_webui.utils.auth import get_admin_user, get_verified_user
+from pydantic import BaseModel
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 log.setLevel(SRC_LOG_LEVELS["MODELS"])
 log.setLevel(SRC_LOG_LEVELS["MODELS"])
@@ -41,7 +33,10 @@ router = APIRouter()
 
 
 @router.post("/", response_model=FileModelResponse)
 @router.post("/", response_model=FileModelResponse)
 def upload_file(
 def upload_file(
-    request: Request, file: UploadFile = File(...), user=Depends(get_verified_user)
+    request: Request,
+    file: UploadFile = File(...),
+    user=Depends(get_verified_user),
+    file_metadata: dict = {},
 ):
 ):
     log.info(f"file.content_type: {file.content_type}")
     log.info(f"file.content_type: {file.content_type}")
     try:
     try:
@@ -65,6 +60,7 @@ def upload_file(
                         "name": name,
                         "name": name,
                         "content_type": file.content_type,
                         "content_type": file.content_type,
                         "size": len(contents),
                         "size": len(contents),
+                        "data": file_metadata,
                     },
                     },
                 }
                 }
             ),
             ),
@@ -126,7 +122,7 @@ async def delete_all_files(user=Depends(get_admin_user)):
             Storage.delete_all_files()
             Storage.delete_all_files()
         except Exception as e:
         except Exception as e:
             log.exception(e)
             log.exception(e)
-            log.error(f"Error deleting files")
+            log.error("Error deleting files")
             raise HTTPException(
             raise HTTPException(
                 status_code=status.HTTP_400_BAD_REQUEST,
                 status_code=status.HTTP_400_BAD_REQUEST,
                 detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
                 detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
@@ -248,7 +244,7 @@ async def get_file_content_by_id(id: str, user=Depends(get_verified_user)):
                 )
                 )
         except Exception as e:
         except Exception as e:
             log.exception(e)
             log.exception(e)
-            log.error(f"Error getting file content")
+            log.error("Error getting file content")
             raise HTTPException(
             raise HTTPException(
                 status_code=status.HTTP_400_BAD_REQUEST,
                 status_code=status.HTTP_400_BAD_REQUEST,
                 detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
                 detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
@@ -279,7 +275,7 @@ async def get_html_file_content_by_id(id: str, user=Depends(get_verified_user)):
                 )
                 )
         except Exception as e:
         except Exception as e:
             log.exception(e)
             log.exception(e)
-            log.error(f"Error getting file content")
+            log.error("Error getting file content")
             raise HTTPException(
             raise HTTPException(
                 status_code=status.HTTP_400_BAD_REQUEST,
                 status_code=status.HTTP_400_BAD_REQUEST,
                 detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
                 detail=ERROR_MESSAGES.DEFAULT("Error getting file content"),
@@ -355,7 +351,7 @@ async def delete_file_by_id(id: str, user=Depends(get_verified_user)):
                 Storage.delete_file(file.path)
                 Storage.delete_file(file.path)
             except Exception as e:
             except Exception as e:
                 log.exception(e)
                 log.exception(e)
-                log.error(f"Error deleting files")
+                log.error("Error deleting files")
                 raise HTTPException(
                 raise HTTPException(
                     status_code=status.HTTP_400_BAD_REQUEST,
                     status_code=status.HTTP_400_BAD_REQUEST,
                     detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),
                     detail=ERROR_MESSAGES.DEFAULT("Error deleting files"),

+ 46 - 69
backend/open_webui/routers/images.py

@@ -1,32 +1,26 @@
 import asyncio
 import asyncio
 import base64
 import base64
+import io
 import json
 import json
 import logging
 import logging
 import mimetypes
 import mimetypes
 import re
 import re
-import uuid
 from pathlib import Path
 from pathlib import Path
 from typing import Optional
 from typing import Optional
 
 
 import requests
 import requests
-
-
-from fastapi import Depends, FastAPI, HTTPException, Request, APIRouter
-from fastapi.middleware.cors import CORSMiddleware
-from pydantic import BaseModel
-
-
+from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile
 from open_webui.config import CACHE_DIR
 from open_webui.config import CACHE_DIR
 from open_webui.constants import ERROR_MESSAGES
 from open_webui.constants import ERROR_MESSAGES
-from open_webui.env import ENV, SRC_LOG_LEVELS, ENABLE_FORWARD_USER_INFO_HEADERS
-
+from open_webui.env import ENABLE_FORWARD_USER_INFO_HEADERS, SRC_LOG_LEVELS
+from open_webui.routers.files import upload_file
 from open_webui.utils.auth import get_admin_user, get_verified_user
 from open_webui.utils.auth import get_admin_user, get_verified_user
 from open_webui.utils.images.comfyui import (
 from open_webui.utils.images.comfyui import (
     ComfyUIGenerateImageForm,
     ComfyUIGenerateImageForm,
     ComfyUIWorkflow,
     ComfyUIWorkflow,
     comfyui_generate_image,
     comfyui_generate_image,
 )
 )
-
+from pydantic import BaseModel
 
 
 log = logging.getLogger(__name__)
 log = logging.getLogger(__name__)
 log.setLevel(SRC_LOG_LEVELS["IMAGES"])
 log.setLevel(SRC_LOG_LEVELS["IMAGES"])
@@ -271,7 +265,6 @@ async def get_image_config(request: Request, user=Depends(get_admin_user)):
 async def update_image_config(
 async def update_image_config(
     request: Request, form_data: ImageConfigForm, user=Depends(get_admin_user)
     request: Request, form_data: ImageConfigForm, user=Depends(get_admin_user)
 ):
 ):
-
     set_image_model(request, form_data.MODEL)
     set_image_model(request, form_data.MODEL)
 
 
     pattern = r"^\d+x\d+$"
     pattern = r"^\d+x\d+$"
@@ -383,40 +376,22 @@ class GenerateImageForm(BaseModel):
     negative_prompt: Optional[str] = None
     negative_prompt: Optional[str] = None
 
 
 
 
-def save_b64_image(b64_str):
+def load_b64_image_data(b64_str):
     try:
     try:
-        image_id = str(uuid.uuid4())
-
         if "," in b64_str:
         if "," in b64_str:
             header, encoded = b64_str.split(",", 1)
             header, encoded = b64_str.split(",", 1)
             mime_type = header.split(";")[0]
             mime_type = header.split(";")[0]
-
             img_data = base64.b64decode(encoded)
             img_data = base64.b64decode(encoded)
-            image_format = mimetypes.guess_extension(mime_type)
-
-            image_filename = f"{image_id}{image_format}"
-            file_path = IMAGE_CACHE_DIR / f"{image_filename}"
-            with open(file_path, "wb") as f:
-                f.write(img_data)
-            return image_filename
         else:
         else:
-            image_filename = f"{image_id}.png"
-            file_path = IMAGE_CACHE_DIR.joinpath(image_filename)
-
+            mime_type = "image/png"
             img_data = base64.b64decode(b64_str)
             img_data = base64.b64decode(b64_str)
-
-            # Write the image data to a file
-            with open(file_path, "wb") as f:
-                f.write(img_data)
-            return image_filename
-
+        return img_data, mime_type
     except Exception as e:
     except Exception as e:
-        log.exception(f"Error saving image: {e}")
+        log.exception(f"Error loading image data: {e}")
         return None
         return None
 
 
 
 
-def save_url_image(url, headers=None):
-    image_id = str(uuid.uuid4())
+def load_url_image_data(url, headers=None):
     try:
     try:
         if headers:
         if headers:
             r = requests.get(url, headers=headers)
             r = requests.get(url, headers=headers)
@@ -426,18 +401,7 @@ def save_url_image(url, headers=None):
         r.raise_for_status()
         r.raise_for_status()
         if r.headers["content-type"].split("/")[0] == "image":
         if r.headers["content-type"].split("/")[0] == "image":
             mime_type = r.headers["content-type"]
             mime_type = r.headers["content-type"]
-            image_format = mimetypes.guess_extension(mime_type)
-
-            if not image_format:
-                raise ValueError("Could not determine image type from MIME type")
-
-            image_filename = f"{image_id}{image_format}"
-
-            file_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}")
-            with open(file_path, "wb") as image_file:
-                for chunk in r.iter_content(chunk_size=8192):
-                    image_file.write(chunk)
-            return image_filename
+            return r.content, mime_type
         else:
         else:
             log.error("Url does not point to an image.")
             log.error("Url does not point to an image.")
             return None
             return None
@@ -447,6 +411,20 @@ def save_url_image(url, headers=None):
         return None
         return None
 
 
 
 
+def upload_image(request, image_metadata, image_data, content_type, user):
+    image_format = mimetypes.guess_extension(content_type)
+    file = UploadFile(
+        file=io.BytesIO(image_data),
+        filename=f"generated-image{image_format}",  # will be converted to a unique ID on upload_file
+        headers={
+            "content-type": content_type,
+        },
+    )
+    file_item = upload_file(request, file, user, file_metadata=image_metadata)
+    url = request.app.url_path_for("get_file_content_by_id", id=file_item.id)
+    return url
+
+
 @router.post("/generations")
 @router.post("/generations")
 async def image_generations(
 async def image_generations(
     request: Request,
     request: Request,
@@ -500,13 +478,9 @@ async def image_generations(
             images = []
             images = []
 
 
             for image in res["data"]:
             for image in res["data"]:
-                image_filename = save_b64_image(image["b64_json"])
-                images.append({"url": f"/cache/image/generations/{image_filename}"})
-                file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
-
-                with open(file_body_path, "w") as f:
-                    json.dump(data, f)
-
+                image_data, content_type = load_b64_image_data(image["b64_json"])
+                url = upload_image(request, data, image_data, content_type, user)
+                images.append({"url": url})
             return images
             return images
 
 
         elif request.app.state.config.IMAGE_GENERATION_ENGINE == "comfyui":
         elif request.app.state.config.IMAGE_GENERATION_ENGINE == "comfyui":
@@ -552,14 +526,15 @@ async def image_generations(
                         "Authorization": f"Bearer {request.app.state.config.COMFYUI_API_KEY}"
                         "Authorization": f"Bearer {request.app.state.config.COMFYUI_API_KEY}"
                     }
                     }
 
 
-                image_filename = save_url_image(image["url"], headers)
-                images.append({"url": f"/cache/image/generations/{image_filename}"})
-                file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
-
-                with open(file_body_path, "w") as f:
-                    json.dump(form_data.model_dump(exclude_none=True), f)
-
-            log.debug(f"images: {images}")
+                image_data, content_type = load_url_image_data(image["url"], headers)
+                url = upload_image(
+                    request,
+                    form_data.model_dump(exclude_none=True),
+                    image_data,
+                    content_type,
+                    user,
+                )
+                images.append({"url": url})
             return images
             return images
         elif (
         elif (
             request.app.state.config.IMAGE_GENERATION_ENGINE == "automatic1111"
             request.app.state.config.IMAGE_GENERATION_ENGINE == "automatic1111"
@@ -604,13 +579,15 @@ async def image_generations(
             images = []
             images = []
 
 
             for image in res["images"]:
             for image in res["images"]:
-                image_filename = save_b64_image(image)
-                images.append({"url": f"/cache/image/generations/{image_filename}"})
-                file_body_path = IMAGE_CACHE_DIR.joinpath(f"{image_filename}.json")
-
-                with open(file_body_path, "w") as f:
-                    json.dump({**data, "info": res["info"]}, f)
-
+                image_data, content_type = load_b64_image_data(image)
+                url = upload_image(
+                    request,
+                    {**data, "info": res["info"]},
+                    image_data,
+                    content_type,
+                    user,
+                )
+                images.append({"url": url})
             return images
             return images
     except Exception as e:
     except Exception as e:
         error = e
         error = e

+ 12 - 14
backend/open_webui/routers/ollama.py

@@ -1424,11 +1424,11 @@ async def upload_model(
     os.makedirs(UPLOAD_DIR, exist_ok=True)
     os.makedirs(UPLOAD_DIR, exist_ok=True)
 
 
     # --- P1: save file locally ---
     # --- P1: save file locally ---
-    chunk_size = 1024 * 1024 * 2 # 2 MB chunks
+    chunk_size = 1024 * 1024 * 2  # 2 MB chunks
     with open(file_path, "wb") as out_f:
     with open(file_path, "wb") as out_f:
         while True:
         while True:
             chunk = file.file.read(chunk_size)
             chunk = file.file.read(chunk_size)
-            #log.info(f"Chunk: {str(chunk)}") # DEBUG
+            # log.info(f"Chunk: {str(chunk)}") # DEBUG
             if not chunk:
             if not chunk:
                 break
                 break
             out_f.write(chunk)
             out_f.write(chunk)
@@ -1436,15 +1436,15 @@ async def upload_model(
     async def file_process_stream():
     async def file_process_stream():
         nonlocal ollama_url
         nonlocal ollama_url
         total_size = os.path.getsize(file_path)
         total_size = os.path.getsize(file_path)
-        log.info(f"Total Model Size: {str(total_size)}") # DEBUG
+        log.info(f"Total Model Size: {str(total_size)}")  # DEBUG
 
 
         # --- P2: SSE progress + calculate sha256 hash ---
         # --- P2: SSE progress + calculate sha256 hash ---
         file_hash = calculate_sha256(file_path, chunk_size)
         file_hash = calculate_sha256(file_path, chunk_size)
-        log.info(f"Model Hash: {str(file_hash)}") # DEBUG
+        log.info(f"Model Hash: {str(file_hash)}")  # DEBUG
         try:
         try:
             with open(file_path, "rb") as f:
             with open(file_path, "rb") as f:
                 bytes_read = 0
                 bytes_read = 0
-                while chunk := f.read(chunk_size): 
+                while chunk := f.read(chunk_size):
                     bytes_read += len(chunk)
                     bytes_read += len(chunk)
                     progress = round(bytes_read / total_size * 100, 2)
                     progress = round(bytes_read / total_size * 100, 2)
                     data_msg = {
                     data_msg = {
@@ -1460,25 +1460,23 @@ async def upload_model(
                 response = requests.post(url, data=f)
                 response = requests.post(url, data=f)
 
 
             if response.ok:
             if response.ok:
-                log.info(f"Uploaded to /api/blobs") # DEBUG
+                log.info(f"Uploaded to /api/blobs")  # DEBUG
                 # Remove local file
                 # Remove local file
                 os.remove(file_path)
                 os.remove(file_path)
 
 
                 # Create model in ollama
                 # Create model in ollama
                 model_name, ext = os.path.splitext(file.filename)
                 model_name, ext = os.path.splitext(file.filename)
-                log.info(f"Created Model: {model_name}") # DEBUG
+                log.info(f"Created Model: {model_name}")  # DEBUG
 
 
                 create_payload = {
                 create_payload = {
                     "model": model_name,
                     "model": model_name,
                     # Reference the file by its original name => the uploaded blob's digest
                     # Reference the file by its original name => the uploaded blob's digest
-                    "files": {
-                        file.filename: f"sha256:{file_hash}"
-                    },
+                    "files": {file.filename: f"sha256:{file_hash}"},
                 }
                 }
-                log.info(f"Model Payload: {create_payload}") # DEBUG
+                log.info(f"Model Payload: {create_payload}")  # DEBUG
 
 
                 # Call ollama /api/create
                 # Call ollama /api/create
-                #https://github.com/ollama/ollama/blob/main/docs/api.md#create-a-model
+                # https://github.com/ollama/ollama/blob/main/docs/api.md#create-a-model
                 create_resp = requests.post(
                 create_resp = requests.post(
                     url=f"{ollama_url}/api/create",
                     url=f"{ollama_url}/api/create",
                     headers={"Content-Type": "application/json"},
                     headers={"Content-Type": "application/json"},
@@ -1486,7 +1484,7 @@ async def upload_model(
                 )
                 )
 
 
                 if create_resp.ok:
                 if create_resp.ok:
-                    log.info(f"API SUCCESS!") # DEBUG
+                    log.info(f"API SUCCESS!")  # DEBUG
                     done_msg = {
                     done_msg = {
                         "done": True,
                         "done": True,
                         "blob": f"sha256:{file_hash}",
                         "blob": f"sha256:{file_hash}",
@@ -1506,4 +1504,4 @@ async def upload_model(
             res = {"error": str(e)}
             res = {"error": str(e)}
             yield f"data: {json.dumps(res)}\n\n"
             yield f"data: {json.dumps(res)}\n\n"
 
 
-    return StreamingResponse(file_process_stream(), media_type="text/event-stream")
+    return StreamingResponse(file_process_stream(), media_type="text/event-stream")

+ 18 - 0
backend/open_webui/routers/retrieval.py

@@ -45,6 +45,7 @@ from open_webui.retrieval.web.utils import get_web_loader
 from open_webui.retrieval.web.brave import search_brave
 from open_webui.retrieval.web.brave import search_brave
 from open_webui.retrieval.web.kagi import search_kagi
 from open_webui.retrieval.web.kagi import search_kagi
 from open_webui.retrieval.web.mojeek import search_mojeek
 from open_webui.retrieval.web.mojeek import search_mojeek
+from open_webui.retrieval.web.bocha import search_bocha
 from open_webui.retrieval.web.duckduckgo import search_duckduckgo
 from open_webui.retrieval.web.duckduckgo import search_duckduckgo
 from open_webui.retrieval.web.google_pse import search_google_pse
 from open_webui.retrieval.web.google_pse import search_google_pse
 from open_webui.retrieval.web.jina_search import search_jina
 from open_webui.retrieval.web.jina_search import search_jina
@@ -379,6 +380,7 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
                 "brave_search_api_key": request.app.state.config.BRAVE_SEARCH_API_KEY,
                 "brave_search_api_key": request.app.state.config.BRAVE_SEARCH_API_KEY,
                 "kagi_search_api_key": request.app.state.config.KAGI_SEARCH_API_KEY,
                 "kagi_search_api_key": request.app.state.config.KAGI_SEARCH_API_KEY,
                 "mojeek_search_api_key": request.app.state.config.MOJEEK_SEARCH_API_KEY,
                 "mojeek_search_api_key": request.app.state.config.MOJEEK_SEARCH_API_KEY,
+                "bocha_search_api_key": request.app.state.config.BOCHA_SEARCH_API_KEY,
                 "serpstack_api_key": request.app.state.config.SERPSTACK_API_KEY,
                 "serpstack_api_key": request.app.state.config.SERPSTACK_API_KEY,
                 "serpstack_https": request.app.state.config.SERPSTACK_HTTPS,
                 "serpstack_https": request.app.state.config.SERPSTACK_HTTPS,
                 "serper_api_key": request.app.state.config.SERPER_API_KEY,
                 "serper_api_key": request.app.state.config.SERPER_API_KEY,
@@ -429,6 +431,7 @@ class WebSearchConfig(BaseModel):
     brave_search_api_key: Optional[str] = None
     brave_search_api_key: Optional[str] = None
     kagi_search_api_key: Optional[str] = None
     kagi_search_api_key: Optional[str] = None
     mojeek_search_api_key: Optional[str] = None
     mojeek_search_api_key: Optional[str] = None
+    bocha_search_api_key: Optional[str] = None
     serpstack_api_key: Optional[str] = None
     serpstack_api_key: Optional[str] = None
     serpstack_https: Optional[bool] = None
     serpstack_https: Optional[bool] = None
     serper_api_key: Optional[str] = None
     serper_api_key: Optional[str] = None
@@ -525,6 +528,9 @@ async def update_rag_config(
         request.app.state.config.MOJEEK_SEARCH_API_KEY = (
         request.app.state.config.MOJEEK_SEARCH_API_KEY = (
             form_data.web.search.mojeek_search_api_key
             form_data.web.search.mojeek_search_api_key
         )
         )
+        request.app.state.config.BOCHA_SEARCH_API_KEY = (
+            form_data.web.search.bocha_search_api_key
+        )
         request.app.state.config.SERPSTACK_API_KEY = (
         request.app.state.config.SERPSTACK_API_KEY = (
             form_data.web.search.serpstack_api_key
             form_data.web.search.serpstack_api_key
         )
         )
@@ -591,6 +597,7 @@ async def update_rag_config(
                 "brave_search_api_key": request.app.state.config.BRAVE_SEARCH_API_KEY,
                 "brave_search_api_key": request.app.state.config.BRAVE_SEARCH_API_KEY,
                 "kagi_search_api_key": request.app.state.config.KAGI_SEARCH_API_KEY,
                 "kagi_search_api_key": request.app.state.config.KAGI_SEARCH_API_KEY,
                 "mojeek_search_api_key": request.app.state.config.MOJEEK_SEARCH_API_KEY,
                 "mojeek_search_api_key": request.app.state.config.MOJEEK_SEARCH_API_KEY,
+                "bocha_search_api_key": request.app.state.config.BOCHA_SEARCH_API_KEY,
                 "serpstack_api_key": request.app.state.config.SERPSTACK_API_KEY,
                 "serpstack_api_key": request.app.state.config.SERPSTACK_API_KEY,
                 "serpstack_https": request.app.state.config.SERPSTACK_HTTPS,
                 "serpstack_https": request.app.state.config.SERPSTACK_HTTPS,
                 "serper_api_key": request.app.state.config.SERPER_API_KEY,
                 "serper_api_key": request.app.state.config.SERPER_API_KEY,
@@ -1113,6 +1120,7 @@ def search_web(request: Request, engine: str, query: str) -> list[SearchResult]:
     - BRAVE_SEARCH_API_KEY
     - BRAVE_SEARCH_API_KEY
     - KAGI_SEARCH_API_KEY
     - KAGI_SEARCH_API_KEY
     - MOJEEK_SEARCH_API_KEY
     - MOJEEK_SEARCH_API_KEY
+    - BOCHA_SEARCH_API_KEY
     - SERPSTACK_API_KEY
     - SERPSTACK_API_KEY
     - SERPER_API_KEY
     - SERPER_API_KEY
     - SERPLY_API_KEY
     - SERPLY_API_KEY
@@ -1180,6 +1188,16 @@ def search_web(request: Request, engine: str, query: str) -> list[SearchResult]:
             )
             )
         else:
         else:
             raise Exception("No MOJEEK_SEARCH_API_KEY found in environment variables")
             raise Exception("No MOJEEK_SEARCH_API_KEY found in environment variables")
+    elif engine == "bocha":
+        if request.app.state.config.BOCHA_SEARCH_API_KEY:
+            return search_bocha(
+                request.app.state.config.BOCHA_SEARCH_API_KEY,
+                query,
+                request.app.state.config.RAG_WEB_SEARCH_RESULT_COUNT,
+                request.app.state.config.RAG_WEB_SEARCH_DOMAIN_FILTER_LIST,
+            )
+        else:
+            raise Exception("No BOCHA_SEARCH_API_KEY found in environment variables")
     elif engine == "serpstack":
     elif engine == "serpstack":
         if request.app.state.config.SERPSTACK_API_KEY:
         if request.app.state.config.SERPSTACK_API_KEY:
             return search_serpstack(
             return search_serpstack(

+ 1 - 1
backend/open_webui/routers/users.py

@@ -153,7 +153,7 @@ async def get_user_settings_by_session_user(user=Depends(get_verified_user)):
 async def update_user_settings_by_session_user(
 async def update_user_settings_by_session_user(
     form_data: UserSettings, user=Depends(get_verified_user)
     form_data: UserSettings, user=Depends(get_verified_user)
 ):
 ):
-    user = Users.update_user_by_id(user.id, {"settings": form_data.model_dump()})
+    user = Users.update_user_settings_by_id(user.id, form_data.model_dump())
     if user:
     if user:
         return user.settings
         return user.settings
     else:
     else:

+ 7 - 5
backend/open_webui/storage/provider.py

@@ -94,7 +94,7 @@ class S3StorageProvider(StorageProvider):
             aws_secret_access_key=S3_SECRET_ACCESS_KEY,
             aws_secret_access_key=S3_SECRET_ACCESS_KEY,
         )
         )
         self.bucket_name = S3_BUCKET_NAME
         self.bucket_name = S3_BUCKET_NAME
-        self.key_prefix = S3_KEY_PREFIX if S3_KEY_PREFIX else "" 
+        self.key_prefix = S3_KEY_PREFIX if S3_KEY_PREFIX else ""
 
 
     def upload_file(self, file: BinaryIO, filename: str) -> Tuple[bytes, str]:
     def upload_file(self, file: BinaryIO, filename: str) -> Tuple[bytes, str]:
         """Handles uploading of the file to S3 storage."""
         """Handles uploading of the file to S3 storage."""
@@ -108,7 +108,7 @@ class S3StorageProvider(StorageProvider):
             )
             )
         except ClientError as e:
         except ClientError as e:
             raise RuntimeError(f"Error uploading file to S3: {e}")
             raise RuntimeError(f"Error uploading file to S3: {e}")
-    
+
     def get_file(self, file_path: str) -> str:
     def get_file(self, file_path: str) -> str:
         """Handles downloading of the file from S3 storage."""
         """Handles downloading of the file from S3 storage."""
         try:
         try:
@@ -137,7 +137,8 @@ class S3StorageProvider(StorageProvider):
             if "Contents" in response:
             if "Contents" in response:
                 for content in response["Contents"]:
                 for content in response["Contents"]:
                     # Skip objects that were not uploaded from open-webui in the first place
                     # Skip objects that were not uploaded from open-webui in the first place
-                    if not content["Key"].startswith(self.key_prefix): continue
+                    if not content["Key"].startswith(self.key_prefix):
+                        continue
 
 
                     self.s3_client.delete_object(
                     self.s3_client.delete_object(
                         Bucket=self.bucket_name, Key=content["Key"]
                         Bucket=self.bucket_name, Key=content["Key"]
@@ -150,11 +151,12 @@ class S3StorageProvider(StorageProvider):
 
 
     # The s3 key is the name assigned to an object. It excludes the bucket name, but includes the internal path and the file name.
     # The s3 key is the name assigned to an object. It excludes the bucket name, but includes the internal path and the file name.
     def _extract_s3_key(self, full_file_path: str) -> str:
     def _extract_s3_key(self, full_file_path: str) -> str:
-        return '/'.join(full_file_path.split("//")[1].split("/")[1:])
-    
+        return "/".join(full_file_path.split("//")[1].split("/")[1:])
+
     def _get_local_file_path(self, s3_key: str) -> str:
     def _get_local_file_path(self, s3_key: str) -> str:
         return f"{UPLOAD_DIR}/{s3_key.split('/')[-1]}"
         return f"{UPLOAD_DIR}/{s3_key.split('/')[-1]}"
 
 
+
 class GCSStorageProvider(StorageProvider):
 class GCSStorageProvider(StorageProvider):
     def __init__(self):
     def __init__(self):
         self.bucket_name = GCS_BUCKET_NAME
         self.bucket_name = GCS_BUCKET_NAME

+ 148 - 0
backend/open_webui/utils/code_interpreter.py

@@ -0,0 +1,148 @@
+import asyncio
+import json
+import uuid
+import websockets
+import requests
+from urllib.parse import urljoin
+
+
+async def execute_code_jupyter(
+    jupyter_url, code, token=None, password=None, timeout=10
+):
+    """
+    Executes Python code in a Jupyter kernel.
+    Supports authentication with a token or password.
+    :param jupyter_url: Jupyter server URL (e.g., "http://localhost:8888")
+    :param code: Code to execute
+    :param token: Jupyter authentication token (optional)
+    :param password: Jupyter password (optional)
+    :param timeout: WebSocket timeout in seconds (default: 10s)
+    :return: Dictionary with stdout, stderr, and result
+             - Images are prefixed with "base64:image/png," and separated by newlines if multiple.
+    """
+    session = requests.Session()  # Maintain cookies
+    headers = {}  # Headers for requests
+
+    # Authenticate using password
+    if password and not token:
+        try:
+            login_url = urljoin(jupyter_url, "/login")
+            response = session.get(login_url)
+            response.raise_for_status()
+            xsrf_token = session.cookies.get("_xsrf")
+            if not xsrf_token:
+                raise ValueError("Failed to fetch _xsrf token")
+
+            login_data = {"_xsrf": xsrf_token, "password": password}
+            login_response = session.post(
+                login_url, data=login_data, cookies=session.cookies
+            )
+            login_response.raise_for_status()
+            headers["X-XSRFToken"] = xsrf_token
+        except Exception as e:
+            return {
+                "stdout": "",
+                "stderr": f"Authentication Error: {str(e)}",
+                "result": "",
+            }
+
+    # Construct API URLs with authentication token if provided
+    params = f"?token={token}" if token else ""
+    kernel_url = urljoin(jupyter_url, f"/api/kernels{params}")
+
+    try:
+        response = session.post(kernel_url, headers=headers, cookies=session.cookies)
+        response.raise_for_status()
+        kernel_id = response.json()["id"]
+
+        websocket_url = urljoin(
+            jupyter_url.replace("http", "ws"),
+            f"/api/kernels/{kernel_id}/channels{params}",
+        )
+
+        ws_headers = {}
+        if password and not token:
+            ws_headers["X-XSRFToken"] = session.cookies.get("_xsrf")
+            cookies = {name: value for name, value in session.cookies.items()}
+            ws_headers["Cookie"] = "; ".join(
+                [f"{name}={value}" for name, value in cookies.items()]
+            )
+
+        async with websockets.connect(
+            websocket_url, additional_headers=ws_headers
+        ) as ws:
+            msg_id = str(uuid.uuid4())
+            execute_request = {
+                "header": {
+                    "msg_id": msg_id,
+                    "msg_type": "execute_request",
+                    "username": "user",
+                    "session": str(uuid.uuid4()),
+                    "date": "",
+                    "version": "5.3",
+                },
+                "parent_header": {},
+                "metadata": {},
+                "content": {
+                    "code": code,
+                    "silent": False,
+                    "store_history": True,
+                    "user_expressions": {},
+                    "allow_stdin": False,
+                    "stop_on_error": True,
+                },
+                "channel": "shell",
+            }
+            await ws.send(json.dumps(execute_request))
+
+            stdout, stderr, result = "", "", []
+
+            while True:
+                try:
+                    message = await asyncio.wait_for(ws.recv(), timeout)
+                    message_data = json.loads(message)
+                    if message_data.get("parent_header", {}).get("msg_id") == msg_id:
+                        msg_type = message_data.get("msg_type")
+
+                        if msg_type == "stream":
+                            if message_data["content"]["name"] == "stdout":
+                                stdout += message_data["content"]["text"]
+                            elif message_data["content"]["name"] == "stderr":
+                                stderr += message_data["content"]["text"]
+
+                        elif msg_type in ("execute_result", "display_data"):
+                            data = message_data["content"]["data"]
+                            if "image/png" in data:
+                                result.append(
+                                    f"data:image/png;base64,{data['image/png']}"
+                                )
+                            elif "text/plain" in data:
+                                result.append(data["text/plain"])
+
+                        elif msg_type == "error":
+                            stderr += "\n".join(message_data["content"]["traceback"])
+
+                        elif (
+                            msg_type == "status"
+                            and message_data["content"]["execution_state"] == "idle"
+                        ):
+                            break
+
+                except asyncio.TimeoutError:
+                    stderr += "\nExecution timed out."
+                    break
+
+    except Exception as e:
+        return {"stdout": "", "stderr": f"Error: {str(e)}", "result": ""}
+
+    finally:
+        if kernel_id:
+            requests.delete(
+                f"{kernel_url}/{kernel_id}", headers=headers, cookies=session.cookies
+            )
+
+    return {
+        "stdout": stdout.strip(),
+        "stderr": stderr.strip(),
+        "result": "\n".join(result).strip() if result else "",
+    }

+ 86 - 10
backend/open_webui/utils/middleware.py

@@ -72,7 +72,7 @@ from open_webui.utils.filter import (
     get_sorted_filter_ids,
     get_sorted_filter_ids,
     process_filter_functions,
     process_filter_functions,
 )
 )
-
+from open_webui.utils.code_interpreter import execute_code_jupyter
 
 
 from open_webui.tasks import create_task
 from open_webui.tasks import create_task
 
 
@@ -684,7 +684,12 @@ async def process_chat_payload(request, form_data, metadata, user, model):
 
 
         if "code_interpreter" in features and features["code_interpreter"]:
         if "code_interpreter" in features and features["code_interpreter"]:
             form_data["messages"] = add_or_update_user_message(
             form_data["messages"] = add_or_update_user_message(
-                DEFAULT_CODE_INTERPRETER_PROMPT, form_data["messages"]
+                (
+                    request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE
+                    if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE != ""
+                    else DEFAULT_CODE_INTERPRETER_PROMPT
+                ),
+                form_data["messages"],
             )
             )
 
 
     try:
     try:
@@ -1639,21 +1644,60 @@ async def process_chat_response(
                         content_blocks[-1]["type"] == "code_interpreter"
                         content_blocks[-1]["type"] == "code_interpreter"
                         and retries < MAX_RETRIES
                         and retries < MAX_RETRIES
                     ):
                     ):
+                        await event_emitter(
+                            {
+                                "type": "chat:completion",
+                                "data": {
+                                    "content": serialize_content_blocks(content_blocks),
+                                },
+                            }
+                        )
+
                         retries += 1
                         retries += 1
                         log.debug(f"Attempt count: {retries}")
                         log.debug(f"Attempt count: {retries}")
 
 
                         output = ""
                         output = ""
                         try:
                         try:
                             if content_blocks[-1]["attributes"].get("type") == "code":
                             if content_blocks[-1]["attributes"].get("type") == "code":
-                                output = await event_caller(
-                                    {
-                                        "type": "execute:python",
-                                        "data": {
-                                            "id": str(uuid4()),
-                                            "code": content_blocks[-1]["content"],
-                                        },
+                                code = content_blocks[-1]["content"]
+
+                                if (
+                                    request.app.state.config.CODE_INTERPRETER_ENGINE
+                                    == "pyodide"
+                                ):
+                                    output = await event_caller(
+                                        {
+                                            "type": "execute:python",
+                                            "data": {
+                                                "id": str(uuid4()),
+                                                "code": code,
+                                            },
+                                        }
+                                    )
+                                elif (
+                                    request.app.state.config.CODE_INTERPRETER_ENGINE
+                                    == "jupyter"
+                                ):
+                                    output = await execute_code_jupyter(
+                                        request.app.state.config.CODE_INTERPRETER_JUPYTER_URL,
+                                        code,
+                                        (
+                                            request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN
+                                            if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH
+                                            == "token"
+                                            else None
+                                        ),
+                                        (
+                                            request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD
+                                            if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH
+                                            == "password"
+                                            else None
+                                        ),
+                                    )
+                                else:
+                                    output = {
+                                        "stdout": "Code interpreter engine not configured."
                                     }
                                     }
-                                )
 
 
                                 if isinstance(output, dict):
                                 if isinstance(output, dict):
                                     stdout = output.get("stdout", "")
                                     stdout = output.get("stdout", "")
@@ -1687,6 +1731,38 @@ async def process_chat_response(
                                                 )
                                                 )
 
 
                                         output["stdout"] = "\n".join(stdoutLines)
                                         output["stdout"] = "\n".join(stdoutLines)
+
+                                    result = output.get("result", "")
+
+                                    if result:
+                                        resultLines = result.split("\n")
+                                        for idx, line in enumerate(resultLines):
+                                            if "data:image/png;base64" in line:
+                                                id = str(uuid4())
+
+                                                # ensure the path exists
+                                                os.makedirs(
+                                                    os.path.join(CACHE_DIR, "images"),
+                                                    exist_ok=True,
+                                                )
+
+                                                image_path = os.path.join(
+                                                    CACHE_DIR,
+                                                    f"images/{id}.png",
+                                                )
+
+                                                with open(image_path, "wb") as f:
+                                                    f.write(
+                                                        base64.b64decode(
+                                                            line.split(",")[1]
+                                                        )
+                                                    )
+
+                                                resultLines[idx] = (
+                                                    f"![Output Image {idx}](/cache/images/{id}.png)"
+                                                )
+
+                                        output["result"] = "\n".join(resultLines)
                         except Exception as e:
                         except Exception as e:
                             output = str(e)
                             output = str(e)
 
 

+ 1 - 1
backend/open_webui/utils/misc.py

@@ -245,7 +245,7 @@ def get_gravatar_url(email):
 
 
 
 
 def calculate_sha256(file_path, chunk_size):
 def calculate_sha256(file_path, chunk_size):
-    #Compute SHA-256 hash of a file efficiently in chunks
+    # Compute SHA-256 hash of a file efficiently in chunks
     sha256 = hashlib.sha256()
     sha256 = hashlib.sha256()
     with open(file_path, "rb") as f:
     with open(file_path, "rb") as f:
         while chunk := f.read(chunk_size):
         while chunk := f.read(chunk_size):

+ 14 - 5
backend/open_webui/utils/oauth.py

@@ -142,13 +142,17 @@ class OAuthManager:
         log.debug(f"Oauth Groups claim: {oauth_claim}")
         log.debug(f"Oauth Groups claim: {oauth_claim}")
         log.debug(f"User oauth groups: {user_oauth_groups}")
         log.debug(f"User oauth groups: {user_oauth_groups}")
         log.debug(f"User's current groups: {[g.name for g in user_current_groups]}")
         log.debug(f"User's current groups: {[g.name for g in user_current_groups]}")
-        log.debug(f"All groups available in OpenWebUI: {[g.name for g in all_available_groups]}")
+        log.debug(
+            f"All groups available in OpenWebUI: {[g.name for g in all_available_groups]}"
+        )
 
 
         # Remove groups that user is no longer a part of
         # Remove groups that user is no longer a part of
         for group_model in user_current_groups:
         for group_model in user_current_groups:
             if group_model.name not in user_oauth_groups:
             if group_model.name not in user_oauth_groups:
                 # Remove group from user
                 # Remove group from user
-                log.debug(f"Removing user from group {group_model.name} as it is no longer in their oauth groups")
+                log.debug(
+                    f"Removing user from group {group_model.name} as it is no longer in their oauth groups"
+                )
 
 
                 user_ids = group_model.user_ids
                 user_ids = group_model.user_ids
                 user_ids = [i for i in user_ids if i != user.id]
                 user_ids = [i for i in user_ids if i != user.id]
@@ -174,7 +178,9 @@ class OAuthManager:
                 gm.name == group_model.name for gm in user_current_groups
                 gm.name == group_model.name for gm in user_current_groups
             ):
             ):
                 # Add user to group
                 # Add user to group
-                log.debug(f"Adding user to group {group_model.name} as it was found in their oauth groups")
+                log.debug(
+                    f"Adding user to group {group_model.name} as it was found in their oauth groups"
+                )
 
 
                 user_ids = group_model.user_ids
                 user_ids = group_model.user_ids
                 user_ids.append(user.id)
                 user_ids.append(user.id)
@@ -289,7 +295,9 @@ class OAuthManager:
                                     base64_encoded_picture = base64.b64encode(
                                     base64_encoded_picture = base64.b64encode(
                                         picture
                                         picture
                                     ).decode("utf-8")
                                     ).decode("utf-8")
-                                    guessed_mime_type = mimetypes.guess_type(picture_url)[0]
+                                    guessed_mime_type = mimetypes.guess_type(
+                                        picture_url
+                                    )[0]
                                     if guessed_mime_type is None:
                                     if guessed_mime_type is None:
                                         # assume JPG, browsers are tolerant enough of image formats
                                         # assume JPG, browsers are tolerant enough of image formats
                                         guessed_mime_type = "image/jpeg"
                                         guessed_mime_type = "image/jpeg"
@@ -307,7 +315,8 @@ class OAuthManager:
                 username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM
                 username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM
 
 
                 name = user_data.get(username_claim)
                 name = user_data.get(username_claim)
-                if not isinstance(name, str):
+                if not name:
+                    log.warning("Username claim is missing, using email as name")
                     name = email
                     name = email
 
 
                 role = self.get_user_role(None, user_data)
                 role = self.get_user_role(None, user_data)

+ 6 - 6
backend/open_webui/utils/payload.py

@@ -14,6 +14,12 @@ def apply_model_system_prompt_to_body(
     if not system:
     if not system:
         return form_data
         return form_data
 
 
+    # Metadata (WebUI Usage)
+    if metadata:
+        variables = metadata.get("variables", {})
+        if variables:
+            system = prompt_variables_template(system, variables)
+
     # Legacy (API Usage)
     # Legacy (API Usage)
     if user:
     if user:
         template_params = {
         template_params = {
@@ -25,12 +31,6 @@ def apply_model_system_prompt_to_body(
 
 
     system = prompt_template(system, **template_params)
     system = prompt_template(system, **template_params)
 
 
-    # Metadata (WebUI Usage)
-    if metadata:
-        variables = metadata.get("variables", {})
-        if variables:
-            system = prompt_variables_template(system, variables)
-
     form_data["messages"] = add_or_update_system_message(
     form_data["messages"] = add_or_update_system_message(
         system, form_data.get("messages", [])
         system, form_data.get("messages", [])
     )
     )

+ 7 - 5
backend/open_webui/utils/pdf_generator.py

@@ -2,6 +2,7 @@ from datetime import datetime
 from io import BytesIO
 from io import BytesIO
 from pathlib import Path
 from pathlib import Path
 from typing import Dict, Any, List
 from typing import Dict, Any, List
+from html import escape
 
 
 from markdown import markdown
 from markdown import markdown
 
 
@@ -41,13 +42,13 @@ class PDFGenerator:
 
 
     def _build_html_message(self, message: Dict[str, Any]) -> str:
     def _build_html_message(self, message: Dict[str, Any]) -> str:
         """Build HTML for a single message."""
         """Build HTML for a single message."""
-        role = message.get("role", "user")
-        content = message.get("content", "")
+        role = escape(message.get("role", "user"))
+        content = escape(message.get("content", ""))
         timestamp = message.get("timestamp")
         timestamp = message.get("timestamp")
 
 
-        model = message.get("model") if role == "assistant" else ""
+        model = escape(message.get("model") if role == "assistant" else "")
 
 
-        date_str = self.format_timestamp(timestamp) if timestamp else ""
+        date_str = escape(self.format_timestamp(timestamp) if timestamp else "")
 
 
         # extends pymdownx extension to convert markdown to html.
         # extends pymdownx extension to convert markdown to html.
         # - https://facelessuser.github.io/pymdown-extensions/usage_notes/
         # - https://facelessuser.github.io/pymdown-extensions/usage_notes/
@@ -76,6 +77,7 @@ class PDFGenerator:
 
 
     def _generate_html_body(self) -> str:
     def _generate_html_body(self) -> str:
         """Generate the full HTML body for the PDF."""
         """Generate the full HTML body for the PDF."""
+        escaped_title = escape(self.form_data.title)
         return f"""
         return f"""
         <html>
         <html>
             <head>
             <head>
@@ -84,7 +86,7 @@ class PDFGenerator:
             <body>
             <body>
             <div>
             <div>
                 <div>
                 <div>
-                    <h2>{self.form_data.title}</h2>
+                    <h2>{escaped_title}</h2>
                     {self.messages_html}
                     {self.messages_html}
                 </div>
                 </div>
             </div>
             </div>

+ 3 - 1
backend/open_webui/utils/response.py

@@ -73,7 +73,9 @@ async def convert_streaming_response_ollama_to_openai(ollama_streaming_response)
                     "type": "function",
                     "type": "function",
                     "function": {
                     "function": {
                         "name": tool_call.get("function", {}).get("name", ""),
                         "name": tool_call.get("function", {}).get("name", ""),
-                        "arguments": f"{tool_call.get('function', {}).get('arguments', {})}",
+                        "arguments": json.dumps(
+                            tool_call.get("function", {}).get("arguments", {})
+                        ),
                     },
                     },
                 }
                 }
                 openai_tool_calls.append(openai_tool_call)
                 openai_tool_calls.append(openai_tool_call)

+ 1 - 1
backend/requirements.txt

@@ -91,7 +91,7 @@ pytube==15.0.0
 
 
 extract_msg
 extract_msg
 pydub
 pydub
-duckduckgo-search~=7.3.0
+duckduckgo-search~=7.3.2
 
 
 ## Google Drive
 ## Google Drive
 google-api-python-client
 google-api-python-client

+ 1 - 1
pyproject.toml

@@ -98,7 +98,7 @@ dependencies = [
 
 
     "extract_msg",
     "extract_msg",
     "pydub",
     "pydub",
-    "duckduckgo-search~=7.3.0",
+    "duckduckgo-search~=7.3.2",
 
 
     "google-api-python-client",
     "google-api-python-client",
     "google-auth-httplib2",
     "google-auth-httplib2",

+ 114 - 0
src/lib/apis/configs/index.ts

@@ -58,6 +58,120 @@ export const exportConfig = async (token: string) => {
 	return res;
 	return res;
 };
 };
 
 
+export const getDirectConnectionsConfig = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_connections`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const setDirectConnectionsConfig = async (token: string, config: object) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_connections`, {
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			...config
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const getCodeInterpreterConfig = async (token: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/code_interpreter`, {
+		method: 'GET',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
+export const setCodeInterpreterConfig = async (token: string, config: object) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/configs/code_interpreter`, {
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/json',
+			Authorization: `Bearer ${token}`
+		},
+		body: JSON.stringify({
+			...config
+		})
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			console.log(err);
+			error = err.detail;
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const getModelsConfig = async (token: string) => {
 export const getModelsConfig = async (token: string) => {
 	let error = null;
 	let error = null;
 
 

+ 97 - 1
src/lib/apis/index.ts

@@ -1,6 +1,11 @@
 import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
 import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
+import { getOpenAIModelsDirect } from './openai';
 
 
-export const getModels = async (token: string = '', base: boolean = false) => {
+export const getModels = async (
+	token: string = '',
+	connections: object | null = null,
+	base: boolean = false
+) => {
 	let error = null;
 	let error = null;
 	const res = await fetch(`${WEBUI_BASE_URL}/api/models${base ? '/base' : ''}`, {
 	const res = await fetch(`${WEBUI_BASE_URL}/api/models${base ? '/base' : ''}`, {
 		method: 'GET',
 		method: 'GET',
@@ -25,6 +30,97 @@ export const getModels = async (token: string = '', base: boolean = false) => {
 	}
 	}
 
 
 	let models = res?.data ?? [];
 	let models = res?.data ?? [];
+
+	if (connections && !base) {
+		let localModels = [];
+
+		if (connections) {
+			const OPENAI_API_BASE_URLS = connections.OPENAI_API_BASE_URLS;
+			const OPENAI_API_KEYS = connections.OPENAI_API_KEYS;
+			const OPENAI_API_CONFIGS = connections.OPENAI_API_CONFIGS;
+
+			const requests = [];
+			for (const idx in OPENAI_API_BASE_URLS) {
+				const url = OPENAI_API_BASE_URLS[idx];
+
+				if (idx.toString() in OPENAI_API_CONFIGS) {
+					const apiConfig = OPENAI_API_CONFIGS[idx.toString()] ?? {};
+
+					const enable = apiConfig?.enable ?? true;
+					const modelIds = apiConfig?.model_ids ?? [];
+
+					if (enable) {
+						if (modelIds.length > 0) {
+							const modelList = {
+								object: 'list',
+								data: modelIds.map((modelId) => ({
+									id: modelId,
+									name: modelId,
+									owned_by: 'openai',
+									openai: { id: modelId },
+									urlIdx: idx
+								}))
+							};
+
+							requests.push(
+								(async () => {
+									return modelList;
+								})()
+							);
+						} else {
+							requests.push(getOpenAIModelsDirect(url, OPENAI_API_KEYS[idx]));
+						}
+					} else {
+						requests.push(
+							(async () => {
+								return {
+									object: 'list',
+									data: [],
+									urlIdx: idx
+								};
+							})()
+						);
+					}
+				}
+			}
+
+			const responses = await Promise.all(requests);
+
+			for (const idx in responses) {
+				const response = responses[idx];
+				const apiConfig = OPENAI_API_CONFIGS[idx.toString()] ?? {};
+
+				let models = Array.isArray(response) ? response : (response?.data ?? []);
+				models = models.map((model) => ({ ...model, openai: { id: model.id }, urlIdx: idx }));
+
+				const prefixId = apiConfig.prefix_id;
+				if (prefixId) {
+					for (const model of models) {
+						model.id = `${prefixId}.${model.id}`;
+					}
+				}
+
+				localModels = localModels.concat(models);
+			}
+		}
+
+		models = models.concat(
+			localModels.map((model) => ({
+				...model,
+				name: model?.name ?? model?.id,
+				direct: true
+			}))
+		);
+
+		// Remove duplicates
+		const modelsMap = {};
+		for (const model of models) {
+			modelsMap[model.id] = model;
+		}
+
+		models = Object.values(modelsMap);
+	}
+
 	return models;
 	return models;
 };
 };
 
 

+ 78 - 22
src/lib/apis/openai/index.ts

@@ -208,6 +208,33 @@ export const updateOpenAIKeys = async (token: string = '', keys: string[]) => {
 	return res.OPENAI_API_KEYS;
 	return res.OPENAI_API_KEYS;
 };
 };
 
 
+export const getOpenAIModelsDirect = async (url: string, key: string) => {
+	let error = null;
+
+	const res = await fetch(`${url}/models`, {
+		method: 'GET',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			...(key && { authorization: `Bearer ${key}` })
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.catch((err) => {
+			error = `OpenAI: ${err?.error?.message ?? 'Network Problem'}`;
+			return [];
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const getOpenAIModels = async (token: string, urlIdx?: number) => {
 export const getOpenAIModels = async (token: string, urlIdx?: number) => {
 	let error = null;
 	let error = null;
 
 
@@ -241,33 +268,62 @@ export const getOpenAIModels = async (token: string, urlIdx?: number) => {
 export const verifyOpenAIConnection = async (
 export const verifyOpenAIConnection = async (
 	token: string = '',
 	token: string = '',
 	url: string = 'https://api.openai.com/v1',
 	url: string = 'https://api.openai.com/v1',
-	key: string = ''
+	key: string = '',
+	direct: boolean = false
 ) => {
 ) => {
+	if (!url) {
+		throw 'OpenAI: URL is required';
+	}
+
 	let error = null;
 	let error = null;
+	let res = null;
 
 
-	const res = await fetch(`${OPENAI_API_BASE_URL}/verify`, {
-		method: 'POST',
-		headers: {
-			Accept: 'application/json',
-			Authorization: `Bearer ${token}`,
-			'Content-Type': 'application/json'
-		},
-		body: JSON.stringify({
-			url,
-			key
+	if (direct) {
+		res = await fetch(`${url}/models`, {
+			method: 'GET',
+			headers: {
+				Accept: 'application/json',
+				Authorization: `Bearer ${key}`,
+				'Content-Type': 'application/json'
+			}
 		})
 		})
-	})
-		.then(async (res) => {
-			if (!res.ok) throw await res.json();
-			return res.json();
+			.then(async (res) => {
+				if (!res.ok) throw await res.json();
+				return res.json();
+			})
+			.catch((err) => {
+				error = `OpenAI: ${err?.error?.message ?? 'Network Problem'}`;
+				return [];
+			});
+
+		if (error) {
+			throw error;
+		}
+	} else {
+		res = await fetch(`${OPENAI_API_BASE_URL}/verify`, {
+			method: 'POST',
+			headers: {
+				Accept: 'application/json',
+				Authorization: `Bearer ${token}`,
+				'Content-Type': 'application/json'
+			},
+			body: JSON.stringify({
+				url,
+				key
+			})
 		})
 		})
-		.catch((err) => {
-			error = `OpenAI: ${err?.error?.message ?? 'Network Problem'}`;
-			return [];
-		});
-
-	if (error) {
-		throw error;
+			.then(async (res) => {
+				if (!res.ok) throw await res.json();
+				return res.json();
+			})
+			.catch((err) => {
+				error = `OpenAI: ${err?.error?.message ?? 'Network Problem'}`;
+				return [];
+			});
+
+		if (error) {
+			throw error;
+		}
 	}
 	}
 
 
 	return res;
 	return res;

+ 7 - 3
src/lib/components/admin/Settings/Connections/AddConnectionModal.svelte → src/lib/components/AddConnectionModal.svelte

@@ -20,7 +20,9 @@
 
 
 	export let show = false;
 	export let show = false;
 	export let edit = false;
 	export let edit = false;
+
 	export let ollama = false;
 	export let ollama = false;
+	export let direct = false;
 
 
 	export let connection = null;
 	export let connection = null;
 
 
@@ -46,9 +48,11 @@
 	};
 	};
 
 
 	const verifyOpenAIHandler = async () => {
 	const verifyOpenAIHandler = async () => {
-		const res = await verifyOpenAIConnection(localStorage.token, url, key).catch((error) => {
-			toast.error(`${error}`);
-		});
+		const res = await verifyOpenAIConnection(localStorage.token, url, key, direct).catch(
+			(error) => {
+				toast.error(`${error}`);
+			}
+		);
 
 
 		if (res) {
 		if (res) {
 			toast.success($i18n.t('Server connection verified'));
 			toast.success($i18n.t('Server connection verified'));

+ 2 - 2
src/lib/components/admin/Evaluations/Feedbacks.svelte

@@ -65,7 +65,7 @@
 	};
 	};
 
 
 	const shareHandler = async () => {
 	const shareHandler = async () => {
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 
 
 		// remove snapshot from feedbacks
 		// remove snapshot from feedbacks
 		const feedbacksToShare = feedbacks.map((f) => {
 		const feedbacksToShare = feedbacks.map((f) => {
@@ -266,7 +266,7 @@
 					}}
 					}}
 				>
 				>
 					<div class=" self-center mr-2 font-medium line-clamp-1">
 					<div class=" self-center mr-2 font-medium line-clamp-1">
-						{$i18n.t('Share to OpenWebUI Community')}
+						{$i18n.t('Share to Open WebUI Community')}
 					</div>
 					</div>
 
 
 					<div class=" self-center">
 					<div class=" self-center">

+ 34 - 8
src/lib/components/admin/Functions.svelte

@@ -3,7 +3,7 @@
 	import fileSaver from 'file-saver';
 	import fileSaver from 'file-saver';
 	const { saveAs } = fileSaver;
 	const { saveAs } = fileSaver;
 
 
-	import { WEBUI_NAME, config, functions, models } from '$lib/stores';
+	import { WEBUI_NAME, config, functions, models, settings } from '$lib/stores';
 	import { onMount, getContext, tick } from 'svelte';
 	import { onMount, getContext, tick } from 'svelte';
 
 
 	import { goto } from '$app/navigation';
 	import { goto } from '$app/navigation';
@@ -65,7 +65,7 @@
 			return null;
 			return null;
 		});
 		});
 
 
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 
 
 		const url = 'https://openwebui.com';
 		const url = 'https://openwebui.com';
 
 
@@ -126,7 +126,12 @@
 			toast.success($i18n.t('Function deleted successfully'));
 			toast.success($i18n.t('Function deleted successfully'));
 
 
 			functions.set(await getFunctions(localStorage.token));
 			functions.set(await getFunctions(localStorage.token));
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		}
 		}
 	};
 	};
 
 
@@ -147,7 +152,12 @@
 			}
 			}
 
 
 			functions.set(await getFunctions(localStorage.token));
 			functions.set(await getFunctions(localStorage.token));
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		}
 		}
 	};
 	};
 
 
@@ -359,7 +369,13 @@
 							bind:state={func.is_active}
 							bind:state={func.is_active}
 							on:change={async (e) => {
 							on:change={async (e) => {
 								toggleFunctionById(localStorage.token, func.id);
 								toggleFunctionById(localStorage.token, func.id);
-								models.set(await getModels(localStorage.token));
+								models.set(
+									await getModels(
+										localStorage.token,
+										$config?.features?.enable_direct_connections &&
+											($settings?.directConnections ?? null)
+									)
+								);
 							}}
 							}}
 						/>
 						/>
 					</Tooltip>
 					</Tooltip>
@@ -453,7 +469,7 @@
 {#if $config?.features.enable_community_sharing}
 {#if $config?.features.enable_community_sharing}
 	<div class=" my-16">
 	<div class=" my-16">
 		<div class=" text-xl font-medium mb-1 line-clamp-1">
 		<div class=" text-xl font-medium mb-1 line-clamp-1">
-			{$i18n.t('Made by OpenWebUI Community')}
+			{$i18n.t('Made by Open WebUI Community')}
 		</div>
 		</div>
 
 
 		<a
 		<a
@@ -496,7 +512,12 @@
 	id={selectedFunction?.id ?? null}
 	id={selectedFunction?.id ?? null}
 	on:save={async () => {
 	on:save={async () => {
 		await tick();
 		await tick();
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	}}
 	}}
 />
 />
 
 
@@ -517,7 +538,12 @@
 
 
 			toast.success($i18n.t('Functions imported successfully'));
 			toast.success($i18n.t('Functions imported successfully'));
 			functions.set(await getFunctions(localStorage.token));
 			functions.set(await getFunctions(localStorage.token));
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		};
 		};
 
 
 		reader.readAsText(importFiles[0]);
 		reader.readAsText(importFiles[0]);

+ 36 - 0
src/lib/components/admin/Settings.svelte

@@ -19,6 +19,7 @@
 	import ChartBar from '../icons/ChartBar.svelte';
 	import ChartBar from '../icons/ChartBar.svelte';
 	import DocumentChartBar from '../icons/DocumentChartBar.svelte';
 	import DocumentChartBar from '../icons/DocumentChartBar.svelte';
 	import Evaluations from './Settings/Evaluations.svelte';
 	import Evaluations from './Settings/Evaluations.svelte';
+	import CodeInterpreter from './Settings/CodeInterpreter.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -188,6 +189,32 @@
 			<div class=" self-center">{$i18n.t('Web Search')}</div>
 			<div class=" self-center">{$i18n.t('Web Search')}</div>
 		</button>
 		</button>
 
 
+		<button
+			class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
+			'code-interpreter'
+				? ''
+				: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
+			on:click={() => {
+				selectedTab = 'code-interpreter';
+			}}
+		>
+			<div class=" self-center mr-2">
+				<svg
+					xmlns="http://www.w3.org/2000/svg"
+					viewBox="0 0 16 16"
+					fill="currentColor"
+					class="size-4"
+				>
+					<path
+						fill-rule="evenodd"
+						d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4Zm2.22 1.97a.75.75 0 0 0 0 1.06l.97.97-.97.97a.75.75 0 1 0 1.06 1.06l1.5-1.5a.75.75 0 0 0 0-1.06l-1.5-1.5a.75.75 0 0 0-1.06 0ZM8.75 8.5a.75.75 0 0 0 0 1.5h2.5a.75.75 0 0 0 0-1.5h-2.5Z"
+						clip-rule="evenodd"
+					/>
+				</svg>
+			</div>
+			<div class=" self-center">{$i18n.t('Code Interpreter')}</div>
+		</button>
+
 		<button
 		<button
 			class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 			class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
 			'interface'
 			'interface'
@@ -364,6 +391,15 @@
 					await config.set(await getBackendConfig());
 					await config.set(await getBackendConfig());
 				}}
 				}}
 			/>
 			/>
+		{:else if selectedTab === 'code-interpreter'}
+			<CodeInterpreter
+				saveHandler={async () => {
+					toast.success($i18n.t('Settings saved successfully!'));
+
+					await tick();
+					await config.set(await getBackendConfig());
+				}}
+			/>
 		{:else if selectedTab === 'interface'}
 		{:else if selectedTab === 'interface'}
 			<Interface
 			<Interface
 				on:save={() => {
 				on:save={() => {

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

@@ -10,7 +10,7 @@
 		getModels as _getModels,
 		getModels as _getModels,
 		getVoices as _getVoices
 		getVoices as _getVoices
 	} from '$lib/apis/audio';
 	} from '$lib/apis/audio';
-	import { config } from '$lib/stores';
+	import { config, settings } from '$lib/stores';
 
 
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
 
 
@@ -51,7 +51,10 @@
 		if (TTS_ENGINE === '') {
 		if (TTS_ENGINE === '') {
 			models = [];
 			models = [];
 		} else {
 		} else {
-			const res = await _getModels(localStorage.token).catch((e) => {
+			const res = await _getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			).catch((e) => {
 				toast.error(`${e}`);
 				toast.error(`${e}`);
 			});
 			});
 
 

+ 166 - 0
src/lib/components/admin/Settings/CodeInterpreter.svelte

@@ -0,0 +1,166 @@
+<script lang="ts">
+	import { toast } from 'svelte-sonner';
+	import { onMount, getContext } from 'svelte';
+	import { getCodeInterpreterConfig, setCodeInterpreterConfig } from '$lib/apis/configs';
+
+	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
+
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import Textarea from '$lib/components/common/Textarea.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
+
+	const i18n = getContext('i18n');
+
+	export let saveHandler: Function;
+
+	let config = null;
+
+	let engines = ['pyodide', 'jupyter'];
+
+	const submitHandler = async () => {
+		const res = await setCodeInterpreterConfig(localStorage.token, config);
+	};
+
+	onMount(async () => {
+		const res = await getCodeInterpreterConfig(localStorage.token);
+
+		if (res) {
+			config = res;
+		}
+	});
+</script>
+
+<form
+	class="flex flex-col h-full justify-between space-y-3 text-sm"
+	on:submit|preventDefault={async () => {
+		await submitHandler();
+		saveHandler();
+	}}
+>
+	<div class=" space-y-3 overflow-y-scroll scrollbar-hidden h-full">
+		{#if config}
+			<div>
+				<div class=" mb-1 text-sm font-medium">
+					{$i18n.t('Code Interpreter')}
+				</div>
+
+				<div>
+					<div class=" py-0.5 flex w-full justify-between">
+						<div class=" self-center text-xs font-medium">
+							{$i18n.t('Enable Code Interpreter')}
+						</div>
+
+						<Switch bind:state={config.ENABLE_CODE_INTERPRETER} />
+					</div>
+				</div>
+
+				<div class=" py-0.5 flex w-full justify-between">
+					<div class=" self-center text-xs font-medium">{$i18n.t('Code Interpreter Engine')}</div>
+					<div class="flex items-center relative">
+						<select
+							class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+							bind:value={config.CODE_INTERPRETER_ENGINE}
+							placeholder={$i18n.t('Select a engine')}
+							required
+						>
+							<option disabled selected value="">{$i18n.t('Select a engine')}</option>
+							{#each engines as engine}
+								<option value={engine}>{engine}</option>
+							{/each}
+						</select>
+					</div>
+				</div>
+
+				{#if config.CODE_INTERPRETER_ENGINE === 'jupyter'}
+					<div class="mt-1 flex flex-col gap-1.5 mb-1 w-full">
+						<div class="text-xs font-medium">
+							{$i18n.t('Jupyter URL')}
+						</div>
+
+						<div class="flex w-full">
+							<div class="flex-1">
+								<input
+									class="w-full text-sm py-0.5 placeholder:text-gray-300 dark:placeholder:text-gray-700 bg-transparent outline-none"
+									type="text"
+									placeholder={$i18n.t('Enter Jupyter URL')}
+									bind:value={config.CODE_INTERPRETER_JUPYTER_URL}
+									autocomplete="off"
+								/>
+							</div>
+						</div>
+					</div>
+
+					<div class="mt-1 flex gap-2 mb-1 w-full items-center justify-between">
+						<div class="text-xs font-medium">
+							{$i18n.t('Jupyter Auth')}
+						</div>
+
+						<div>
+							<select
+								class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-left"
+								bind:value={config.CODE_INTERPRETER_JUPYTER_AUTH}
+								placeholder={$i18n.t('Select an auth method')}
+							>
+								<option selected value="">{$i18n.t('None')}</option>
+								<option value="token">{$i18n.t('Token')}</option>
+								<option value="password">{$i18n.t('Password')}</option>
+							</select>
+						</div>
+					</div>
+
+					{#if config.CODE_INTERPRETER_JUPYTER_AUTH}
+						<div class="flex w-full gap-2">
+							<div class="flex-1">
+								{#if config.CODE_INTERPRETER_JUPYTER_AUTH === 'password'}
+									<SensitiveInput
+										type="text"
+										placeholder={$i18n.t('Enter Jupyter Password')}
+										bind:value={config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD}
+										autocomplete="off"
+									/>
+								{:else}
+									<SensitiveInput
+										type="text"
+										placeholder={$i18n.t('Enter Jupyter Token')}
+										bind:value={config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN}
+										autocomplete="off"
+									/>
+								{/if}
+							</div>
+						</div>
+					{/if}
+				{/if}
+			</div>
+
+			<hr class=" dark:border-gray-850 my-2" />
+
+			<div>
+				<div class="py-0.5 w-full">
+					<div class=" mb-2.5 text-xs font-medium">
+						{$i18n.t('Code Interpreter Prompt Template')}
+					</div>
+
+					<Tooltip
+						content={$i18n.t('Leave empty to use the default prompt, or enter a custom prompt')}
+						placement="top-start"
+					>
+						<Textarea
+							bind:value={config.CODE_INTERPRETER_PROMPT_TEMPLATE}
+							placeholder={$i18n.t(
+								'Leave empty to use the default prompt, or enter a custom prompt'
+							)}
+						/>
+					</Tooltip>
+				</div>
+			</div>
+		{/if}
+	</div>
+	<div class="flex justify-end pt-3 text-sm font-medium">
+		<button
+			class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
+			type="submit"
+		>
+			{$i18n.t('Save')}
+		</button>
+	</div>
+</form>

+ 62 - 13
src/lib/components/admin/Settings/Connections.svelte

@@ -7,8 +7,9 @@
 	import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama';
 	import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama';
 	import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai';
 	import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai';
 	import { getModels as _getModels } from '$lib/apis';
 	import { getModels as _getModels } from '$lib/apis';
+	import { getDirectConnectionsConfig, setDirectConnectionsConfig } from '$lib/apis/configs';
 
 
-	import { models, user } from '$lib/stores';
+	import { config, models, settings, user } from '$lib/stores';
 
 
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
@@ -16,13 +17,16 @@
 	import Plus from '$lib/components/icons/Plus.svelte';
 	import Plus from '$lib/components/icons/Plus.svelte';
 
 
 	import OpenAIConnection from './Connections/OpenAIConnection.svelte';
 	import OpenAIConnection from './Connections/OpenAIConnection.svelte';
-	import AddConnectionModal from './Connections/AddConnectionModal.svelte';
+	import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
 	import OllamaConnection from './Connections/OllamaConnection.svelte';
 	import OllamaConnection from './Connections/OllamaConnection.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
 	const getModels = async () => {
 	const getModels = async () => {
-		const models = await _getModels(localStorage.token);
+		const models = await _getModels(
+			localStorage.token,
+			$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+		);
 		return models;
 		return models;
 	};
 	};
 
 
@@ -37,6 +41,8 @@
 	let ENABLE_OPENAI_API: null | boolean = null;
 	let ENABLE_OPENAI_API: null | boolean = null;
 	let ENABLE_OLLAMA_API: null | boolean = null;
 	let ENABLE_OLLAMA_API: null | boolean = null;
 
 
+	let directConnectionsConfig = null;
+
 	let pipelineUrls = {};
 	let pipelineUrls = {};
 	let showAddOpenAIConnectionModal = false;
 	let showAddOpenAIConnectionModal = false;
 	let showAddOllamaConnectionModal = false;
 	let showAddOllamaConnectionModal = false;
@@ -98,6 +104,19 @@
 		}
 		}
 	};
 	};
 
 
+	const updateDirectConnectionsHandler = async () => {
+		const res = await setDirectConnectionsConfig(localStorage.token, directConnectionsConfig).catch(
+			(error) => {
+				toast.error(`${error}`);
+			}
+		);
+
+		if (res) {
+			toast.success($i18n.t('Direct Connections settings updated'));
+			await models.set(await getModels());
+		}
+	};
+
 	const addOpenAIConnectionHandler = async (connection) => {
 	const addOpenAIConnectionHandler = async (connection) => {
 		OPENAI_API_BASE_URLS = [...OPENAI_API_BASE_URLS, connection.url];
 		OPENAI_API_BASE_URLS = [...OPENAI_API_BASE_URLS, connection.url];
 		OPENAI_API_KEYS = [...OPENAI_API_KEYS, connection.key];
 		OPENAI_API_KEYS = [...OPENAI_API_KEYS, connection.key];
@@ -127,6 +146,9 @@
 				})(),
 				})(),
 				(async () => {
 				(async () => {
 					openaiConfig = await getOpenAIConfig(localStorage.token);
 					openaiConfig = await getOpenAIConfig(localStorage.token);
+				})(),
+				(async () => {
+					directConnectionsConfig = await getDirectConnectionsConfig(localStorage.token);
 				})()
 				})()
 			]);
 			]);
 
 
@@ -170,6 +192,14 @@
 			}
 			}
 		}
 		}
 	});
 	});
+
+	const submitHandler = async () => {
+		updateOpenAIHandler();
+		updateOllamaHandler();
+		updateDirectConnectionsHandler();
+
+		dispatch('save');
+	};
 </script>
 </script>
 
 
 <AddConnectionModal
 <AddConnectionModal
@@ -183,17 +213,9 @@
 	onSubmit={addOllamaConnectionHandler}
 	onSubmit={addOllamaConnectionHandler}
 />
 />
 
 
-<form
-	class="flex flex-col h-full justify-between text-sm"
-	on:submit|preventDefault={() => {
-		updateOpenAIHandler();
-		updateOllamaHandler();
-
-		dispatch('save');
-	}}
->
+<form class="flex flex-col h-full justify-between text-sm" on:submit|preventDefault={submitHandler}>
 	<div class=" overflow-y-scroll scrollbar-hidden h-full">
 	<div class=" overflow-y-scroll scrollbar-hidden h-full">
-		{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null}
+		{#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null && directConnectionsConfig !== null}
 			<div class="my-2">
 			<div class="my-2">
 				<div class="mt-2 space-y-2 pr-1.5">
 				<div class="mt-2 space-y-2 pr-1.5">
 					<div class="flex justify-between items-center text-sm">
 					<div class="flex justify-between items-center text-sm">
@@ -334,6 +356,33 @@
 					</div>
 					</div>
 				{/if}
 				{/if}
 			</div>
 			</div>
+
+			<hr class=" border-gray-50 dark:border-gray-850" />
+
+			<div class="pr-1.5 my-2">
+				<div class="flex justify-between items-center text-sm">
+					<div class="  font-medium">{$i18n.t('Direct Connections')}</div>
+
+					<div class="flex items-center">
+						<div class="">
+							<Switch
+								bind:state={directConnectionsConfig.ENABLE_DIRECT_CONNECTIONS}
+								on:change={async () => {
+									updateDirectConnectionsHandler();
+								}}
+							/>
+						</div>
+					</div>
+				</div>
+
+				<div class="mt-1.5">
+					<div class="text-xs text-gray-500">
+						{$i18n.t(
+							'Direct Connections allow users to connect to their own OpenAI compatible API endpoints.'
+						)}
+					</div>
+				</div>
+			</div>
 		{:else}
 		{:else}
 			<div class="flex h-full justify-center">
 			<div class="flex h-full justify-center">
 				<div class="my-auto">
 				<div class="my-auto">

+ 1 - 1
src/lib/components/admin/Settings/Connections/OllamaConnection.svelte

@@ -4,7 +4,7 @@
 
 
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
-	import AddConnectionModal from './AddConnectionModal.svelte';
+	import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
 
 
 	import Cog6 from '$lib/components/icons/Cog6.svelte';
 	import Cog6 from '$lib/components/icons/Cog6.svelte';
 	import Wrench from '$lib/components/icons/Wrench.svelte';
 	import Wrench from '$lib/components/icons/Wrench.svelte';

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

@@ -5,7 +5,8 @@
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
 	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
 	import Cog6 from '$lib/components/icons/Cog6.svelte';
 	import Cog6 from '$lib/components/icons/Cog6.svelte';
-	import AddConnectionModal from './AddConnectionModal.svelte';
+	import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
+
 	import { connect } from 'socket.io-client';
 	import { connect } from 'socket.io-client';
 
 
 	export let onDelete = () => {};
 	export let onDelete = () => {};

+ 39 - 19
src/lib/components/admin/Settings/Evaluations.svelte

@@ -1,6 +1,6 @@
 <script lang="ts">
 <script lang="ts">
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
-	import { models, user } from '$lib/stores';
+	import { models, settings, user, config } from '$lib/stores';
 	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
 	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
 
 
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
@@ -16,49 +16,69 @@
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
-	let config = null;
+	let evaluationConfig = null;
 	let showAddModel = false;
 	let showAddModel = false;
 
 
 	const submitHandler = async () => {
 	const submitHandler = async () => {
-		config = await updateConfig(localStorage.token, config).catch((err) => {
+		evaluationConfig = await updateConfig(localStorage.token, evaluationConfig).catch((err) => {
 			toast.error(err);
 			toast.error(err);
 			return null;
 			return null;
 		});
 		});
 
 
-		if (config) {
+		if (evaluationConfig) {
 			toast.success('Settings saved successfully');
 			toast.success('Settings saved successfully');
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		}
 		}
 	};
 	};
 
 
 	const addModelHandler = async (model) => {
 	const addModelHandler = async (model) => {
-		config.EVALUATION_ARENA_MODELS.push(model);
-		config.EVALUATION_ARENA_MODELS = [...config.EVALUATION_ARENA_MODELS];
+		evaluationConfig.EVALUATION_ARENA_MODELS.push(model);
+		evaluationConfig.EVALUATION_ARENA_MODELS = [...evaluationConfig.EVALUATION_ARENA_MODELS];
 
 
 		await submitHandler();
 		await submitHandler();
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	const editModelHandler = async (model, modelIdx) => {
 	const editModelHandler = async (model, modelIdx) => {
-		config.EVALUATION_ARENA_MODELS[modelIdx] = model;
-		config.EVALUATION_ARENA_MODELS = [...config.EVALUATION_ARENA_MODELS];
+		evaluationConfig.EVALUATION_ARENA_MODELS[modelIdx] = model;
+		evaluationConfig.EVALUATION_ARENA_MODELS = [...evaluationConfig.EVALUATION_ARENA_MODELS];
 
 
 		await submitHandler();
 		await submitHandler();
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	const deleteModelHandler = async (modelIdx) => {
 	const deleteModelHandler = async (modelIdx) => {
-		config.EVALUATION_ARENA_MODELS = config.EVALUATION_ARENA_MODELS.filter(
+		evaluationConfig.EVALUATION_ARENA_MODELS = evaluationConfig.EVALUATION_ARENA_MODELS.filter(
 			(m, mIdx) => mIdx !== modelIdx
 			(m, mIdx) => mIdx !== modelIdx
 		);
 		);
 
 
 		await submitHandler();
 		await submitHandler();
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	onMount(async () => {
 	onMount(async () => {
 		if ($user.role === 'admin') {
 		if ($user.role === 'admin') {
-			config = await getConfig(localStorage.token).catch((err) => {
+			evaluationConfig = await getConfig(localStorage.token).catch((err) => {
 				toast.error(err);
 				toast.error(err);
 				return null;
 				return null;
 			});
 			});
@@ -81,7 +101,7 @@
 	}}
 	}}
 >
 >
 	<div class="overflow-y-scroll scrollbar-hidden h-full">
 	<div class="overflow-y-scroll scrollbar-hidden h-full">
-		{#if config !== null}
+		{#if evaluationConfig !== null}
 			<div class="">
 			<div class="">
 				<div class="text-sm font-medium mb-2">{$i18n.t('General Settings')}</div>
 				<div class="text-sm font-medium mb-2">{$i18n.t('General Settings')}</div>
 
 
@@ -90,12 +110,12 @@
 						<div class=" text-xs font-medium">{$i18n.t('Arena Models')}</div>
 						<div class=" text-xs font-medium">{$i18n.t('Arena Models')}</div>
 
 
 						<Tooltip content={$i18n.t(`Message rating should be enabled to use this feature`)}>
 						<Tooltip content={$i18n.t(`Message rating should be enabled to use this feature`)}>
-							<Switch bind:state={config.ENABLE_EVALUATION_ARENA_MODELS} />
+							<Switch bind:state={evaluationConfig.ENABLE_EVALUATION_ARENA_MODELS} />
 						</Tooltip>
 						</Tooltip>
 					</div>
 					</div>
 				</div>
 				</div>
 
 
-				{#if config.ENABLE_EVALUATION_ARENA_MODELS}
+				{#if evaluationConfig.ENABLE_EVALUATION_ARENA_MODELS}
 					<hr class=" border-gray-50 dark:border-gray-700/10 my-2" />
 					<hr class=" border-gray-50 dark:border-gray-700/10 my-2" />
 
 
 					<div class="flex justify-between items-center mb-2">
 					<div class="flex justify-between items-center mb-2">
@@ -117,8 +137,8 @@
 					</div>
 					</div>
 
 
 					<div class="flex flex-col gap-2">
 					<div class="flex flex-col gap-2">
-						{#if (config?.EVALUATION_ARENA_MODELS ?? []).length > 0}
-							{#each config.EVALUATION_ARENA_MODELS as model, index}
+						{#if (evaluationConfig?.EVALUATION_ARENA_MODELS ?? []).length > 0}
+							{#each evaluationConfig.EVALUATION_ARENA_MODELS as model, index}
 								<Model
 								<Model
 									{model}
 									{model}
 									on:edit={(e) => {
 									on:edit={(e) => {

+ 1 - 1
src/lib/components/admin/Settings/General.svelte

@@ -144,7 +144,7 @@
 							<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
 							<div class="mt-2 text-xs text-gray-400 dark:text-gray-500">
 								<!-- https://docs.openwebui.com/getting-started/advanced-topics/api-endpoints -->
 								<!-- https://docs.openwebui.com/getting-started/advanced-topics/api-endpoints -->
 								<a
 								<a
-									href="https://docs.openwebui.com/getting-started/advanced-topics/api-endpoints"
+									href="https://docs.openwebui.com/getting-started/api-endpoints"
 									target="_blank"
 									target="_blank"
 									class=" text-gray-300 font-medium underline"
 									class=" text-gray-300 font-medium underline"
 								>
 								>

+ 20 - 4
src/lib/components/admin/Settings/Models.svelte

@@ -68,7 +68,7 @@
 
 
 	const init = async () => {
 	const init = async () => {
 		workspaceModels = await getBaseModels(localStorage.token);
 		workspaceModels = await getBaseModels(localStorage.token);
-		baseModels = await getModels(localStorage.token, true);
+		baseModels = await getModels(localStorage.token, null, true);
 
 
 		models = baseModels.map((m) => {
 		models = baseModels.map((m) => {
 			const workspaceModel = workspaceModels.find((wm) => wm.id === m.id);
 			const workspaceModel = workspaceModels.find((wm) => wm.id === m.id);
@@ -111,7 +111,12 @@
 			}
 			}
 		}
 		}
 
 
-		_models.set(await getModels(localStorage.token));
+		_models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 		await init();
 		await init();
 	};
 	};
 
 
@@ -133,7 +138,12 @@
 		}
 		}
 
 
 		// await init();
 		// await init();
-		_models.set(await getModels(localStorage.token));
+		_models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	onMount(async () => {
 	onMount(async () => {
@@ -330,7 +340,13 @@
 									}
 									}
 								}
 								}
 
 
-								await _models.set(await getModels(localStorage.token));
+								await _models.set(
+									await getModels(
+										localStorage.token,
+										$config?.features?.enable_direct_connections &&
+											($settings?.directConnections ?? null)
+									)
+								);
 								init();
 								init();
 							};
 							};
 
 

+ 25 - 5
src/lib/components/admin/Settings/Models/Manage/ManageOllama.svelte

@@ -3,7 +3,7 @@
 	import { getContext, onMount } from 'svelte';
 	import { getContext, onMount } from 'svelte';
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
-	import { WEBUI_NAME, models, MODEL_DOWNLOAD_POOL, user, config } from '$lib/stores';
+	import { WEBUI_NAME, models, MODEL_DOWNLOAD_POOL, user, config, settings } from '$lib/stores';
 	import { splitStream } from '$lib/utils';
 	import { splitStream } from '$lib/utils';
 
 
 	import {
 	import {
@@ -235,7 +235,12 @@
 					})
 					})
 				);
 				);
 
 
-				models.set(await getModels(localStorage.token));
+				models.set(
+					await getModels(
+						localStorage.token,
+						$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+					)
+				);
 			} else {
 			} else {
 				toast.error($i18n.t('Download canceled'));
 				toast.error($i18n.t('Download canceled'));
 			}
 			}
@@ -394,7 +399,12 @@
 		modelTransferring = false;
 		modelTransferring = false;
 		uploadProgress = null;
 		uploadProgress = null;
 
 
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	const deleteModelHandler = async () => {
 	const deleteModelHandler = async () => {
@@ -407,7 +417,12 @@
 		}
 		}
 
 
 		deleteModelTag = '';
 		deleteModelTag = '';
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 	};
 	};
 
 
 	const cancelModelPullHandler = async (model: string) => {
 	const cancelModelPullHandler = async (model: string) => {
@@ -506,7 +521,12 @@
 			}
 			}
 		}
 		}
 
 
-		models.set(await getModels(localStorage.token));
+		models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 
 
 		createModelLoading = false;
 		createModelLoading = false;
 
 

+ 25 - 5
src/lib/components/admin/Settings/Pipelines.svelte

@@ -2,7 +2,7 @@
 	import { v4 as uuidv4 } from 'uuid';
 	import { v4 as uuidv4 } from 'uuid';
 
 
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
-	import { models } from '$lib/stores';
+	import { config, models, settings } from '$lib/stores';
 	import { getContext, onMount, tick } from 'svelte';
 	import { getContext, onMount, tick } from 'svelte';
 	import type { Writable } from 'svelte/store';
 	import type { Writable } from 'svelte/store';
 	import type { i18n as i18nType } from 'i18next';
 	import type { i18n as i18nType } from 'i18next';
@@ -63,7 +63,12 @@
 			if (res) {
 			if (res) {
 				toast.success($i18n.t('Valves updated successfully'));
 				toast.success($i18n.t('Valves updated successfully'));
 				setPipelines();
 				setPipelines();
-				models.set(await getModels(localStorage.token));
+				models.set(
+					await getModels(
+						localStorage.token,
+						$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+					)
+				);
 				saveHandler();
 				saveHandler();
 			}
 			}
 		} else {
 		} else {
@@ -125,7 +130,12 @@
 		if (res) {
 		if (res) {
 			toast.success($i18n.t('Pipeline downloaded successfully'));
 			toast.success($i18n.t('Pipeline downloaded successfully'));
 			setPipelines();
 			setPipelines();
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		}
 		}
 
 
 		downloading = false;
 		downloading = false;
@@ -150,7 +160,12 @@
 			if (res) {
 			if (res) {
 				toast.success($i18n.t('Pipeline downloaded successfully'));
 				toast.success($i18n.t('Pipeline downloaded successfully'));
 				setPipelines();
 				setPipelines();
-				models.set(await getModels(localStorage.token));
+				models.set(
+					await getModels(
+						localStorage.token,
+						$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+					)
+				);
 			}
 			}
 		} else {
 		} else {
 			toast.error($i18n.t('No file selected'));
 			toast.error($i18n.t('No file selected'));
@@ -179,7 +194,12 @@
 		if (res) {
 		if (res) {
 			toast.success($i18n.t('Pipeline deleted successfully'));
 			toast.success($i18n.t('Pipeline deleted successfully'));
 			setPipelines();
 			setPipelines();
-			models.set(await getModels(localStorage.token));
+			models.set(
+				await getModels(
+					localStorage.token,
+					$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+				)
+			);
 		}
 		}
 	};
 	};
 
 

+ 14 - 0
src/lib/components/admin/Settings/WebSearch.svelte

@@ -18,6 +18,7 @@
 		'brave',
 		'brave',
 		'kagi',
 		'kagi',
 		'mojeek',
 		'mojeek',
+		'bocha',
 		'serpstack',
 		'serpstack',
 		'serper',
 		'serper',
 		'serply',
 		'serply',
@@ -52,6 +53,8 @@
 				proxy_url: youtubeProxyUrl
 				proxy_url: youtubeProxyUrl
 			}
 			}
 		});
 		});
+
+		webConfig.search.domain_filter_list = webConfig.search.domain_filter_list.join(', ');
 	};
 	};
 
 
 	onMount(async () => {
 	onMount(async () => {
@@ -193,6 +196,17 @@
 									bind:value={webConfig.search.mojeek_search_api_key}
 									bind:value={webConfig.search.mojeek_search_api_key}
 								/>
 								/>
 							</div>
 							</div>
+						{:else if webConfig.search.engine === 'bocha'}
+							<div>
+								<div class=" self-center text-xs font-medium mb-1">
+									{$i18n.t('Bocha Search API Key')}
+								</div>
+
+								<SensitiveInput
+									placeholder={$i18n.t('Enter Bocha Search API Key')}
+									bind:value={webConfig.search.bocha_search_api_key}
+								/>
+							</div>
 						{:else if webConfig.search.engine === 'serpstack'}
 						{:else if webConfig.search.engine === 'serpstack'}
 							<div>
 							<div>
 								<div class=" self-center text-xs font-medium mb-1">
 								<div class=" self-center text-xs font-medium mb-1">

+ 12 - 9
src/lib/components/chat/Chat.svelte

@@ -1226,7 +1226,7 @@
 			selectedModels = _selectedModels;
 			selectedModels = _selectedModels;
 		}
 		}
 
 
-		if (userPrompt === '') {
+		if (userPrompt === '' && files.length === 0) {
 			toast.error($i18n.t('Please enter a prompt'));
 			toast.error($i18n.t('Please enter a prompt'));
 			return;
 			return;
 		}
 		}
@@ -1478,7 +1478,7 @@
 			params?.stream_response ??
 			params?.stream_response ??
 			true;
 			true;
 
 
-		const messages = [
+		let messages = [
 			params?.system || $settings.system || (responseMessage?.userContext ?? null)
 			params?.system || $settings.system || (responseMessage?.userContext ?? null)
 				? {
 				? {
 						role: 'system',
 						role: 'system',
@@ -1499,8 +1499,9 @@
 				...message,
 				...message,
 				content: removeDetails(message.content, ['reasoning', 'code_interpreter'])
 				content: removeDetails(message.content, ['reasoning', 'code_interpreter'])
 			}))
 			}))
-		]
-			.filter((message) => message?.content?.trim())
+		].filter((message) => message);
+
+		messages = messages
 			.map((message, idx, arr) => ({
 			.map((message, idx, arr) => ({
 				role: message.role,
 				role: message.role,
 				...((message.files?.filter((file) => file.type === 'image').length > 0 ?? false) &&
 				...((message.files?.filter((file) => file.type === 'image').length > 0 ?? false) &&
@@ -1524,7 +1525,8 @@
 					: {
 					: {
 							content: message?.merged?.content ?? message.content
 							content: message?.merged?.content ?? message.content
 						})
 						})
-			}));
+			}))
+			.filter((message) => message?.role === 'user' || message?.content?.trim());
 
 
 		const res = await generateOpenAIChatCompletion(
 		const res = await generateOpenAIChatCompletion(
 			localStorage.token,
 			localStorage.token,
@@ -1556,7 +1558,8 @@
 							? imageGenerationEnabled
 							? imageGenerationEnabled
 							: false,
 							: false,
 					code_interpreter:
 					code_interpreter:
-						$user.role === 'admin' || $user?.permissions?.features?.code_interpreter
+						$config?.features?.enable_code_interpreter &&
+						($user.role === 'admin' || $user?.permissions?.features?.code_interpreter)
 							? codeInterpreterEnabled
 							? codeInterpreterEnabled
 							: false,
 							: false,
 					web_search:
 					web_search:
@@ -1581,7 +1584,7 @@
 					(messages.length == 2 &&
 					(messages.length == 2 &&
 						messages.at(0)?.role === 'system' &&
 						messages.at(0)?.role === 'system' &&
 						messages.at(1)?.role === 'user')) &&
 						messages.at(1)?.role === 'user')) &&
-				selectedModels[0] === model.id
+				(selectedModels[0] === model.id || atSelectedModel !== undefined)
 					? {
 					? {
 							background_tasks: {
 							background_tasks: {
 								title_generation: $settings?.title?.auto ?? true,
 								title_generation: $settings?.title?.auto ?? true,
@@ -2006,7 +2009,7 @@
 									}
 									}
 								}}
 								}}
 								on:submit={async (e) => {
 								on:submit={async (e) => {
-									if (e.detail) {
+									if (e.detail || files.length > 0) {
 										await tick();
 										await tick();
 										submitPrompt(
 										submitPrompt(
 											($settings?.richTextInput ?? true)
 											($settings?.richTextInput ?? true)
@@ -2049,7 +2052,7 @@
 									}
 									}
 								}}
 								}}
 								on:submit={async (e) => {
 								on:submit={async (e) => {
-									if (e.detail) {
+									if (e.detail || files.length > 0) {
 										await tick();
 										await tick();
 										submitPrompt(
 										submitPrompt(
 											($settings?.richTextInput ?? true)
 											($settings?.richTextInput ?? true)

+ 18 - 6
src/lib/components/chat/MessageInput.svelte

@@ -16,7 +16,8 @@
 		showCallOverlay,
 		showCallOverlay,
 		tools,
 		tools,
 		user as _user,
 		user as _user,
-		showControls
+		showControls,
+		TTSWorker
 	} from '$lib/stores';
 	} from '$lib/stores';
 
 
 	import { blobToFile, compressImage, createMessagesList, findWordIndices } from '$lib/utils';
 	import { blobToFile, compressImage, createMessagesList, findWordIndices } from '$lib/utils';
@@ -43,6 +44,7 @@
 	import PhotoSolid from '../icons/PhotoSolid.svelte';
 	import PhotoSolid from '../icons/PhotoSolid.svelte';
 	import Photo from '../icons/Photo.svelte';
 	import Photo from '../icons/Photo.svelte';
 	import CommandLine from '../icons/CommandLine.svelte';
 	import CommandLine from '../icons/CommandLine.svelte';
+	import { KokoroWorker } from '$lib/workers/KokoroWorker';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -638,7 +640,7 @@
 																xmlns="http://www.w3.org/2000/svg"
 																xmlns="http://www.w3.org/2000/svg"
 																viewBox="0 0 20 20"
 																viewBox="0 0 20 20"
 																fill="currentColor"
 																fill="currentColor"
-																class="w-4 h-4"
+																class="size-4"
 															>
 															>
 																<path
 																<path
 																	d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
 																	d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
@@ -1169,7 +1171,7 @@
 													</Tooltip>
 													</Tooltip>
 												{/if}
 												{/if}
 
 
-												{#if $_user.role === 'admin' || $_user?.permissions?.features?.code_interpreter}
+												{#if $config?.features?.enable_code_interpreter && ($_user.role === 'admin' || $_user?.permissions?.features?.code_interpreter)}
 													<Tooltip content={$i18n.t('Execute code for analysis')} placement="top">
 													<Tooltip content={$i18n.t('Execute code for analysis')} placement="top">
 														<button
 														<button
 															on:click|preventDefault={() =>
 															on:click|preventDefault={() =>
@@ -1242,7 +1244,7 @@
 										{/if}
 										{/if}
 
 
 										{#if !history.currentId || history.messages[history.currentId]?.done == true}
 										{#if !history.currentId || history.messages[history.currentId]?.done == true}
-											{#if prompt === ''}
+											{#if prompt === '' && files.length === 0}
 												<div class=" flex items-center">
 												<div class=" flex items-center">
 													<Tooltip content={$i18n.t('Call')}>
 													<Tooltip content={$i18n.t('Call')}>
 														<button
 														<button
@@ -1281,6 +1283,16 @@
 
 
 																	stream = null;
 																	stream = null;
 
 
+																	if (!$TTSWorker) {
+																		await TTSWorker.set(
+																			new KokoroWorker({
+																				dtype: $settings.audio?.tts?.engineConfig?.dtype ?? 'fp32'
+																			})
+																		);
+
+																		await $TTSWorker.init();
+																	}
+
 																	showCallOverlay.set(true);
 																	showCallOverlay.set(true);
 																	showControls.set(true);
 																	showControls.set(true);
 																} catch (err) {
 																} catch (err) {
@@ -1301,13 +1313,13 @@
 													<Tooltip content={$i18n.t('Send message')}>
 													<Tooltip content={$i18n.t('Send message')}>
 														<button
 														<button
 															id="send-message-button"
 															id="send-message-button"
-															class="{prompt !== ''
+															class="{!(prompt === '' && files.length === 0)
 																? webSearchEnabled || ($settings?.webSearch ?? false) === 'always'
 																? webSearchEnabled || ($settings?.webSearch ?? false) === 'always'
 																	? 'bg-blue-500 text-white hover:bg-blue-400 '
 																	? 'bg-blue-500 text-white hover:bg-blue-400 '
 																	: 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
 																	: 'bg-black text-white hover:bg-gray-900 dark:bg-white dark:text-black dark:hover:bg-gray-100 '
 																: 'text-white bg-gray-200 dark:text-gray-900 dark:bg-gray-700 disabled'} transition rounded-full p-1.5 self-center"
 																: 'text-white bg-gray-200 dark:text-gray-900 dark:bg-gray-700 disabled'} transition rounded-full p-1.5 self-center"
 															type="submit"
 															type="submit"
-															disabled={prompt === ''}
+															disabled={prompt === '' && files.length === 0}
 														>
 														>
 															<svg
 															<svg
 																xmlns="http://www.w3.org/2000/svg"
 																xmlns="http://www.w3.org/2000/svg"

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

@@ -1,5 +1,5 @@
 <script lang="ts">
 <script lang="ts">
-	import { config, models, settings, showCallOverlay } from '$lib/stores';
+	import { config, models, settings, showCallOverlay, TTSWorker } from '$lib/stores';
 	import { onMount, tick, getContext, onDestroy, createEventDispatcher } from 'svelte';
 	import { onMount, tick, getContext, onDestroy, createEventDispatcher } from 'svelte';
 
 
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
@@ -12,6 +12,7 @@
 
 
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import VideoInputMenu from './CallOverlay/VideoInputMenu.svelte';
 	import VideoInputMenu from './CallOverlay/VideoInputMenu.svelte';
+	import { KokoroWorker } from '$lib/workers/KokoroWorker';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -459,7 +460,21 @@
 					}
 					}
 				}
 				}
 
 
-				if ($config.audio.tts.engine !== '') {
+				if ($settings.audio?.tts?.engine === 'browser-kokoro') {
+					const blob = await $TTSWorker
+						.generate({
+							text: content,
+							voice: $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice
+						})
+						.catch((error) => {
+							console.error(error);
+							toast.error(`${error}`);
+						});
+
+					if (blob) {
+						audioCache.set(content, new Audio(blob));
+					}
+				} else if ($config.audio.tts.engine !== '') {
 					const res = await synthesizeOpenAISpeech(
 					const res = await synthesizeOpenAISpeech(
 						localStorage.token,
 						localStorage.token,
 						$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
 						$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice

+ 2 - 0
src/lib/components/chat/Messages/Citations.svelte

@@ -122,6 +122,7 @@
 			</div>
 			</div>
 		{:else}
 		{:else}
 			<Collapsible
 			<Collapsible
+				id="collapsible-sources"
 				bind:open={isCollapsibleOpen}
 				bind:open={isCollapsibleOpen}
 				className="w-full max-w-full "
 				className="w-full max-w-full "
 				buttonClassName="w-fit max-w-full"
 				buttonClassName="w-fit max-w-full"
@@ -178,6 +179,7 @@
 					<div class="flex text-xs font-medium flex-wrap">
 					<div class="flex text-xs font-medium flex-wrap">
 						{#each citations as citation, idx}
 						{#each citations as citation, idx}
 							<button
 							<button
+								id={`source-${citation.source.name}`}
 								class="no-toggle outline-none flex dark:text-gray-300 p-1 bg-gray-50 hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 transition rounded-xl max-w-96"
 								class="no-toggle outline-none flex dark:text-gray-300 p-1 bg-gray-50 hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 transition rounded-xl max-w-96"
 								on:click={() => {
 								on:click={() => {
 									showCitationModal = true;
 									showCitationModal = true;

+ 17 - 2
src/lib/components/chat/Messages/CodeBlock.svelte

@@ -5,7 +5,14 @@
 
 
 	import { v4 as uuidv4 } from 'uuid';
 	import { v4 as uuidv4 } from 'uuid';
 
 
-	import { getContext, getAllContexts, onMount, tick, createEventDispatcher } from 'svelte';
+	import {
+		getContext,
+		getAllContexts,
+		onMount,
+		tick,
+		createEventDispatcher,
+		onDestroy
+	} from 'svelte';
 	import { copyToClipboard } from '$lib/utils';
 	import { copyToClipboard } from '$lib/utils';
 
 
 	import 'highlight.js/styles/github-dark.min.css';
 	import 'highlight.js/styles/github-dark.min.css';
@@ -31,6 +38,8 @@
 	export let editorClassName = '';
 	export let editorClassName = '';
 	export let stickyButtonsClassName = 'top-8';
 	export let stickyButtonsClassName = 'top-8';
 
 
+	let pyodideWorker = null;
+
 	let _code = '';
 	let _code = '';
 	$: if (code) {
 	$: if (code) {
 		updateCode();
 		updateCode();
@@ -138,7 +147,7 @@
 
 
 		console.log(packages);
 		console.log(packages);
 
 
-		const pyodideWorker = new PyodideWorker();
+		pyodideWorker = new PyodideWorker();
 
 
 		pyodideWorker.postMessage({
 		pyodideWorker.postMessage({
 			id: id,
 			id: id,
@@ -280,6 +289,12 @@
 			});
 			});
 		}
 		}
 	});
 	});
+
+	onDestroy(() => {
+		if (pyodideWorker) {
+			pyodideWorker.terminate();
+		}
+	});
 </script>
 </script>
 
 
 <div>
 <div>

+ 115 - 63
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -4,12 +4,18 @@
 
 
 	import { createEventDispatcher } from 'svelte';
 	import { createEventDispatcher } from 'svelte';
 	import { onMount, tick, getContext } from 'svelte';
 	import { onMount, tick, getContext } from 'svelte';
+	import type { Writable } from 'svelte/store';
+	import type { i18n as i18nType } from 'i18next';
 
 
 	const i18n = getContext<Writable<i18nType>>('i18n');
 	const i18n = getContext<Writable<i18nType>>('i18n');
 
 
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
 
 
-	import { config, models, settings, user } from '$lib/stores';
+	import { createNewFeedback, getFeedbackById, updateFeedbackById } from '$lib/apis/evaluations';
+	import { getChatById } from '$lib/apis/chats';
+	import { generateTags } from '$lib/apis';
+
+	import { config, models, settings, TTSWorker, user } from '$lib/stores';
 	import { synthesizeOpenAISpeech } from '$lib/apis/audio';
 	import { synthesizeOpenAISpeech } from '$lib/apis/audio';
 	import { imageGenerations } from '$lib/apis/images';
 	import { imageGenerations } from '$lib/apis/images';
 	import {
 	import {
@@ -34,13 +40,8 @@
 	import Error from './Error.svelte';
 	import Error from './Error.svelte';
 	import Citations from './Citations.svelte';
 	import Citations from './Citations.svelte';
 	import CodeExecutions from './CodeExecutions.svelte';
 	import CodeExecutions from './CodeExecutions.svelte';
-
-	import type { Writable } from 'svelte/store';
-	import type { i18n as i18nType } from 'i18next';
 	import ContentRenderer from './ContentRenderer.svelte';
 	import ContentRenderer from './ContentRenderer.svelte';
-	import { createNewFeedback, getFeedbackById, updateFeedbackById } from '$lib/apis/evaluations';
-	import { getChatById } from '$lib/apis/chats';
-	import { generateTags } from '$lib/apis';
+	import { KokoroWorker } from '$lib/workers/KokoroWorker';
 
 
 	interface MessageType {
 	interface MessageType {
 		id: string;
 		id: string;
@@ -193,7 +194,42 @@
 
 
 		speaking = true;
 		speaking = true;
 
 
-		if ($config.audio.tts.engine !== '') {
+		if ($config.audio.tts.engine === '') {
+			let voices = [];
+			const getVoicesLoop = setInterval(() => {
+				voices = speechSynthesis.getVoices();
+				if (voices.length > 0) {
+					clearInterval(getVoicesLoop);
+
+					const voice =
+						voices
+							?.filter(
+								(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
+							)
+							?.at(0) ?? undefined;
+
+					console.log(voice);
+
+					const speak = new SpeechSynthesisUtterance(message.content);
+					speak.rate = $settings.audio?.tts?.playbackRate ?? 1;
+
+					console.log(speak);
+
+					speak.onend = () => {
+						speaking = false;
+						if ($settings.conversationMode) {
+							document.getElementById('voice-input-button')?.click();
+						}
+					};
+
+					if (voice) {
+						speak.voice = voice;
+					}
+
+					speechSynthesis.speak(speak);
+				}
+			}, 100);
+		} else {
 			loadingSpeech = true;
 			loadingSpeech = true;
 
 
 			const messageContentParts: string[] = getMessageContentParts(
 			const messageContentParts: string[] = getMessageContentParts(
@@ -222,67 +258,68 @@
 
 
 			let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
 			let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
 
 
-			for (const [idx, sentence] of messageContentParts.entries()) {
-				const res = await synthesizeOpenAISpeech(
-					localStorage.token,
-					$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
-						? ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
-						: $config?.audio?.tts?.voice,
-					sentence
-				).catch((error) => {
-					console.error(error);
-					toast.error(`${error}`);
+			if ($settings.audio?.tts?.engine === 'browser-kokoro') {
+				if (!$TTSWorker) {
+					await TTSWorker.set(
+						new KokoroWorker({
+							dtype: $settings.audio?.tts?.engineConfig?.dtype ?? 'fp32'
+						})
+					);
 
 
-					speaking = false;
-					loadingSpeech = false;
-				});
-
-				if (res) {
-					const blob = await res.blob();
-					const blobUrl = URL.createObjectURL(blob);
-					const audio = new Audio(blobUrl);
-					audio.playbackRate = $settings.audio?.tts?.playbackRate ?? 1;
-
-					audioParts[idx] = audio;
-					loadingSpeech = false;
-					lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+					await $TTSWorker.init();
 				}
 				}
-			}
-		} else {
-			let voices = [];
-			const getVoicesLoop = setInterval(() => {
-				voices = speechSynthesis.getVoices();
-				if (voices.length > 0) {
-					clearInterval(getVoicesLoop);
 
 
-					const voice =
-						voices
-							?.filter(
-								(v) => v.voiceURI === ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
-							)
-							?.at(0) ?? undefined;
-
-					console.log(voice);
-
-					const speak = new SpeechSynthesisUtterance(message.content);
-					speak.rate = $settings.audio?.tts?.playbackRate ?? 1;
-
-					console.log(speak);
+				for (const [idx, sentence] of messageContentParts.entries()) {
+					const blob = await $TTSWorker
+						.generate({
+							text: sentence,
+							voice: $settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice
+						})
+						.catch((error) => {
+							console.error(error);
+							toast.error(`${error}`);
+
+							speaking = false;
+							loadingSpeech = false;
+						});
+
+					if (blob) {
+						const audio = new Audio(blob);
+						audio.playbackRate = $settings.audio?.tts?.playbackRate ?? 1;
+
+						audioParts[idx] = audio;
+						loadingSpeech = false;
+						lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+					}
+				}
+			} else {
+				for (const [idx, sentence] of messageContentParts.entries()) {
+					const res = await synthesizeOpenAISpeech(
+						localStorage.token,
+						$settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice
+							? ($settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice)
+							: $config?.audio?.tts?.voice,
+						sentence
+					).catch((error) => {
+						console.error(error);
+						toast.error(`${error}`);
 
 
-					speak.onend = () => {
 						speaking = false;
 						speaking = false;
-						if ($settings.conversationMode) {
-							document.getElementById('voice-input-button')?.click();
-						}
-					};
+						loadingSpeech = false;
+					});
 
 
-					if (voice) {
-						speak.voice = voice;
-					}
+					if (res) {
+						const blob = await res.blob();
+						const blobUrl = URL.createObjectURL(blob);
+						const audio = new Audio(blobUrl);
+						audio.playbackRate = $settings.audio?.tts?.playbackRate ?? 1;
 
 
-					speechSynthesis.speak(speak);
+						audioParts[idx] = audio;
+						loadingSpeech = false;
+						lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+					}
 				}
 				}
-			}, 100);
+			}
 		}
 		}
 	};
 	};
 
 
@@ -679,12 +716,27 @@
 										floatingButtons={message?.done}
 										floatingButtons={message?.done}
 										save={!readOnly}
 										save={!readOnly}
 										{model}
 										{model}
-										onSourceClick={(e) => {
+										onSourceClick={async (e) => {
 											console.log(e);
 											console.log(e);
-											const sourceButton = document.getElementById(`source-${e}`);
+											let sourceButton = document.getElementById(`source-${e}`);
+											const sourcesCollapsible = document.getElementById(`collapsible-sources`);
 
 
 											if (sourceButton) {
 											if (sourceButton) {
 												sourceButton.click();
 												sourceButton.click();
+											} else if (sourcesCollapsible) {
+												// Open sources collapsible so we can click the source button
+												sourcesCollapsible.querySelector("div:first-child").dispatchEvent(new PointerEvent('pointerup', {}))
+
+												// Wait for next frame to ensure DOM updates
+												await new Promise(resolve => {
+													requestAnimationFrame(() => {
+														requestAnimationFrame(resolve);
+													});
+												});
+
+												// Try clicking the source button again
+												sourceButton = document.getElementById(`source-${e}`);
+												sourceButton && sourceButton.click();
 											}
 											}
 										}}
 										}}
 										onAddMessages={({ modelId, parentId, messages }) => {
 										onAddMessages={({ modelId, parentId, messages }) => {

+ 207 - 201
src/lib/components/chat/Messages/UserMessage.svelte

@@ -145,274 +145,280 @@
 				</div>
 				</div>
 			{/if}
 			{/if}
 
 
-			{#if edit === true}
-				<div class=" w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 mb-2">
-					<div class="max-h-96 overflow-auto">
-						<textarea
-							id="message-edit-{message.id}"
-							bind:this={messageEditTextAreaElement}
-							class=" bg-transparent outline-none w-full resize-none"
-							bind:value={editedContent}
-							on:input={(e) => {
-								e.target.style.height = '';
-								e.target.style.height = `${e.target.scrollHeight}px`;
-							}}
-							on:keydown={(e) => {
-								if (e.key === 'Escape') {
-									document.getElementById('close-edit-message-button')?.click();
-								}
-
-								const isCmdOrCtrlPressed = e.metaKey || e.ctrlKey;
-								const isEnterPressed = e.key === 'Enter';
-
-								if (isCmdOrCtrlPressed && isEnterPressed) {
-									document.getElementById('confirm-edit-message-button')?.click();
-								}
-							}}
-						/>
-					</div>
+			{#if message.content !== ''}
+				{#if edit === true}
+					<div class=" w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 mb-2">
+						<div class="max-h-96 overflow-auto">
+							<textarea
+								id="message-edit-{message.id}"
+								bind:this={messageEditTextAreaElement}
+								class=" bg-transparent outline-none w-full resize-none"
+								bind:value={editedContent}
+								on:input={(e) => {
+									e.target.style.height = '';
+									e.target.style.height = `${e.target.scrollHeight}px`;
+								}}
+								on:keydown={(e) => {
+									if (e.key === 'Escape') {
+										document.getElementById('close-edit-message-button')?.click();
+									}
 
 
-					<div class=" mt-2 mb-1 flex justify-between text-sm font-medium">
-						<div>
-							<button
-								id="save-edit-message-button"
-								class=" px-4 py-2 bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 border dark:border-gray-700 text-gray-700 dark:text-gray-200 transition rounded-3xl"
-								on:click={() => {
-									editMessageConfirmHandler(false);
+									const isCmdOrCtrlPressed = e.metaKey || e.ctrlKey;
+									const isEnterPressed = e.key === 'Enter';
+
+									if (isCmdOrCtrlPressed && isEnterPressed) {
+										document.getElementById('confirm-edit-message-button')?.click();
+									}
 								}}
 								}}
-							>
-								{$i18n.t('Save')}
-							</button>
+							/>
 						</div>
 						</div>
 
 
-						<div class="flex space-x-1.5">
-							<button
-								id="close-edit-message-button"
-								class="px-4 py-2 bg-white dark:bg-gray-900 hover:bg-gray-100 text-gray-800 dark:text-gray-100 transition rounded-3xl"
-								on:click={() => {
-									cancelEditMessage();
-								}}
-							>
-								{$i18n.t('Cancel')}
-							</button>
-
-							<button
-								id="confirm-edit-message-button"
-								class=" px-4 py-2 bg-gray-900 dark:bg-white hover:bg-gray-850 text-gray-100 dark:text-gray-800 transition rounded-3xl"
-								on:click={() => {
-									editMessageConfirmHandler();
-								}}
-							>
-								{$i18n.t('Send')}
-							</button>
+						<div class=" mt-2 mb-1 flex justify-between text-sm font-medium">
+							<div>
+								<button
+									id="save-edit-message-button"
+									class=" px-4 py-2 bg-gray-50 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 border dark:border-gray-700 text-gray-700 dark:text-gray-200 transition rounded-3xl"
+									on:click={() => {
+										editMessageConfirmHandler(false);
+									}}
+								>
+									{$i18n.t('Save')}
+								</button>
+							</div>
+
+							<div class="flex space-x-1.5">
+								<button
+									id="close-edit-message-button"
+									class="px-4 py-2 bg-white dark:bg-gray-900 hover:bg-gray-100 text-gray-800 dark:text-gray-100 transition rounded-3xl"
+									on:click={() => {
+										cancelEditMessage();
+									}}
+								>
+									{$i18n.t('Cancel')}
+								</button>
+
+								<button
+									id="confirm-edit-message-button"
+									class=" px-4 py-2 bg-gray-900 dark:bg-white hover:bg-gray-850 text-gray-100 dark:text-gray-800 transition rounded-3xl"
+									on:click={() => {
+										editMessageConfirmHandler();
+									}}
+								>
+									{$i18n.t('Send')}
+								</button>
+							</div>
 						</div>
 						</div>
 					</div>
 					</div>
-				</div>
-			{:else}
-				<div class="w-full">
-					<div class="flex {($settings?.chatBubble ?? true) ? 'justify-end pb-1' : 'w-full'}">
-						<div
-							class="rounded-3xl {($settings?.chatBubble ?? true)
-								? `max-w-[90%] px-5 py-2  bg-gray-50 dark:bg-gray-850 ${
-										message.files ? 'rounded-tr-lg' : ''
-									}`
-								: ' w-full'}"
-						>
-							{#if message.content}
-								<Markdown id={message.id} content={message.content} />
-							{/if}
+				{:else}
+					<div class="w-full">
+						<div class="flex {($settings?.chatBubble ?? true) ? 'justify-end pb-1' : 'w-full'}">
+							<div
+								class="rounded-3xl {($settings?.chatBubble ?? true)
+									? `max-w-[90%] px-5 py-2  bg-gray-50 dark:bg-gray-850 ${
+											message.files ? 'rounded-tr-lg' : ''
+										}`
+									: ' w-full'}"
+							>
+								{#if message.content}
+									<Markdown id={message.id} content={message.content} />
+								{/if}
+							</div>
 						</div>
 						</div>
-					</div>
 
 
-					<div
-						class=" flex {($settings?.chatBubble ?? true)
-							? 'justify-end'
-							: ''}  text-gray-600 dark:text-gray-500"
-					>
-						{#if !($settings?.chatBubble ?? true)}
-							{#if siblings.length > 1}
-								<div class="flex self-center" dir="ltr">
-									<button
-										class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
-										on:click={() => {
-											showPreviousMessage(message);
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											fill="none"
-											viewBox="0 0 24 24"
-											stroke="currentColor"
-											stroke-width="2.5"
-											class="size-3.5"
+						<div
+							class=" flex {($settings?.chatBubble ?? true)
+								? 'justify-end'
+								: ''}  text-gray-600 dark:text-gray-500"
+						>
+							{#if !($settings?.chatBubble ?? true)}
+								{#if siblings.length > 1}
+									<div class="flex self-center" dir="ltr">
+										<button
+											class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+											on:click={() => {
+												showPreviousMessage(message);
+											}}
 										>
 										>
-											<path
-												stroke-linecap="round"
-												stroke-linejoin="round"
-												d="M15.75 19.5 8.25 12l7.5-7.5"
-											/>
-										</svg>
-									</button>
-
-									<div class="text-sm tracking-widest font-semibold self-center dark:text-gray-100">
-										{siblings.indexOf(message.id) + 1}/{siblings.length}
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke="currentColor"
+												stroke-width="2.5"
+												class="size-3.5"
+											>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="M15.75 19.5 8.25 12l7.5-7.5"
+												/>
+											</svg>
+										</button>
+
+										<div
+											class="text-sm tracking-widest font-semibold self-center dark:text-gray-100"
+										>
+											{siblings.indexOf(message.id) + 1}/{siblings.length}
+										</div>
+
+										<button
+											class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+											on:click={() => {
+												showNextMessage(message);
+											}}
+										>
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke="currentColor"
+												stroke-width="2.5"
+												class="size-3.5"
+											>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="m8.25 4.5 7.5 7.5-7.5 7.5"
+												/>
+											</svg>
+										</button>
 									</div>
 									</div>
-
+								{/if}
+							{/if}
+							{#if !readOnly}
+								<Tooltip content={$i18n.t('Edit')} placement="bottom">
 									<button
 									<button
-										class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+										class="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 edit-user-message-button"
 										on:click={() => {
 										on:click={() => {
-											showNextMessage(message);
+											editMessageHandler();
 										}}
 										}}
 									>
 									>
 										<svg
 										<svg
 											xmlns="http://www.w3.org/2000/svg"
 											xmlns="http://www.w3.org/2000/svg"
 											fill="none"
 											fill="none"
 											viewBox="0 0 24 24"
 											viewBox="0 0 24 24"
+											stroke-width="2.3"
 											stroke="currentColor"
 											stroke="currentColor"
-											stroke-width="2.5"
-											class="size-3.5"
+											class="w-4 h-4"
 										>
 										>
 											<path
 											<path
 												stroke-linecap="round"
 												stroke-linecap="round"
 												stroke-linejoin="round"
 												stroke-linejoin="round"
-												d="m8.25 4.5 7.5 7.5-7.5 7.5"
+												d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
 											/>
 											/>
 										</svg>
 										</svg>
 									</button>
 									</button>
-								</div>
+								</Tooltip>
 							{/if}
 							{/if}
-						{/if}
-						{#if !readOnly}
-							<Tooltip content={$i18n.t('Edit')} placement="bottom">
-								<button
-									class="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 edit-user-message-button"
-									on:click={() => {
-										editMessageHandler();
-									}}
-								>
-									<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="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
-										/>
-									</svg>
-								</button>
-							</Tooltip>
-						{/if}
 
 
-						<Tooltip content={$i18n.t('Copy')} placement="bottom">
-							<button
-								class="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={() => {
-									copyToClipboard(message.content);
-								}}
-							>
-								<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="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"
-									/>
-								</svg>
-							</button>
-						</Tooltip>
-
-						{#if !isFirstMessage && !readOnly}
-							<Tooltip content={$i18n.t('Delete')} placement="bottom">
+							<Tooltip content={$i18n.t('Copy')} placement="bottom">
 								<button
 								<button
-									class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
+									class="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={() => {
 									on:click={() => {
-										deleteMessageHandler();
+										copyToClipboard(message.content);
 									}}
 									}}
 								>
 								>
 									<svg
 									<svg
 										xmlns="http://www.w3.org/2000/svg"
 										xmlns="http://www.w3.org/2000/svg"
 										fill="none"
 										fill="none"
 										viewBox="0 0 24 24"
 										viewBox="0 0 24 24"
-										stroke-width="2"
+										stroke-width="2.3"
 										stroke="currentColor"
 										stroke="currentColor"
 										class="w-4 h-4"
 										class="w-4 h-4"
 									>
 									>
 										<path
 										<path
 											stroke-linecap="round"
 											stroke-linecap="round"
 											stroke-linejoin="round"
 											stroke-linejoin="round"
-											d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
+											d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"
 										/>
 										/>
 									</svg>
 									</svg>
 								</button>
 								</button>
 							</Tooltip>
 							</Tooltip>
-						{/if}
 
 
-						{#if $settings?.chatBubble ?? true}
-							{#if siblings.length > 1}
-								<div class="flex self-center" dir="ltr">
+							{#if !isFirstMessage && !readOnly}
+								<Tooltip content={$i18n.t('Delete')} placement="bottom">
 									<button
 									<button
-										class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+										class="invisible group-hover:visible p-1 rounded dark:hover:text-white hover:text-black transition"
 										on:click={() => {
 										on:click={() => {
-											showPreviousMessage(message);
+											deleteMessageHandler();
 										}}
 										}}
 									>
 									>
 										<svg
 										<svg
 											xmlns="http://www.w3.org/2000/svg"
 											xmlns="http://www.w3.org/2000/svg"
 											fill="none"
 											fill="none"
 											viewBox="0 0 24 24"
 											viewBox="0 0 24 24"
+											stroke-width="2"
 											stroke="currentColor"
 											stroke="currentColor"
-											stroke-width="2.5"
-											class="size-3.5"
+											class="w-4 h-4"
 										>
 										>
 											<path
 											<path
 												stroke-linecap="round"
 												stroke-linecap="round"
 												stroke-linejoin="round"
 												stroke-linejoin="round"
-												d="M15.75 19.5 8.25 12l7.5-7.5"
+												d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0"
 											/>
 											/>
 										</svg>
 										</svg>
 									</button>
 									</button>
+								</Tooltip>
+							{/if}
 
 
-									<div class="text-sm tracking-widest font-semibold self-center dark:text-gray-100">
-										{siblings.indexOf(message.id) + 1}/{siblings.length}
-									</div>
-
-									<button
-										class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
-										on:click={() => {
-											showNextMessage(message);
-										}}
-									>
-										<svg
-											xmlns="http://www.w3.org/2000/svg"
-											fill="none"
-											viewBox="0 0 24 24"
-											stroke="currentColor"
-											stroke-width="2.5"
-											class="size-3.5"
+							{#if $settings?.chatBubble ?? true}
+								{#if siblings.length > 1}
+									<div class="flex self-center" dir="ltr">
+										<button
+											class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+											on:click={() => {
+												showPreviousMessage(message);
+											}}
 										>
 										>
-											<path
-												stroke-linecap="round"
-												stroke-linejoin="round"
-												d="m8.25 4.5 7.5 7.5-7.5 7.5"
-											/>
-										</svg>
-									</button>
-								</div>
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke="currentColor"
+												stroke-width="2.5"
+												class="size-3.5"
+											>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="M15.75 19.5 8.25 12l7.5-7.5"
+												/>
+											</svg>
+										</button>
+
+										<div
+											class="text-sm tracking-widest font-semibold self-center dark:text-gray-100"
+										>
+											{siblings.indexOf(message.id) + 1}/{siblings.length}
+										</div>
+
+										<button
+											class="self-center p-1 hover:bg-black/5 dark:hover:bg-white/5 dark:hover:text-white hover:text-black rounded-md transition"
+											on:click={() => {
+												showNextMessage(message);
+											}}
+										>
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke="currentColor"
+												stroke-width="2.5"
+												class="size-3.5"
+											>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="m8.25 4.5 7.5 7.5-7.5 7.5"
+												/>
+											</svg>
+										</button>
+									</div>
+								{/if}
 							{/if}
 							{/if}
-						{/if}
+						</div>
 					</div>
 					</div>
-				</div>
+				{/if}
 			{/if}
 			{/if}
 		</div>
 		</div>
 	</div>
 	</div>

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

@@ -12,7 +12,15 @@
 
 
 	import { deleteModel, getOllamaVersion, pullModel } from '$lib/apis/ollama';
 	import { deleteModel, getOllamaVersion, pullModel } from '$lib/apis/ollama';
 
 
-	import { user, MODEL_DOWNLOAD_POOL, models, mobile, temporaryChatEnabled } from '$lib/stores';
+	import {
+		user,
+		MODEL_DOWNLOAD_POOL,
+		models,
+		mobile,
+		temporaryChatEnabled,
+		settings,
+		config
+	} from '$lib/stores';
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
 	import { capitalizeFirstLetter, sanitizeResponseContent, splitStream } from '$lib/utils';
 	import { capitalizeFirstLetter, sanitizeResponseContent, splitStream } from '$lib/utils';
 	import { getModels } from '$lib/apis';
 	import { getModels } from '$lib/apis';
@@ -186,7 +194,12 @@
 					})
 					})
 				);
 				);
 
 
-				models.set(await getModels(localStorage.token));
+				models.set(
+					await getModels(
+						localStorage.token,
+						$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+					)
+				);
 			} else {
 			} else {
 				toast.error($i18n.t('Download canceled'));
 				toast.error($i18n.t('Download canceled'));
 			}
 			}
@@ -358,7 +371,24 @@
 
 
 								<!-- {JSON.stringify(item.info)} -->
 								<!-- {JSON.stringify(item.info)} -->
 
 
-								{#if item.model.owned_by === 'openai'}
+								{#if item.model?.direct}
+									<Tooltip content={`${'Direct'}`}>
+										<div class="translate-y-[1px]">
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												viewBox="0 0 16 16"
+												fill="currentColor"
+												class="size-3"
+											>
+												<path
+													fill-rule="evenodd"
+													d="M2 2.75A.75.75 0 0 1 2.75 2C8.963 2 14 7.037 14 13.25a.75.75 0 0 1-1.5 0c0-5.385-4.365-9.75-9.75-9.75A.75.75 0 0 1 2 2.75Zm0 4.5a.75.75 0 0 1 .75-.75 6.75 6.75 0 0 1 6.75 6.75.75.75 0 0 1-1.5 0C8 10.35 5.65 8 2.75 8A.75.75 0 0 1 2 7.25ZM3.5 11a1.5 1.5 0 1 0 0 3 1.5 1.5 0 0 0 0-3Z"
+													clip-rule="evenodd"
+												/>
+											</svg>
+										</div>
+									</Tooltip>
+								{:else if item.model.owned_by === 'openai'}
 									<Tooltip content={`${'External'}`}>
 									<Tooltip content={`${'External'}`}>
 										<div class="translate-y-[1px]">
 										<div class="translate-y-[1px]">
 											<svg
 											<svg

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

@@ -114,7 +114,7 @@
 							</div>
 							</div>
 						</button>
 						</button>
 					</Menu>
 					</Menu>
-				{:else if $mobile && ($user.role === 'admin' || $user?.permissions.chat?.controls)}
+				{:else if $mobile && ($user.role === 'admin' || $user?.permissions?.chat?.controls)}
 					<Tooltip content={$i18n.t('Controls')}>
 					<Tooltip content={$i18n.t('Controls')}>
 						<button
 						<button
 							class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"
 							class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"
@@ -130,7 +130,7 @@
 					</Tooltip>
 					</Tooltip>
 				{/if}
 				{/if}
 
 
-				{#if !$mobile && ($user.role === 'admin' || $user?.permissions.chat?.controls)}
+				{#if !$mobile && ($user.role === 'admin' || $user?.permissions?.chat?.controls)}
 					<Tooltip content={$i18n.t('Controls')}>
 					<Tooltip content={$i18n.t('Controls')}>
 						<button
 						<button
 							class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"
 							class=" flex cursor-pointer px-2 py-2 rounded-xl hover:bg-gray-50 dark:hover:bg-gray-850 transition"

+ 8 - 2
src/lib/components/chat/Settings/Account.svelte

@@ -3,7 +3,7 @@
 	import { onMount, getContext } from 'svelte';
 	import { onMount, getContext } from 'svelte';
 
 
 	import { user, config, settings } from '$lib/stores';
 	import { user, config, settings } from '$lib/stores';
-	import { updateUserProfile, createAPIKey, getAPIKey } from '$lib/apis/auths';
+	import { updateUserProfile, createAPIKey, getAPIKey, getSessionUser } from '$lib/apis/auths';
 
 
 	import UpdatePassword from './Account/UpdatePassword.svelte';
 	import UpdatePassword from './Account/UpdatePassword.svelte';
 	import { getGravatarUrl } from '$lib/apis/utils';
 	import { getGravatarUrl } from '$lib/apis/utils';
@@ -53,7 +53,13 @@
 		);
 		);
 
 
 		if (updatedUser) {
 		if (updatedUser) {
-			await user.set(updatedUser);
+			// Get Session User Info
+			const sessionUser = await getSessionUser(localStorage.token).catch((error) => {
+				toast.error(`${error}`);
+				return null;
+			});
+
+			await user.set(sessionUser);
 			return true;
 			return true;
 		}
 		}
 		return false;
 		return false;

+ 162 - 16
src/lib/components/chat/Settings/Audio.svelte

@@ -1,11 +1,14 @@
 <script lang="ts">
 <script lang="ts">
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
 	import { createEventDispatcher, onMount, getContext } from 'svelte';
 	import { createEventDispatcher, onMount, getContext } from 'svelte';
+	import { KokoroTTS } from 'kokoro-js';
 
 
 	import { user, settings, config } from '$lib/stores';
 	import { user, settings, config } from '$lib/stores';
 	import { getVoices as _getVoices } from '$lib/apis/audio';
 	import { getVoices as _getVoices } from '$lib/apis/audio';
 
 
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
+	import { round } from '@huggingface/transformers';
+	import Spinner from '$lib/components/common/Spinner.svelte';
 	const dispatch = createEventDispatcher();
 	const dispatch = createEventDispatcher();
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
@@ -20,6 +23,13 @@
 
 
 	let STTEngine = '';
 	let STTEngine = '';
 
 
+	let TTSEngine = '';
+	let TTSEngineConfig = {};
+
+	let TTSModel = null;
+	let TTSModelProgress = null;
+	let TTSModelLoading = false;
+
 	let voices = [];
 	let voices = [];
 	let voice = '';
 	let voice = '';
 
 
@@ -28,23 +38,37 @@
 	const speedOptions = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5];
 	const speedOptions = [2, 1.75, 1.5, 1.25, 1, 0.75, 0.5];
 
 
 	const getVoices = async () => {
 	const getVoices = async () => {
-		if ($config.audio.tts.engine === '') {
-			const getVoicesLoop = setInterval(async () => {
-				voices = await speechSynthesis.getVoices();
+		if (TTSEngine === 'browser-kokoro') {
+			if (!TTSModel) {
+				await loadKokoro();
+			}
 
 
-				// do your loop
-				if (voices.length > 0) {
-					clearInterval(getVoicesLoop);
-				}
-			}, 100);
-		} else {
-			const res = await _getVoices(localStorage.token).catch((e) => {
-				toast.error(`${e}`);
+			voices = Object.entries(TTSModel.voices).map(([key, value]) => {
+				return {
+					id: key,
+					name: value.name,
+					localService: false
+				};
 			});
 			});
-
-			if (res) {
-				console.log(res);
-				voices = res.voices;
+		} else {
+			if ($config.audio.tts.engine === '') {
+				const getVoicesLoop = setInterval(async () => {
+					voices = await speechSynthesis.getVoices();
+
+					// do your loop
+					if (voices.length > 0) {
+						clearInterval(getVoicesLoop);
+					}
+				}, 100);
+			} else {
+				const res = await _getVoices(localStorage.token).catch((e) => {
+					toast.error(`${e}`);
+				});
+
+				if (res) {
+					console.log(res);
+					voices = res.voices;
+				}
 			}
 			}
 		}
 		}
 	};
 	};
@@ -67,6 +91,9 @@
 
 
 		STTEngine = $settings?.audio?.stt?.engine ?? '';
 		STTEngine = $settings?.audio?.stt?.engine ?? '';
 
 
+		TTSEngine = $settings?.audio?.tts?.engine ?? '';
+		TTSEngineConfig = $settings?.audio?.tts?.engineConfig ?? {};
+
 		if ($settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice) {
 		if ($settings?.audio?.tts?.defaultVoice === $config.audio.tts.voice) {
 			voice = $settings?.audio?.tts?.voice ?? $config.audio.tts.voice ?? '';
 			voice = $settings?.audio?.tts?.voice ?? $config.audio.tts.voice ?? '';
 		} else {
 		} else {
@@ -77,6 +104,51 @@
 
 
 		await getVoices();
 		await getVoices();
 	});
 	});
+
+	$: if (TTSEngine && TTSEngineConfig) {
+		onTTSEngineChange();
+	}
+
+	const onTTSEngineChange = async () => {
+		if (TTSEngine === 'browser-kokoro') {
+			await loadKokoro();
+		}
+	};
+
+	const loadKokoro = async () => {
+		if (TTSEngine === 'browser-kokoro') {
+			voices = [];
+
+			if (TTSEngineConfig?.dtype) {
+				TTSModel = null;
+				TTSModelProgress = null;
+				TTSModelLoading = true;
+
+				const model_id = 'onnx-community/Kokoro-82M-v1.0-ONNX';
+
+				TTSModel = await KokoroTTS.from_pretrained(model_id, {
+					dtype: TTSEngineConfig.dtype, // Options: "fp32", "fp16", "q8", "q4", "q4f16"
+					device: !!navigator?.gpu ? 'webgpu' : 'wasm', // Detect WebGPU
+					progress_callback: (e) => {
+						TTSModelProgress = e;
+						console.log(e);
+					}
+				});
+
+				await getVoices();
+
+				// const rawAudio = await tts.generate(inputText, {
+				// 	// Use `tts.list_voices()` to list all available voices
+				// 	voice: voice
+				// });
+
+				// const blobUrl = URL.createObjectURL(await rawAudio.toBlob());
+				// const audio = new Audio(blobUrl);
+
+				// audio.play();
+			}
+		}
+	};
 </script>
 </script>
 
 
 <form
 <form
@@ -88,6 +160,8 @@
 					engine: STTEngine !== '' ? STTEngine : undefined
 					engine: STTEngine !== '' ? STTEngine : undefined
 				},
 				},
 				tts: {
 				tts: {
+					engine: TTSEngine !== '' ? TTSEngine : undefined,
+					engineConfig: TTSEngineConfig,
 					playbackRate: playbackRate,
 					playbackRate: playbackRate,
 					voice: voice !== '' ? voice : undefined,
 					voice: voice !== '' ? voice : undefined,
 					defaultVoice: $config?.audio?.tts?.voice ?? '',
 					defaultVoice: $config?.audio?.tts?.voice ?? '',
@@ -142,6 +216,39 @@
 		<div>
 		<div>
 			<div class=" mb-1 text-sm font-medium">{$i18n.t('TTS Settings')}</div>
 			<div class=" mb-1 text-sm font-medium">{$i18n.t('TTS Settings')}</div>
 
 
+			<div class=" py-0.5 flex w-full justify-between">
+				<div class=" self-center text-xs font-medium">{$i18n.t('Text-to-Speech Engine')}</div>
+				<div class="flex items-center relative">
+					<select
+						class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+						bind:value={TTSEngine}
+						placeholder="Select an engine"
+					>
+						<option value="">{$i18n.t('Default')}</option>
+						<option value="browser-kokoro">{$i18n.t('Kokoro.js (Browser)')}</option>
+					</select>
+				</div>
+			</div>
+
+			{#if TTSEngine === 'browser-kokoro'}
+				<div class=" py-0.5 flex w-full justify-between">
+					<div class=" self-center text-xs font-medium">{$i18n.t('Kokoro.js Dtype')}</div>
+					<div class="flex items-center relative">
+						<select
+							class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+							bind:value={TTSEngineConfig.dtype}
+							placeholder="Select dtype"
+						>
+							<option value="" disabled selected>Select dtype</option>
+							<option value="fp32">fp32</option>
+							<option value="fp16">fp16</option>
+							<option value="q8">q8</option>
+							<option value="q4">q4</option>
+						</select>
+					</div>
+				</div>
+			{/if}
+
 			<div class=" py-0.5 flex w-full justify-between">
 			<div class=" py-0.5 flex w-full justify-between">
 				<div class=" self-center text-xs font-medium">{$i18n.t('Auto-playback response')}</div>
 				<div class=" self-center text-xs font-medium">{$i18n.t('Auto-playback response')}</div>
 
 
@@ -178,7 +285,46 @@
 
 
 		<hr class=" dark:border-gray-850" />
 		<hr class=" dark:border-gray-850" />
 
 
-		{#if $config.audio.tts.engine === ''}
+		{#if TTSEngine === 'browser-kokoro'}
+			{#if TTSModel}
+				<div>
+					<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
+					<div class="flex w-full">
+						<div class="flex-1">
+							<input
+								list="voice-list"
+								class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+								bind:value={voice}
+								placeholder="Select a voice"
+							/>
+
+							<datalist id="voice-list">
+								{#each voices as voice}
+									<option value={voice.id}>{voice.name}</option>
+								{/each}
+							</datalist>
+						</div>
+					</div>
+				</div>
+			{:else}
+				<div>
+					<div class=" mb-2.5 text-sm font-medium flex gap-2 items-center">
+						<Spinner className="size-4" />
+
+						<div class=" text-sm font-medium shimmer">
+							{$i18n.t('Loading Kokoro.js...')}
+							{TTSModelProgress && TTSModelProgress.status === 'progress'
+								? `(${Math.round(TTSModelProgress.progress * 10) / 10}%)`
+								: ''}
+						</div>
+					</div>
+
+					<div class="text-xs text-gray-500">
+						{$i18n.t('Please do not close the settings page while loading the model.')}
+					</div>
+				</div>
+			{/if}
+		{:else if $config.audio.tts.engine === ''}
 			<div>
 			<div>
 				<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
 				<div class=" mb-2.5 text-sm font-medium">{$i18n.t('Set Voice')}</div>
 				<div class="flex w-full">
 				<div class="flex w-full">

+ 152 - 0
src/lib/components/chat/Settings/Connections.svelte

@@ -0,0 +1,152 @@
+<script lang="ts">
+	import { toast } from 'svelte-sonner';
+	import { createEventDispatcher, onMount, getContext, tick } from 'svelte';
+	import { getModels as _getModels } from '$lib/apis';
+
+	const dispatch = createEventDispatcher();
+	const i18n = getContext('i18n');
+
+	import { models, settings, user } from '$lib/stores';
+
+	import Switch from '$lib/components/common/Switch.svelte';
+	import Spinner from '$lib/components/common/Spinner.svelte';
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import Plus from '$lib/components/icons/Plus.svelte';
+	import Connection from './Connections/Connection.svelte';
+
+	import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
+
+	export let saveSettings: Function;
+
+	let config = null;
+
+	let showConnectionModal = false;
+
+	const addConnectionHandler = async (connection) => {
+		config.OPENAI_API_BASE_URLS.push(connection.url);
+		config.OPENAI_API_KEYS.push(connection.key);
+		config.OPENAI_API_CONFIGS[config.OPENAI_API_BASE_URLS.length - 1] = connection.config;
+
+		await updateHandler();
+	};
+
+	const updateHandler = async () => {
+		// Remove trailing slashes
+		config.OPENAI_API_BASE_URLS = config.OPENAI_API_BASE_URLS.map((url) => url.replace(/\/$/, ''));
+
+		// Check if API KEYS length is same than API URLS length
+		if (config.OPENAI_API_KEYS.length !== config.OPENAI_API_BASE_URLS.length) {
+			// if there are more keys than urls, remove the extra keys
+			if (config.OPENAI_API_KEYS.length > config.OPENAI_API_BASE_URLS.length) {
+				config.OPENAI_API_KEYS = config.OPENAI_API_KEYS.slice(
+					0,
+					config.OPENAI_API_BASE_URLS.length
+				);
+			}
+
+			// if there are more urls than keys, add empty keys
+			if (config.OPENAI_API_KEYS.length < config.OPENAI_API_BASE_URLS.length) {
+				const diff = config.OPENAI_API_BASE_URLS.length - config.OPENAI_API_KEYS.length;
+				for (let i = 0; i < diff; i++) {
+					config.OPENAI_API_KEYS.push('');
+				}
+			}
+		}
+
+		await saveSettings({
+			directConnections: config
+		});
+	};
+
+	onMount(async () => {
+		config = $settings?.directConnections ?? {
+			OPENAI_API_BASE_URLS: [],
+			OPENAI_API_KEYS: [],
+			OPENAI_API_CONFIGS: {}
+		};
+	});
+</script>
+
+<AddConnectionModal direct bind:show={showConnectionModal} onSubmit={addConnectionHandler} />
+
+<form
+	class="flex flex-col h-full justify-between text-sm"
+	on:submit|preventDefault={() => {
+		updateHandler();
+	}}
+>
+	<div class=" overflow-y-scroll scrollbar-hidden h-full">
+		{#if config !== null}
+			<div class="">
+				<div class="pr-1.5">
+					<div class="">
+						<div class="flex justify-between items-center mb-0.5">
+							<div class="font-medium">{$i18n.t('Manage Direct Connections')}</div>
+
+							<Tooltip content={$i18n.t(`Add Connection`)}>
+								<button
+									class="px-1"
+									on:click={() => {
+										showConnectionModal = true;
+									}}
+									type="button"
+								>
+									<Plus />
+								</button>
+							</Tooltip>
+						</div>
+
+						<div class="flex flex-col gap-1.5">
+							{#each config?.OPENAI_API_BASE_URLS ?? [] as url, idx}
+								<Connection
+									bind:url
+									bind:key={config.OPENAI_API_KEYS[idx]}
+									bind:config={config.OPENAI_API_CONFIGS[idx]}
+									onSubmit={() => {
+										updateHandler();
+									}}
+									onDelete={() => {
+										config.OPENAI_API_BASE_URLS = config.OPENAI_API_BASE_URLS.filter(
+											(url, urlIdx) => idx !== urlIdx
+										);
+										config.OPENAI_API_KEYS = config.OPENAI_API_KEYS.filter(
+											(key, keyIdx) => idx !== keyIdx
+										);
+
+										let newConfig = {};
+										config.OPENAI_API_BASE_URLS.forEach((url, newIdx) => {
+											newConfig[newIdx] =
+												config.OPENAI_API_CONFIGS[newIdx < idx ? newIdx : newIdx + 1];
+										});
+										config.OPENAI_API_CONFIGS = newConfig;
+									}}
+								/>
+							{/each}
+						</div>
+					</div>
+
+					<div class="my-1.5">
+						<div class="text-xs text-gray-500">
+							{$i18n.t('Connect to your own OpenAI compatible API endpoints.')}
+						</div>
+					</div>
+				</div>
+			</div>
+		{:else}
+			<div class="flex h-full justify-center">
+				<div class="my-auto">
+					<Spinner className="size-6" />
+				</div>
+			</div>
+		{/if}
+	</div>
+
+	<div class="flex justify-end pt-3 text-sm font-medium">
+		<button
+			class="px-3.5 py-1.5 text-sm font-medium bg-black hover:bg-gray-900 text-white dark:bg-white dark:text-black dark:hover:bg-gray-100 transition rounded-full"
+			type="submit"
+		>
+			{$i18n.t('Save')}
+		</button>
+	</div>
+</form>

+ 83 - 0
src/lib/components/chat/Settings/Connections/Connection.svelte

@@ -0,0 +1,83 @@
+<script lang="ts">
+	import { getContext, tick } from 'svelte';
+	const i18n = getContext('i18n');
+
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import SensitiveInput from '$lib/components/common/SensitiveInput.svelte';
+	import Cog6 from '$lib/components/icons/Cog6.svelte';
+	import AddConnectionModal from '$lib/components/AddConnectionModal.svelte';
+
+	export let onDelete = () => {};
+	export let onSubmit = () => {};
+
+	export let pipeline = false;
+
+	export let url = '';
+	export let key = '';
+	export let config = {};
+
+	let showConfigModal = false;
+</script>
+
+<AddConnectionModal
+	edit
+	bind:show={showConfigModal}
+	connection={{
+		url,
+		key,
+		config
+	}}
+	{onDelete}
+	onSubmit={(connection) => {
+		url = connection.url;
+		key = connection.key;
+		config = connection.config;
+		onSubmit(connection);
+	}}
+/>
+
+<div class="flex w-full gap-2 items-center">
+	<Tooltip
+		className="w-full relative"
+		content={$i18n.t(`WebUI will make requests to "{{url}}/chat/completions"`, {
+			url
+		})}
+		placement="top-start"
+	>
+		{#if !(config?.enable ?? true)}
+			<div
+				class="absolute top-0 bottom-0 left-0 right-0 opacity-60 bg-white dark:bg-gray-900 z-10"
+			></div>
+		{/if}
+		<div class="flex w-full">
+			<div class="flex-1 relative">
+				<input
+					class=" outline-none w-full bg-transparent {pipeline ? 'pr-8' : ''}"
+					placeholder={$i18n.t('API Base URL')}
+					bind:value={url}
+					autocomplete="off"
+				/>
+			</div>
+
+			<SensitiveInput
+				inputClassName=" outline-none bg-transparent w-full"
+				placeholder={$i18n.t('API Key')}
+				bind:value={key}
+			/>
+		</div>
+	</Tooltip>
+
+	<div class="flex gap-1">
+		<Tooltip content={$i18n.t('Configure')} className="self-start">
+			<button
+				class="self-center p-1 bg-transparent hover:bg-gray-100 dark:bg-gray-900 dark:hover:bg-gray-850 rounded-lg transition"
+				on:click={() => {
+					showConfigModal = true;
+				}}
+				type="button"
+			>
+				<Cog6 />
+			</button>
+		</Tooltip>
+	</div>
+</div>

+ 44 - 2
src/lib/components/chat/SettingsModal.svelte

@@ -1,7 +1,7 @@
 <script lang="ts">
 <script lang="ts">
 	import { getContext, tick } from 'svelte';
 	import { getContext, tick } from 'svelte';
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
-	import { models, settings, user } from '$lib/stores';
+	import { config, models, settings, user } from '$lib/stores';
 	import { updateUserSettings } from '$lib/apis/users';
 	import { updateUserSettings } from '$lib/apis/users';
 	import { getModels as _getModels } from '$lib/apis';
 	import { getModels as _getModels } from '$lib/apis';
 	import { goto } from '$app/navigation';
 	import { goto } from '$app/navigation';
@@ -17,6 +17,7 @@
 	import Personalization from './Settings/Personalization.svelte';
 	import Personalization from './Settings/Personalization.svelte';
 	import SearchInput from '../layout/Sidebar/SearchInput.svelte';
 	import SearchInput from '../layout/Sidebar/SearchInput.svelte';
 	import Search from '../icons/Search.svelte';
 	import Search from '../icons/Search.svelte';
+	import Connections from './Settings/Connections.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -122,6 +123,11 @@
 				'alwaysonwebsearch'
 				'alwaysonwebsearch'
 			]
 			]
 		},
 		},
+		{
+			id: 'connections',
+			title: 'Connections',
+			keywords: []
+		},
 		{
 		{
 			id: 'personalization',
 			id: 'personalization',
 			title: 'Personalization',
 			title: 'Personalization',
@@ -316,7 +322,10 @@
 	};
 	};
 
 
 	const getModels = async () => {
 	const getModels = async () => {
-		return await _getModels(localStorage.token);
+		return await _getModels(
+			localStorage.token,
+			$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+		);
 	};
 	};
 
 
 	let selectedTab = 'general';
 	let selectedTab = 'general';
@@ -447,6 +456,32 @@
 								</div>
 								</div>
 								<div class=" self-center">{$i18n.t('Interface')}</div>
 								<div class=" self-center">{$i18n.t('Interface')}</div>
 							</button>
 							</button>
+						{:else if tabId === 'connections'}
+							{#if $user.role === 'admin' || ($user.role === 'user' && $config?.features?.enable_direct_connections)}
+								<button
+									class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
+									'connections'
+										? ''
+										: ' text-gray-300 dark:text-gray-600 hover:text-gray-700 dark:hover:text-white'}"
+									on:click={() => {
+										selectedTab = 'connections';
+									}}
+								>
+									<div class=" self-center mr-2">
+										<svg
+											xmlns="http://www.w3.org/2000/svg"
+											viewBox="0 0 16 16"
+											fill="currentColor"
+											class="w-4 h-4"
+										>
+											<path
+												d="M1 9.5A3.5 3.5 0 0 0 4.5 13H12a3 3 0 0 0 .917-5.857 2.503 2.503 0 0 0-3.198-3.019 3.5 3.5 0 0 0-6.628 2.171A3.5 3.5 0 0 0 1 9.5Z"
+											/>
+										</svg>
+									</div>
+									<div class=" self-center">{$i18n.t('Connections')}</div>
+								</button>
+							{/if}
 						{:else if tabId === 'personalization'}
 						{:else if tabId === 'personalization'}
 							<button
 							<button
 								class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
 								class="px-0.5 py-1 min-w-fit rounded-lg flex-1 md:flex-none flex text-left transition {selectedTab ===
@@ -620,6 +655,13 @@
 							toast.success($i18n.t('Settings saved successfully!'));
 							toast.success($i18n.t('Settings saved successfully!'));
 						}}
 						}}
 					/>
 					/>
+				{:else if selectedTab === 'connections'}
+					<Connections
+						saveSettings={async (updated) => {
+							await saveSettings(updated);
+							toast.success($i18n.t('Settings saved successfully!'));
+						}}
+					/>
 				{:else if selectedTab === 'personalization'}
 				{:else if selectedTab === 'personalization'}
 					<Personalization
 					<Personalization
 						{saveSettings}
 						{saveSettings}

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

@@ -30,7 +30,7 @@
 		const _chat = chat.chat;
 		const _chat = chat.chat;
 		console.log('share', _chat);
 		console.log('share', _chat);
 
 
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 		const url = 'https://openwebui.com';
 		const url = 'https://openwebui.com';
 		// const url = 'http://localhost:5173';
 		// const url = 'http://localhost:5173';
 
 
@@ -143,7 +143,7 @@
 										show = false;
 										show = false;
 									}}
 									}}
 								>
 								>
-									{$i18n.t('Share to OpenWebUI Community')}
+									{$i18n.t('Share to Open WebUI Community')}
 								</button>
 								</button>
 							{/if}
 							{/if}
 
 

+ 2 - 1
src/lib/components/common/Collapsible.svelte

@@ -34,6 +34,7 @@
 	import Spinner from './Spinner.svelte';
 	import Spinner from './Spinner.svelte';
 
 
 	export let open = false;
 	export let open = false;
+	export let id = '';
 	export let className = '';
 	export let className = '';
 	export let buttonClassName =
 	export let buttonClassName =
 		'w-fit text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition';
 		'w-fit text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition';
@@ -46,7 +47,7 @@
 	export let hide = false;
 	export let hide = false;
 </script>
 </script>
 
 
-<div class={className}>
+<div id={id} class={className}>
 	{#if title !== null}
 	{#if title !== null}
 		<!-- svelte-ignore a11y-no-static-element-interactions -->
 		<!-- svelte-ignore a11y-no-static-element-interactions -->
 		<!-- svelte-ignore a11y-click-events-have-key-events -->
 		<!-- svelte-ignore a11y-click-events-have-key-events -->

+ 28 - 6
src/lib/components/workspace/Models.svelte

@@ -68,7 +68,12 @@
 			toast.success($i18n.t(`Deleted {{name}}`, { name: model.id }));
 			toast.success($i18n.t(`Deleted {{name}}`, { name: model.id }));
 		}
 		}
 
 
-		await _models.set(await getModels(localStorage.token));
+		await _models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 		models = await getWorkspaceModels(localStorage.token);
 		models = await getWorkspaceModels(localStorage.token);
 	};
 	};
 
 
@@ -82,7 +87,7 @@
 	};
 	};
 
 
 	const shareModelHandler = async (model) => {
 	const shareModelHandler = async (model) => {
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 
 
 		const url = 'https://openwebui.com';
 		const url = 'https://openwebui.com';
 
 
@@ -134,7 +139,12 @@
 			);
 			);
 		}
 		}
 
 
-		await _models.set(await getModels(localStorage.token));
+		await _models.set(
+			await getModels(
+				localStorage.token,
+				$config?.features?.enable_direct_connections && ($settings?.directConnections ?? null)
+			)
+		);
 		models = await getWorkspaceModels(localStorage.token);
 		models = await getWorkspaceModels(localStorage.token);
 	};
 	};
 
 
@@ -371,7 +381,13 @@
 										bind:state={model.is_active}
 										bind:state={model.is_active}
 										on:change={async (e) => {
 										on:change={async (e) => {
 											toggleModelById(localStorage.token, model.id);
 											toggleModelById(localStorage.token, model.id);
-											_models.set(await getModels(localStorage.token));
+											_models.set(
+												await getModels(
+													localStorage.token,
+													$config?.features?.enable_direct_connections &&
+														($settings?.directConnections ?? null)
+												)
+											);
 										}}
 										}}
 									/>
 									/>
 								</Tooltip>
 								</Tooltip>
@@ -417,7 +433,13 @@
 								}
 								}
 							}
 							}
 
 
-							await _models.set(await getModels(localStorage.token));
+							await _models.set(
+								await getModels(
+									localStorage.token,
+									$config?.features?.enable_direct_connections &&
+										($settings?.directConnections ?? null)
+								)
+							);
 							models = await getWorkspaceModels(localStorage.token);
 							models = await getWorkspaceModels(localStorage.token);
 						};
 						};
 
 
@@ -479,7 +501,7 @@
 	{#if $config?.features.enable_community_sharing}
 	{#if $config?.features.enable_community_sharing}
 		<div class=" my-16">
 		<div class=" my-16">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
-				{$i18n.t('Made by OpenWebUI Community')}
+				{$i18n.t('Made by Open WebUI Community')}
 			</div>
 			</div>
 
 
 			<a
 			<a

+ 2 - 2
src/lib/components/workspace/Prompts.svelte

@@ -40,7 +40,7 @@
 	$: filteredItems = prompts.filter((p) => query === '' || p.command.includes(query));
 	$: filteredItems = prompts.filter((p) => query === '' || p.command.includes(query));
 
 
 	const shareHandler = async (prompt) => {
 	const shareHandler = async (prompt) => {
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 
 
 		const url = 'https://openwebui.com';
 		const url = 'https://openwebui.com';
 
 
@@ -319,7 +319,7 @@
 	{#if $config?.features.enable_community_sharing}
 	{#if $config?.features.enable_community_sharing}
 		<div class=" my-16">
 		<div class=" my-16">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
-				{$i18n.t('Made by OpenWebUI Community')}
+				{$i18n.t('Made by Open WebUI Community')}
 			</div>
 			</div>
 
 
 			<a
 			<a

+ 2 - 2
src/lib/components/workspace/Tools.svelte

@@ -65,7 +65,7 @@
 			return null;
 			return null;
 		});
 		});
 
 
-		toast.success($i18n.t('Redirecting you to OpenWebUI Community'));
+		toast.success($i18n.t('Redirecting you to Open WebUI Community'));
 
 
 		const url = 'https://openwebui.com';
 		const url = 'https://openwebui.com';
 
 
@@ -438,7 +438,7 @@
 	{#if $config?.features.enable_community_sharing}
 	{#if $config?.features.enable_community_sharing}
 		<div class=" my-16">
 		<div class=" my-16">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
 			<div class=" text-xl font-medium mb-1 line-clamp-1">
-				{$i18n.t('Made by OpenWebUI Community')}
+				{$i18n.t('Made by Open WebUI Community')}
 			</div>
 			</div>
 
 
 			<a
 			<a

+ 10 - 3
src/lib/i18n/locales/ar-BH/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "أضغط هنا الانتقال",
 	"Click here to": "أضغط هنا الانتقال",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "أضغط هنا للاختيار",
 	"Click here to select": "أضغط هنا للاختيار",
 	"Click here to select a csv file.": "أضغط هنا للاختيار ملف csv",
 	"Click here to select a csv file.": "أضغط هنا للاختيار ملف csv",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "مستندات",
 	"Documents": "مستندات",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "لا يجري أي اتصالات خارجية، وتظل بياناتك آمنة على الخادم المستضاف محليًا.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "لا يجري أي اتصالات خارجية، وتظل بياناتك آمنة على الخادم المستضاف محليًا.",
+	"Domain Filter List": "",
 	"Don't have an account?": "ليس لديك حساب؟",
 	"Don't have an account?": "ليس لديك حساب؟",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "أدخل الChunk Overlap",
 	"Enter Chunk Overlap": "أدخل الChunk Overlap",
 	"Enter Chunk Size": "أدخل Chunk الحجم",
 	"Enter Chunk Size": "أدخل Chunk الحجم",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "أدخل عنوان URL ل Github Raw",
 	"Enter Github Raw URL": "أدخل عنوان URL ل Github Raw",
 	"Enter Google PSE API Key": "أدخل مفتاح واجهة برمجة تطبيقات PSE من Google",
 	"Enter Google PSE API Key": "أدخل مفتاح واجهة برمجة تطبيقات PSE من Google",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "اللغة",
 	"Language": "اللغة",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "فاتح",
 	"Light": "فاتح",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "من جهة اليسار إلى اليمين",
 	"LTR": "من جهة اليسار إلى اليمين",
-	"Made by OpenWebUI Community": "OpenWebUI تم إنشاؤه بواسطة مجتمع ",
+	"Made by Open WebUI Community": "OpenWebUI تم إنشاؤه بواسطة مجتمع ",
 	"Make sure to enclose them with": "تأكد من إرفاقها",
 	"Make sure to enclose them with": "تأكد من إرفاقها",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "أقراء لي",
 	"Read Aloud": "أقراء لي",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "سجل صوت",
 	"Record voice": "سجل صوت",
-	"Redirecting you to OpenWebUI Community": "OpenWebUI إعادة توجيهك إلى مجتمع ",
+	"Redirecting you to Open WebUI Community": "OpenWebUI إعادة توجيهك إلى مجتمع ",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "تم حفظ الاعدادات بنجاح",
 	"Settings saved successfully!": "تم حفظ الاعدادات بنجاح",
 	"Share": "كشاركة",
 	"Share": "كشاركة",
 	"Share Chat": "مشاركة الدردشة",
 	"Share Chat": "مشاركة الدردشة",
-	"Share to OpenWebUI Community": "OpenWebUI شارك في مجتمع",
+	"Share to Open WebUI Community": "OpenWebUI شارك في مجتمع",
 	"Show": "عرض",
 	"Show": "عرض",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "شرح شامل",
 	"Thorough explanation": "شرح شامل",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/bg-BG/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Натиснете тук за",
 	"Click here to": "Натиснете тук за",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Натиснете тук, за да изберете",
 	"Click here to select": "Натиснете тук, за да изберете",
 	"Click here to select a csv file.": "Натиснете тук, за да изберете csv файл.",
 	"Click here to select a csv file.": "Натиснете тук, за да изберете csv файл.",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "Документи",
 	"Documents": "Документи",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "няма външни връзки, и вашите данни остават сигурни на локално назначен сървър.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "няма външни връзки, и вашите данни остават сигурни на локално назначен сървър.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Нямате акаунт?",
 	"Don't have an account?": "Нямате акаунт?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Въведете Chunk Overlap",
 	"Enter Chunk Overlap": "Въведете Chunk Overlap",
 	"Enter Chunk Size": "Въведете Chunk Size",
 	"Enter Chunk Size": "Въведете Chunk Size",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Въведете URL адреса на Github Raw",
 	"Enter Github Raw URL": "Въведете URL адреса на Github Raw",
 	"Enter Google PSE API Key": "Въведете Google PSE API ключ",
 	"Enter Google PSE API Key": "Въведете Google PSE API ключ",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Език",
 	"Language": "Език",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Светъл",
 	"Light": "Светъл",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Направено от OpenWebUI общността",
+	"Made by Open WebUI Community": "Направено от OpenWebUI общността",
 	"Make sure to enclose them with": "Уверете се, че са заключени с",
 	"Make sure to enclose them with": "Уверете се, че са заключени с",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Прочети на Голос",
 	"Read Aloud": "Прочети на Голос",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Записване на глас",
 	"Record voice": "Записване на глас",
-	"Redirecting you to OpenWebUI Community": "Пренасочване към OpenWebUI общността",
+	"Redirecting you to Open WebUI Community": "Пренасочване към OpenWebUI общността",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Настройките са запазени успешно!",
 	"Settings saved successfully!": "Настройките са запазени успешно!",
 	"Share": "Подели",
 	"Share": "Подели",
 	"Share Chat": "Подели Чат",
 	"Share Chat": "Подели Чат",
-	"Share to OpenWebUI Community": "Споделите с OpenWebUI Общността",
+	"Share to Open WebUI Community": "Споделите с OpenWebUI Общността",
 	"Show": "Покажи",
 	"Show": "Покажи",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Това е подробно описание.",
 	"Thorough explanation": "Това е подробно описание.",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/bn-BD/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "এখানে ক্লিক করুন",
 	"Click here to": "এখানে ক্লিক করুন",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "নির্বাচন করার জন্য এখানে ক্লিক করুন",
 	"Click here to select": "নির্বাচন করার জন্য এখানে ক্লিক করুন",
 	"Click here to select a csv file.": "একটি csv ফাইল নির্বাচন করার জন্য এখানে ক্লিক করুন",
 	"Click here to select a csv file.": "একটি csv ফাইল নির্বাচন করার জন্য এখানে ক্লিক করুন",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "ডকুমেন্টসমূহ",
 	"Documents": "ডকুমেন্টসমূহ",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "কোন এক্সটার্নাল কানেকশন তৈরি করে না, এবং আপনার ডেটা আর লোকালি হোস্টেড সার্ভারেই নিরাপদে থাকে।",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "কোন এক্সটার্নাল কানেকশন তৈরি করে না, এবং আপনার ডেটা আর লোকালি হোস্টেড সার্ভারেই নিরাপদে থাকে।",
+	"Domain Filter List": "",
 	"Don't have an account?": "একাউন্ট নেই?",
 	"Don't have an account?": "একাউন্ট নেই?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "চাঙ্ক ওভারল্যাপ লিখুন",
 	"Enter Chunk Overlap": "চাঙ্ক ওভারল্যাপ লিখুন",
 	"Enter Chunk Size": "চাংক সাইজ লিখুন",
 	"Enter Chunk Size": "চাংক সাইজ লিখুন",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "গিটহাব কাঁচা URL লিখুন",
 	"Enter Github Raw URL": "গিটহাব কাঁচা URL লিখুন",
 	"Enter Google PSE API Key": "গুগল পিএসই এপিআই কী লিখুন",
 	"Enter Google PSE API Key": "গুগল পিএসই এপিআই কী লিখুন",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "ভাষা",
 	"Language": "ভাষা",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "লাইট",
 	"Light": "লাইট",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "OpenWebUI কমিউনিটিকর্তৃক নির্মিত",
+	"Made by Open WebUI Community": "OpenWebUI কমিউনিটিকর্তৃক নির্মিত",
 	"Make sure to enclose them with": "এটা দিয়ে বন্ধনী দিতে ভুলবেন না",
 	"Make sure to enclose them with": "এটা দিয়ে বন্ধনী দিতে ভুলবেন না",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "পড়াশোনা করুন",
 	"Read Aloud": "পড়াশোনা করুন",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "ভয়েস রেকর্ড করুন",
 	"Record voice": "ভয়েস রেকর্ড করুন",
-	"Redirecting you to OpenWebUI Community": "আপনাকে OpenWebUI কমিউনিটিতে পাঠানো হচ্ছে",
+	"Redirecting you to Open WebUI Community": "আপনাকে OpenWebUI কমিউনিটিতে পাঠানো হচ্ছে",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "সেটিংগুলো সফলভাবে সংরক্ষিত হয়েছে",
 	"Settings saved successfully!": "সেটিংগুলো সফলভাবে সংরক্ষিত হয়েছে",
 	"Share": "শেয়ার করুন",
 	"Share": "শেয়ার করুন",
 	"Share Chat": "চ্যাট শেয়ার করুন",
 	"Share Chat": "চ্যাট শেয়ার করুন",
-	"Share to OpenWebUI Community": "OpenWebUI কমিউনিটিতে শেয়ার করুন",
+	"Share to Open WebUI Community": "OpenWebUI কমিউনিটিতে শেয়ার করুন",
 	"Show": "দেখান",
 	"Show": "দেখান",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "পুঙ্খানুপুঙ্খ ব্যাখ্যা",
 	"Thorough explanation": "পুঙ্খানুপুঙ্খ ব্যাখ্যা",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 29 - 22
src/lib/i18n/locales/ca-ES/translation.json

@@ -63,11 +63,11 @@
 	"Allowed Endpoints": "Punts d'accés permesos",
 	"Allowed Endpoints": "Punts d'accés permesos",
 	"Already have an account?": "Ja tens un compte?",
 	"Already have an account?": "Ja tens un compte?",
 	"Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out. (Default: 0.0)": "Alternativa al top_p, i pretén garantir un equilibri de qualitat i varietat. El paràmetre p representa la probabilitat mínima que es consideri un token, en relació amb la probabilitat del token més probable. Per exemple, amb p=0,05 i el token més probable amb una probabilitat de 0,9, es filtren els logits amb un valor inferior a 0,045. (Per defecte: 0.0)",
 	"Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out. (Default: 0.0)": "Alternativa al top_p, i pretén garantir un equilibri de qualitat i varietat. El paràmetre p representa la probabilitat mínima que es consideri un token, en relació amb la probabilitat del token més probable. Per exemple, amb p=0,05 i el token més probable amb una probabilitat de 0,9, es filtren els logits amb un valor inferior a 0,045. (Per defecte: 0.0)",
-	"Always": "",
+	"Always": "Sempre",
 	"Amazing": "Al·lucinant",
 	"Amazing": "Al·lucinant",
 	"an assistant": "un assistent",
 	"an assistant": "un assistent",
-	"Analyzed": "",
-	"Analyzing...": "",
+	"Analyzed": "Analitzat",
+	"Analyzing...": "Analitzant...",
 	"and": "i",
 	"and": "i",
 	"and {{COUNT}} more": "i {{COUNT}} més",
 	"and {{COUNT}} more": "i {{COUNT}} més",
 	"and create a new shared link.": "i crear un nou enllaç compartit.",
 	"and create a new shared link.": "i crear un nou enllaç compartit.",
@@ -163,6 +163,7 @@
 	"Click here to": "Clic aquí per",
 	"Click here to": "Clic aquí per",
 	"Click here to download user import template file.": "Fes clic aquí per descarregar l'arxiu de plantilla d'importació d'usuaris",
 	"Click here to download user import template file.": "Fes clic aquí per descarregar l'arxiu de plantilla d'importació d'usuaris",
 	"Click here to learn more about faster-whisper and see the available models.": "Clica aquí per obtenir més informació sobre faster-whisper i veure els models disponibles.",
 	"Click here to learn more about faster-whisper and see the available models.": "Clica aquí per obtenir més informació sobre faster-whisper i veure els models disponibles.",
+	"Click here to see available models.": "Clica aquí per veure els models disponibles.",
 	"Click here to select": "Clica aquí per seleccionar",
 	"Click here to select": "Clica aquí per seleccionar",
 	"Click here to select a csv file.": "Clica aquí per seleccionar un fitxer csv.",
 	"Click here to select a csv file.": "Clica aquí per seleccionar un fitxer csv.",
 	"Click here to select a py file.": "Clica aquí per seleccionar un fitxer py.",
 	"Click here to select a py file.": "Clica aquí per seleccionar un fitxer py.",
@@ -172,11 +173,11 @@
 	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permís d'escriptura al porta-retalls denegat. Comprova els ajustos de navegador per donar l'accés necessari.",
 	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permís d'escriptura al porta-retalls denegat. Comprova els ajustos de navegador per donar l'accés necessari.",
 	"Clone": "Clonar",
 	"Clone": "Clonar",
 	"Clone Chat": "Clonar el xat",
 	"Clone Chat": "Clonar el xat",
-	"Clone of {{TITLE}}": "",
+	"Clone of {{TITLE}}": "Clon de {{TITLE}}",
 	"Close": "Tancar",
 	"Close": "Tancar",
 	"Code execution": "Execució de codi",
 	"Code execution": "Execució de codi",
 	"Code formatted successfully": "Codi formatat correctament",
 	"Code formatted successfully": "Codi formatat correctament",
-	"Code Interpreter": "",
+	"Code Interpreter": "Intèrpret de codi",
 	"Collection": "Col·lecció",
 	"Collection": "Col·lecció",
 	"Color": "Color",
 	"Color": "Color",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI": "ComfyUI",
@@ -238,7 +239,7 @@
 	"Default": "Per defecte",
 	"Default": "Per defecte",
 	"Default (Open AI)": "Per defecte (Open AI)",
 	"Default (Open AI)": "Per defecte (Open AI)",
 	"Default (SentenceTransformers)": "Per defecte (SentenceTransformers)",
 	"Default (SentenceTransformers)": "Per defecte (SentenceTransformers)",
-	"Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model’s built-in tool-calling capabilities, but requires the model to inherently support this feature.": "",
+	"Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model’s built-in tool-calling capabilities, but requires the model to inherently support this feature.": "El mode predeterminat funciona amb una gamma més àmplia de models cridant a les eines una vegada abans de l'execució. El mode natiu aprofita les capacitats de crida d'eines integrades del model, però requereix que el model admeti aquesta funció de manera inherent.",
 	"Default Model": "Model per defecte",
 	"Default Model": "Model per defecte",
 	"Default model updated": "Model per defecte actualitzat",
 	"Default model updated": "Model per defecte actualitzat",
 	"Default Models": "Models per defecte",
 	"Default Models": "Models per defecte",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentació",
 	"Documentation": "Documentació",
 	"Documents": "Documents",
 	"Documents": "Documents",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "no realitza connexions externes, i les teves dades romanen segures al teu servidor allotjat localment.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "no realitza connexions externes, i les teves dades romanen segures al teu servidor allotjat localment.",
+	"Domain Filter List": "Llista de filtre de dominis",
 	"Don't have an account?": "No tens un compte?",
 	"Don't have an account?": "No tens un compte?",
 	"don't install random functions from sources you don't trust.": "no instal·lis funcions aleatòries de fonts en què no confiïs.",
 	"don't install random functions from sources you don't trust.": "no instal·lis funcions aleatòries de fonts en què no confiïs.",
 	"don't install random tools from sources you don't trust.": "no instal·lis eines aleatòries de fonts en què no confiïs.",
 	"don't install random tools from sources you don't trust.": "no instal·lis eines aleatòries de fonts en què no confiïs.",
@@ -349,7 +351,8 @@
 	"Enter Chunk Overlap": "Introdueix la mida de solapament de blocs",
 	"Enter Chunk Overlap": "Introdueix la mida de solapament de blocs",
 	"Enter Chunk Size": "Introdueix la mida del bloc",
 	"Enter Chunk Size": "Introdueix la mida del bloc",
 	"Enter description": "Introdueix la descripció",
 	"Enter description": "Introdueix la descripció",
-	"Enter Exa API Key": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "Introdueix els dominis separats per comes (p. ex. example.com,site.org)",
+	"Enter Exa API Key": "Introdueix la clau API de d'EXA",
 	"Enter Github Raw URL": "Introdueix l'URL en brut de Github",
 	"Enter Github Raw URL": "Introdueix l'URL en brut de Github",
 	"Enter Google PSE API Key": "Introdueix la clau API de Google PSE",
 	"Enter Google PSE API Key": "Introdueix la clau API de Google PSE",
 	"Enter Google PSE Engine Id": "Introdueix l'identificador del motor PSE de Google",
 	"Enter Google PSE Engine Id": "Introdueix l'identificador del motor PSE de Google",
@@ -398,14 +401,14 @@
 	"Error accessing Google Drive: {{error}}": "Error en accedir a Google Drive: {{error}}",
 	"Error accessing Google Drive: {{error}}": "Error en accedir a Google Drive: {{error}}",
 	"Error uploading file: {{error}}": "Error en pujar l'arxiu: {{error}}",
 	"Error uploading file: {{error}}": "Error en pujar l'arxiu: {{error}}",
 	"Evaluations": "Avaluacions",
 	"Evaluations": "Avaluacions",
-	"Exa API Key": "",
+	"Exa API Key": "Clau API d'EXA",
 	"Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))",
 	"Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))",
 	"Example: ALL": "Exemple: TOTS",
 	"Example: ALL": "Exemple: TOTS",
 	"Example: mail": "Exemple: mail",
 	"Example: mail": "Exemple: mail",
 	"Example: ou=users,dc=foo,dc=example": "Exemple: ou=users,dc=foo,dc=example",
 	"Example: ou=users,dc=foo,dc=example": "Exemple: ou=users,dc=foo,dc=example",
 	"Example: sAMAccountName or uid or userPrincipalName": "Exemple: sAMAccountName o uid o userPrincipalName",
 	"Example: sAMAccountName or uid or userPrincipalName": "Exemple: sAMAccountName o uid o userPrincipalName",
 	"Exclude": "Excloure",
 	"Exclude": "Excloure",
-	"Execute code for analysis": "",
+	"Execute code for analysis": "Executa el codi per analitzar-lo",
 	"Experimental": "Experimental",
 	"Experimental": "Experimental",
 	"Explore the cosmos": "Explorar el cosmos",
 	"Explore the cosmos": "Explorar el cosmos",
 	"Export": "Exportar",
 	"Export": "Exportar",
@@ -458,7 +461,7 @@
 	"Format your variables using brackets like this:": "Formata les teves variables utilitzant claudàtors així:",
 	"Format your variables using brackets like this:": "Formata les teves variables utilitzant claudàtors així:",
 	"Frequency Penalty": "Penalització per freqüència",
 	"Frequency Penalty": "Penalització per freqüència",
 	"Function": "Funció",
 	"Function": "Funció",
-	"Function Calling": "",
+	"Function Calling": "Crida a funcions",
 	"Function created successfully": "La funció s'ha creat correctament",
 	"Function created successfully": "La funció s'ha creat correctament",
 	"Function deleted successfully": "La funció s'ha eliminat correctament",
 	"Function deleted successfully": "La funció s'ha eliminat correctament",
 	"Function Description": "Descripció de la funció",
 	"Function Description": "Descripció de la funció",
@@ -473,7 +476,7 @@
 	"Functions imported successfully": "Les funcions s'han importat correctament",
 	"Functions imported successfully": "Les funcions s'han importat correctament",
 	"General": "General",
 	"General": "General",
 	"General Settings": "Preferències generals",
 	"General Settings": "Preferències generals",
-	"Generate an image": "",
+	"Generate an image": "Generar una imatge",
 	"Generate Image": "Generar imatge",
 	"Generate Image": "Generar imatge",
 	"Generating search query": "Generant consulta",
 	"Generating search query": "Generant consulta",
 	"Get started": "Començar",
 	"Get started": "Començar",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Coneixement eliminat correctament.",
 	"Knowledge deleted successfully.": "Coneixement eliminat correctament.",
 	"Knowledge reset successfully.": "Coneixement restablert correctament.",
 	"Knowledge reset successfully.": "Coneixement restablert correctament.",
 	"Knowledge updated successfully": "Coneixement actualitzat correctament.",
 	"Knowledge updated successfully": "Coneixement actualitzat correctament.",
+	"Kokoro.js (Browser)": "Kokoro.js (Navegador)",
+	"Kokoro.js Dtype": "Kokoro.js Dtype",
 	"Label": "Etiqueta",
 	"Label": "Etiqueta",
 	"Landing Page Mode": "Mode de la pàgina d'entrada",
 	"Landing Page Mode": "Mode de la pàgina d'entrada",
 	"Language": "Idioma",
 	"Language": "Idioma",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Deixar-ho buit per incloure tots els models del punt de connexió \"{{URL}}/models\"",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Deixar-ho buit per incloure tots els models del punt de connexió \"{{URL}}/models\"",
 	"Leave empty to include all models or select specific models": "Deixa-ho en blanc per incloure tots els models o selecciona models específics",
 	"Leave empty to include all models or select specific models": "Deixa-ho en blanc per incloure tots els models o selecciona models específics",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Deixa-ho en blanc per utilitzar la indicació predeterminada o introdueix una indicació personalitzada",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Deixa-ho en blanc per utilitzar la indicació predeterminada o introdueix una indicació personalitzada",
+	"Leave model field empty to use the default model.": "Deixa el camp de model buit per utilitzar el model per defecte.",
 	"Light": "Clar",
 	"Light": "Clar",
 	"Listening...": "Escoltant...",
 	"Listening...": "Escoltant...",
 	"Llama.cpp": "Llama.cpp",
 	"Llama.cpp": "Llama.cpp",
@@ -574,7 +580,7 @@
 	"Local Models": "Models locals",
 	"Local Models": "Models locals",
 	"Lost": "Perdut",
 	"Lost": "Perdut",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Creat per la Comunitat OpenWebUI",
+	"Made by Open WebUI Community": "Creat per la Comunitat OpenWebUI",
 	"Make sure to enclose them with": "Assegura't d'envoltar-los amb",
 	"Make sure to enclose them with": "Assegura't d'envoltar-los amb",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Assegura't d'exportar un fitxer workflow.json com a format API des de ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Assegura't d'exportar un fitxer workflow.json com a format API des de ComfyUI.",
 	"Manage": "Gestionar",
 	"Manage": "Gestionar",
@@ -630,7 +636,7 @@
 	"More": "Més",
 	"More": "Més",
 	"Name": "Nom",
 	"Name": "Nom",
 	"Name your knowledge base": "Anomena la teva base de coneixement",
 	"Name your knowledge base": "Anomena la teva base de coneixement",
-	"Native": "",
+	"Native": "Natiu",
 	"New Chat": "Nou xat",
 	"New Chat": "Nou xat",
 	"New Folder": "Nova carpeta",
 	"New Folder": "Nova carpeta",
 	"New Password": "Nova contrasenya",
 	"New Password": "Nova contrasenya",
@@ -725,7 +731,7 @@
 	"Please enter a prompt": "Si us plau, entra una indicació",
 	"Please enter a prompt": "Si us plau, entra una indicació",
 	"Please fill in all fields.": "Emplena tots els camps, si us plau.",
 	"Please fill in all fields.": "Emplena tots els camps, si us plau.",
 	"Please select a model first.": "Si us plau, selecciona un model primer",
 	"Please select a model first.": "Si us plau, selecciona un model primer",
-	"Please select a model.": "",
+	"Please select a model.": "Si us plau, selecciona un model.",
 	"Please select a reason": "Si us plau, selecciona una raó",
 	"Please select a reason": "Si us plau, selecciona una raó",
 	"Port": "Port",
 	"Port": "Port",
 	"Positive attitude": "Actitud positiva",
 	"Positive attitude": "Actitud positiva",
@@ -734,7 +740,7 @@
 	"Previous 30 days": "30 dies anteriors",
 	"Previous 30 days": "30 dies anteriors",
 	"Previous 7 days": "7 dies anteriors",
 	"Previous 7 days": "7 dies anteriors",
 	"Profile Image": "Imatge de perfil",
 	"Profile Image": "Imatge de perfil",
-	"Prompt": "",
+	"Prompt": "Indicació",
 	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Indicació (p.ex. Digues-me quelcom divertit sobre l'Imperi Romà)",
 	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Indicació (p.ex. Digues-me quelcom divertit sobre l'Imperi Romà)",
 	"Prompt Content": "Contingut de la indicació",
 	"Prompt Content": "Contingut de la indicació",
 	"Prompt created successfully": "Indicació creada correctament",
 	"Prompt created successfully": "Indicació creada correctament",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Llegir en veu alta",
 	"Read Aloud": "Llegir en veu alta",
 	"Reasoning Effort": "Esforç de raonament",
 	"Reasoning Effort": "Esforç de raonament",
 	"Record voice": "Enregistrar la veu",
 	"Record voice": "Enregistrar la veu",
-	"Redirecting you to OpenWebUI Community": "Redirigint-te a la comunitat OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Redirigint-te a la comunitat OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Redueix la probabilitat de generar ximpleries. Un valor més alt (p. ex. 100) donarà respostes més diverses, mentre que un valor més baix (p. ex. 10) serà més conservador. (Per defecte: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Redueix la probabilitat de generar ximpleries. Un valor més alt (p. ex. 100) donarà respostes més diverses, mentre que un valor més baix (p. ex. 10) serà més conservador. (Per defecte: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Fes referència a tu mateix com a \"Usuari\" (p. ex., \"L'usuari està aprenent espanyol\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Fes referència a tu mateix com a \"Usuari\" (p. ex., \"L'usuari està aprenent espanyol\")",
 	"References from": "Referències de",
 	"References from": "Referències de",
@@ -810,7 +816,7 @@
 	"Search options": "Opcions de cerca",
 	"Search options": "Opcions de cerca",
 	"Search Prompts": "Cercar indicacions",
 	"Search Prompts": "Cercar indicacions",
 	"Search Result Count": "Recompte de resultats de cerca",
 	"Search Result Count": "Recompte de resultats de cerca",
-	"Search the internet": "",
+	"Search the internet": "Cerca a internet",
 	"Search Tools": "Cercar eines",
 	"Search Tools": "Cercar eines",
 	"SearchApi API Key": "Clau API de SearchApi",
 	"SearchApi API Key": "Clau API de SearchApi",
 	"SearchApi Engine": "Motor de SearchApi",
 	"SearchApi Engine": "Motor de SearchApi",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Les preferències s'han desat correctament",
 	"Settings saved successfully!": "Les preferències s'han desat correctament",
 	"Share": "Compartir",
 	"Share": "Compartir",
 	"Share Chat": "Compartir el xat",
 	"Share Chat": "Compartir el xat",
-	"Share to OpenWebUI Community": "Compartir amb la comunitat OpenWebUI",
+	"Share to Open WebUI Community": "Compartir amb la comunitat OpenWebUI",
 	"Show": "Mostrar",
 	"Show": "Mostrar",
 	"Show \"What's New\" modal on login": "Veure 'Què hi ha de nou' a l'entrada",
 	"Show \"What's New\" modal on login": "Veure 'Què hi ha de nou' a l'entrada",
 	"Show Admin Details in Account Pending Overlay": "Mostrar els detalls de l'administrador a la superposició del compte pendent",
 	"Show Admin Details in Account Pending Overlay": "Mostrar els detalls de l'administrador a la superposició del compte pendent",
@@ -943,7 +949,8 @@
 	"This will delete all models including custom models and cannot be undone.": "Això eliminarà tots els models incloent els personalitzats i no es pot desfer",
 	"This will delete all models including custom models and cannot be undone.": "Això eliminarà tots els models incloent els personalitzats i no es pot desfer",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Això restablirà la base de coneixement i sincronitzarà tots els fitxers. Vols continuar?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Això restablirà la base de coneixement i sincronitzarà tots els fitxers. Vols continuar?",
 	"Thorough explanation": "Explicació en detall",
 	"Thorough explanation": "Explicació en detall",
-	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}}": "He pensat durant {{DURATION}}",
+	"Thought for {{DURATION}} seconds": "He pensat durant {{DURATION}} segons",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "La URL del servidor Tika és obligatòria.",
 	"Tika Server URL required.": "La URL del servidor Tika és obligatòria.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",
@@ -980,7 +987,7 @@
 	"Tools": "Eines",
 	"Tools": "Eines",
 	"Tools Access": "Accés a les eines",
 	"Tools Access": "Accés a les eines",
 	"Tools are a function calling system with arbitrary code execution": "Les eines són un sistema de crida a funcions amb execució de codi arbitrari",
 	"Tools are a function calling system with arbitrary code execution": "Les eines són un sistema de crida a funcions amb execució de codi arbitrari",
-	"Tools Function Calling Prompt": "",
+	"Tools Function Calling Prompt": "Indicació per a la crida de funcions",
 	"Tools have a function calling system that allows arbitrary code execution": "Les eines disposen d'un sistema de crida a funcions que permet execució de codi arbitrari",
 	"Tools have a function calling system that allows arbitrary code execution": "Les eines disposen d'un sistema de crida a funcions que permet execució de codi arbitrari",
 	"Tools have a function calling system that allows arbitrary code execution.": "Les eines disposen d'un sistema de crida a funcions que permet execució de codi arbitrari.",
 	"Tools have a function calling system that allows arbitrary code execution.": "Les eines disposen d'un sistema de crida a funcions que permet execució de codi arbitrari.",
 	"Top K": "Top K",
 	"Top K": "Top K",
@@ -1051,7 +1058,7 @@
 	"Web Loader Settings": "Preferències del carregador web",
 	"Web Loader Settings": "Preferències del carregador web",
 	"Web Search": "Cerca la web",
 	"Web Search": "Cerca la web",
 	"Web Search Engine": "Motor de cerca de la web",
 	"Web Search Engine": "Motor de cerca de la web",
-	"Web Search in Chat": "",
+	"Web Search in Chat": "Cerca a internet al xat",
 	"Web Search Query Generation": "Generació de consultes per a la cerca de la web",
 	"Web Search Query Generation": "Generació de consultes per a la cerca de la web",
 	"Webhook URL": "URL del webhook",
 	"Webhook URL": "URL del webhook",
 	"WebUI Settings": "Preferències de WebUI",
 	"WebUI Settings": "Preferències de WebUI",
@@ -1081,7 +1088,7 @@
 	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Pots personalitzar les teves interaccions amb els models de llenguatge afegint memòries mitjançant el botó 'Gestiona' que hi ha a continuació, fent-les més útils i adaptades a tu.",
 	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Pots personalitzar les teves interaccions amb els models de llenguatge afegint memòries mitjançant el botó 'Gestiona' que hi ha a continuació, fent-les més útils i adaptades a tu.",
 	"You cannot upload an empty file.": "No es pot pujar un ariux buit.",
 	"You cannot upload an empty file.": "No es pot pujar un ariux buit.",
 	"You do not have permission to access this feature.": "No tens permís per accedir a aquesta funcionalitat",
 	"You do not have permission to access this feature.": "No tens permís per accedir a aquesta funcionalitat",
-	"You do not have permission to upload files": "",
+	"You do not have permission to upload files": "No tens permisos per pujar arxius",
 	"You do not have permission to upload files.": "No tens permisos per pujar arxius.",
 	"You do not have permission to upload files.": "No tens permisos per pujar arxius.",
 	"You have no archived conversations.": "No tens converses arxivades.",
 	"You have no archived conversations.": "No tens converses arxivades.",
 	"You have shared this chat": "Has compartit aquest xat",
 	"You have shared this chat": "Has compartit aquest xat",

+ 10 - 3
src/lib/i18n/locales/ceb-PH/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "",
 	"Click here to": "",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "I-klik dinhi aron makapili",
 	"Click here to select": "I-klik dinhi aron makapili",
 	"Click here to select a csv file.": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "Mga dokumento",
 	"Documents": "Mga dokumento",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "wala maghimo ug eksternal nga koneksyon, ug ang imong data nagpabiling luwas sa imong lokal nga host server.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "wala maghimo ug eksternal nga koneksyon, ug ang imong data nagpabiling luwas sa imong lokal nga host server.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Wala kay account ?",
 	"Don't have an account?": "Wala kay account ?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Pagsulod sa block overlap",
 	"Enter Chunk Overlap": "Pagsulod sa block overlap",
 	"Enter Chunk Size": "Isulod ang block size",
 	"Enter Chunk Size": "Isulod ang block size",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "",
 	"Enter Github Raw URL": "",
 	"Enter Google PSE API Key": "",
 	"Enter Google PSE API Key": "",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Pinulongan",
 	"Language": "Pinulongan",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Kahayag",
 	"Light": "Kahayag",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "",
 	"LTR": "",
-	"Made by OpenWebUI Community": "Gihimo sa komunidad sa OpenWebUI",
+	"Made by Open WebUI Community": "Gihimo sa komunidad sa OpenWebUI",
 	"Make sure to enclose them with": "Siguruha nga palibutan sila",
 	"Make sure to enclose them with": "Siguruha nga palibutan sila",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "",
 	"Read Aloud": "",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Irekord ang tingog",
 	"Record voice": "Irekord ang tingog",
-	"Redirecting you to OpenWebUI Community": "Gi-redirect ka sa komunidad sa OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Gi-redirect ka sa komunidad sa OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Malampuson nga na-save ang mga setting!",
 	"Settings saved successfully!": "Malampuson nga na-save ang mga setting!",
 	"Share": "",
 	"Share": "",
 	"Share Chat": "",
 	"Share Chat": "",
-	"Share to OpenWebUI Community": "Ipakigbahin sa komunidad sa OpenWebUI",
+	"Share to Open WebUI Community": "Ipakigbahin sa komunidad sa OpenWebUI",
 	"Show": "Pagpakita",
 	"Show": "Pagpakita",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "",
 	"Thorough explanation": "",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/cs-CZ/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klikněte sem pro",
 	"Click here to": "Klikněte sem pro",
 	"Click here to download user import template file.": "Klikněte zde pro stažení šablony souboru pro import uživatelů.",
 	"Click here to download user import template file.": "Klikněte zde pro stažení šablony souboru pro import uživatelů.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikněte sem a zjistěte více o faster-whisper a podívejte se na dostupné modely.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikněte sem a zjistěte více o faster-whisper a podívejte se na dostupné modely.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klikněte sem pro výběr",
 	"Click here to select": "Klikněte sem pro výběr",
 	"Click here to select a csv file.": "Klikněte zde pro výběr souboru typu csv.",
 	"Click here to select a csv file.": "Klikněte zde pro výběr souboru typu csv.",
 	"Click here to select a py file.": "Klikněte sem pro výběr {{py}} souboru.",
 	"Click here to select a py file.": "Klikněte sem pro výběr {{py}} souboru.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentace",
 	"Documentation": "Dokumentace",
 	"Documents": "Dokumenty",
 	"Documents": "Dokumenty",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nevytváří žádná externí připojení a vaše data zůstávají bezpečně na vašem lokálním serveru.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nevytváří žádná externí připojení a vaše data zůstávají bezpečně na vašem lokálním serveru.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nemáte účet?",
 	"Don't have an account?": "Nemáte účet?",
 	"don't install random functions from sources you don't trust.": "Neinstalujte náhodné funkce ze zdrojů, kterým nedůvěřujete.",
 	"don't install random functions from sources you don't trust.": "Neinstalujte náhodné funkce ze zdrojů, kterým nedůvěřujete.",
 	"don't install random tools from sources you don't trust.": "Neinstalujte náhodné nástroje ze zdrojů, kterým nedůvěřujete.",
 	"don't install random tools from sources you don't trust.": "Neinstalujte náhodné nástroje ze zdrojů, kterým nedůvěřujete.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Zadejte překryv části",
 	"Enter Chunk Overlap": "Zadejte překryv části",
 	"Enter Chunk Size": "Zadejte velikost bloku",
 	"Enter Chunk Size": "Zadejte velikost bloku",
 	"Enter description": "Zadejte popis",
 	"Enter description": "Zadejte popis",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Zadejte URL adresu Github Raw",
 	"Enter Github Raw URL": "Zadejte URL adresu Github Raw",
 	"Enter Google PSE API Key": "Zadejte klíč rozhraní API Google PSE",
 	"Enter Google PSE API Key": "Zadejte klíč rozhraní API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Znalosti byly úspěšně odstraněny.",
 	"Knowledge deleted successfully.": "Znalosti byly úspěšně odstraněny.",
 	"Knowledge reset successfully.": "Úspěšné obnovení znalostí.",
 	"Knowledge reset successfully.": "Úspěšné obnovení znalostí.",
 	"Knowledge updated successfully": "Znalosti úspěšně aktualizovány",
 	"Knowledge updated successfully": "Znalosti úspěšně aktualizovány",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Režim vstupní stránky",
 	"Landing Page Mode": "Režim vstupní stránky",
 	"Language": "Jazyk",
 	"Language": "Jazyk",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "Nechte prázdné pro zahrnutí všech modelů nebo vyberte konkrétní modely.",
 	"Leave empty to include all models or select specific models": "Nechte prázdné pro zahrnutí všech modelů nebo vyberte konkrétní modely.",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Nechte prázdné pro použití výchozího podnětu, nebo zadejte vlastní podnět.",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Nechte prázdné pro použití výchozího podnětu, nebo zadejte vlastní podnět.",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Světlo",
 	"Light": "Světlo",
 	"Listening...": "Poslouchání...",
 	"Listening...": "Poslouchání...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokální modely",
 	"Local Models": "Lokální modely",
 	"Lost": "Ztracený",
 	"Lost": "Ztracený",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Vytvořeno komunitou OpenWebUI",
+	"Made by Open WebUI Community": "Vytvořeno komunitou OpenWebUI",
 	"Make sure to enclose them with": "Ujistěte se, že jsou uzavřeny pomocí",
 	"Make sure to enclose them with": "Ujistěte se, že jsou uzavřeny pomocí",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Ujistěte se, že exportujete soubor workflow.json ve formátu API z ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Ujistěte se, že exportujete soubor workflow.json ve formátu API z ComfyUI.",
 	"Manage": "Spravovat",
 	"Manage": "Spravovat",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Číst nahlas",
 	"Read Aloud": "Číst nahlas",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Nahrát hlas",
 	"Record voice": "Nahrát hlas",
-	"Redirecting you to OpenWebUI Community": "Přesměrování na komunitu OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Přesměrování na komunitu OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na sebe jako na \"uživatele\" (např. \"Uživatel se učí španělsky\").",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na sebe jako na \"uživatele\" (např. \"Uživatel se učí španělsky\").",
 	"References from": "Reference z",
 	"References from": "Reference z",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Nastavení byla úspěšně uložena!",
 	"Settings saved successfully!": "Nastavení byla úspěšně uložena!",
 	"Share": "Sdílet",
 	"Share": "Sdílet",
 	"Share Chat": "Sdílet chat",
 	"Share Chat": "Sdílet chat",
-	"Share to OpenWebUI Community": "Sdílet s komunitou OpenWebUI",
+	"Share to Open WebUI Community": "Sdílet s komunitou OpenWebUI",
 	"Show": "Zobrazit",
 	"Show": "Zobrazit",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Zobrazit podrobnosti administrátora v překryvném okně s čekajícím účtem",
 	"Show Admin Details in Account Pending Overlay": "Zobrazit podrobnosti administrátora v překryvném okně s čekajícím účtem",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Toto obnoví znalostní databázi a synchronizuje všechny soubory. Přejete si pokračovat?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Toto obnoví znalostní databázi a synchronizuje všechny soubory. Přejete si pokračovat?",
 	"Thorough explanation": "Obsáhlé vysvětlení",
 	"Thorough explanation": "Obsáhlé vysvětlení",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Je vyžadována URL adresa serveru Tika.",
 	"Tika Server URL required.": "Je vyžadována URL adresa serveru Tika.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/da-DK/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klik her for at",
 	"Click here to": "Klik her for at",
 	"Click here to download user import template file.": "Klik her for at downloade bruger import template fil.",
 	"Click here to download user import template file.": "Klik her for at downloade bruger import template fil.",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Klik her for at vælge",
 	"Click here to select": "Klik her for at vælge",
 	"Click here to select a csv file.": "Klik her for at vælge en csv fil",
 	"Click here to select a csv file.": "Klik her for at vælge en csv fil",
 	"Click here to select a py file.": "Klik her for at vælge en py fil",
 	"Click here to select a py file.": "Klik her for at vælge en py fil",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentation",
 	"Documentation": "Dokumentation",
 	"Documents": "Dokumenter",
 	"Documents": "Dokumenter",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "laver ikke eksterne kald, og din data bliver sikkert på din egen lokalt hostede server.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "laver ikke eksterne kald, og din data bliver sikkert på din egen lokalt hostede server.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Har du ikke en profil?",
 	"Don't have an account?": "Har du ikke en profil?",
 	"don't install random functions from sources you don't trust.": "lad være med at installere tilfældige funktioner fra kilder, som du ikke stoler på.",
 	"don't install random functions from sources you don't trust.": "lad være med at installere tilfældige funktioner fra kilder, som du ikke stoler på.",
 	"don't install random tools from sources you don't trust.": "lad være med at installere tilfældige værktøjer fra kilder, som du ikke stoler på.",
 	"don't install random tools from sources you don't trust.": "lad være med at installere tilfældige værktøjer fra kilder, som du ikke stoler på.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Indtast overlapning af tekststykker",
 	"Enter Chunk Overlap": "Indtast overlapning af tekststykker",
 	"Enter Chunk Size": "Indtast størrelse af tekststykker",
 	"Enter Chunk Size": "Indtast størrelse af tekststykker",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Indtast Github Raw URL",
 	"Enter Github Raw URL": "Indtast Github Raw URL",
 	"Enter Google PSE API Key": "Indtast Google PSE API-nøgle",
 	"Enter Google PSE API Key": "Indtast Google PSE API-nøgle",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Viden slettet.",
 	"Knowledge deleted successfully.": "Viden slettet.",
 	"Knowledge reset successfully.": "Viden nulstillet.",
 	"Knowledge reset successfully.": "Viden nulstillet.",
 	"Knowledge updated successfully": "Viden opdateret.",
 	"Knowledge updated successfully": "Viden opdateret.",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Landing Page-tilstand",
 	"Landing Page Mode": "Landing Page-tilstand",
 	"Language": "Sprog",
 	"Language": "Sprog",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Lad stå tomt for at bruge standardprompten, eller indtast en brugerdefineret prompt",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Lad stå tomt for at bruge standardprompten, eller indtast en brugerdefineret prompt",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Lys",
 	"Light": "Lys",
 	"Listening...": "Lytter...",
 	"Listening...": "Lytter...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokale modeller",
 	"Local Models": "Lokale modeller",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Lavet af OpenWebUI Community",
+	"Made by Open WebUI Community": "Lavet af OpenWebUI Community",
 	"Make sure to enclose them with": "Sørg for at omslutte dem med",
 	"Make sure to enclose them with": "Sørg for at omslutte dem med",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Sørg for at eksportere en workflow.json-fil som API-format fra ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Sørg for at eksportere en workflow.json-fil som API-format fra ComfyUI.",
 	"Manage": "Administrer",
 	"Manage": "Administrer",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Læs højt",
 	"Read Aloud": "Læs højt",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Optag stemme",
 	"Record voice": "Optag stemme",
-	"Redirecting you to OpenWebUI Community": "Omdirigerer dig til OpenWebUI Community",
+	"Redirecting you to Open WebUI Community": "Omdirigerer dig til OpenWebUI Community",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referer til dig selv som \"Bruger\" (f.eks. \"Bruger lærer spansk\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referer til dig selv som \"Bruger\" (f.eks. \"Bruger lærer spansk\")",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Indstillinger gemt!",
 	"Settings saved successfully!": "Indstillinger gemt!",
 	"Share": "Del",
 	"Share": "Del",
 	"Share Chat": "Del chat",
 	"Share Chat": "Del chat",
-	"Share to OpenWebUI Community": "Del til OpenWebUI Community",
+	"Share to Open WebUI Community": "Del til OpenWebUI Community",
 	"Show": "Vis",
 	"Show": "Vis",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i overlay for ventende konto",
 	"Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i overlay for ventende konto",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dette vil nulstille vidensbasen og synkronisere alle filer. Vil du fortsætte?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dette vil nulstille vidensbasen og synkronisere alle filer. Vil du fortsætte?",
 	"Thorough explanation": "Grundig forklaring",
 	"Thorough explanation": "Grundig forklaring",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika-server-URL påkrævet.",
 	"Tika Server URL required.": "Tika-server-URL påkrævet.",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/de-DE/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klicken Sie hier, um",
 	"Click here to": "Klicken Sie hier, um",
 	"Click here to download user import template file.": "Klicken Sie hier, um die Vorlage für den Benutzerimport herunterzuladen.",
 	"Click here to download user import template file.": "Klicken Sie hier, um die Vorlage für den Benutzerimport herunterzuladen.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klicken Sie hier, um mehr über faster-whisper zu erfahren und die verfügbaren Modelle zu sehen.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klicken Sie hier, um mehr über faster-whisper zu erfahren und die verfügbaren Modelle zu sehen.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klicke Sie zum Auswählen hier",
 	"Click here to select": "Klicke Sie zum Auswählen hier",
 	"Click here to select a csv file.": "Klicken Sie zum Auswählen einer CSV-Datei hier.",
 	"Click here to select a csv file.": "Klicken Sie zum Auswählen einer CSV-Datei hier.",
 	"Click here to select a py file.": "Klicken Sie zum Auswählen einer py-Datei hier.",
 	"Click here to select a py file.": "Klicken Sie zum Auswählen einer py-Datei hier.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentation",
 	"Documentation": "Dokumentation",
 	"Documents": "Dokumente",
 	"Documents": "Dokumente",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Ihre Daten bleiben sicher auf Ihrem lokal gehosteten Server.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Ihre Daten bleiben sicher auf Ihrem lokal gehosteten Server.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Haben Sie noch kein Benutzerkonto?",
 	"Don't have an account?": "Haben Sie noch kein Benutzerkonto?",
 	"don't install random functions from sources you don't trust.": "installieren Sie keine Funktionen aus Quellen, denen Sie nicht vertrauen.",
 	"don't install random functions from sources you don't trust.": "installieren Sie keine Funktionen aus Quellen, denen Sie nicht vertrauen.",
 	"don't install random tools from sources you don't trust.": "installieren Sie keine Werkzeuge aus Quellen, denen Sie nicht vertrauen.",
 	"don't install random tools from sources you don't trust.": "installieren Sie keine Werkzeuge aus Quellen, denen Sie nicht vertrauen.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Geben Sie die Blocküberlappung ein",
 	"Enter Chunk Overlap": "Geben Sie die Blocküberlappung ein",
 	"Enter Chunk Size": "Geben Sie die Blockgröße ein",
 	"Enter Chunk Size": "Geben Sie die Blockgröße ein",
 	"Enter description": "Geben Sie eine Beschreibung ein",
 	"Enter description": "Geben Sie eine Beschreibung ein",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "Geben Sie den Exa-API-Schlüssel ein",
 	"Enter Exa API Key": "Geben Sie den Exa-API-Schlüssel ein",
 	"Enter Github Raw URL": "Geben Sie die Github Raw-URL ein",
 	"Enter Github Raw URL": "Geben Sie die Github Raw-URL ein",
 	"Enter Google PSE API Key": "Geben Sie den Google PSE-API-Schlüssel ein",
 	"Enter Google PSE API Key": "Geben Sie den Google PSE-API-Schlüssel ein",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Wissen erfolgreich gelöscht.",
 	"Knowledge deleted successfully.": "Wissen erfolgreich gelöscht.",
 	"Knowledge reset successfully.": "Wissen erfolgreich zurückgesetzt.",
 	"Knowledge reset successfully.": "Wissen erfolgreich zurückgesetzt.",
 	"Knowledge updated successfully": "Wissen erfolgreich aktualisiert",
 	"Knowledge updated successfully": "Wissen erfolgreich aktualisiert",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Label",
 	"Label": "Label",
 	"Landing Page Mode": "Startseitenmodus",
 	"Landing Page Mode": "Startseitenmodus",
 	"Language": "Sprache",
 	"Language": "Sprache",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Leer lassen, um alle Modelle vom \"{{URL}}/models\"-Endpunkt einzuschließen",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Leer lassen, um alle Modelle vom \"{{URL}}/models\"-Endpunkt einzuschließen",
 	"Leave empty to include all models or select specific models": "Leer lassen, um alle Modelle einzuschließen oder spezifische Modelle auszuwählen",
 	"Leave empty to include all models or select specific models": "Leer lassen, um alle Modelle einzuschließen oder spezifische Modelle auszuwählen",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Leer lassen, um den Standardprompt zu verwenden, oder geben Sie einen benutzerdefinierten Prompt ein",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Leer lassen, um den Standardprompt zu verwenden, oder geben Sie einen benutzerdefinierten Prompt ein",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Hell",
 	"Light": "Hell",
 	"Listening...": "Höre zu...",
 	"Listening...": "Höre zu...",
 	"Llama.cpp": "Llama.cpp",
 	"Llama.cpp": "Llama.cpp",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokale Modelle",
 	"Local Models": "Lokale Modelle",
 	"Lost": "Verloren",
 	"Lost": "Verloren",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Von der OpenWebUI-Community",
+	"Made by Open WebUI Community": "Von der OpenWebUI-Community",
 	"Make sure to enclose them with": "Umschließe Variablen mit",
 	"Make sure to enclose them with": "Umschließe Variablen mit",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Stellen Sie sicher, dass sie eine workflow.json-Datei im API-Format von ComfyUI exportieren.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Stellen Sie sicher, dass sie eine workflow.json-Datei im API-Format von ComfyUI exportieren.",
 	"Manage": "Verwalten",
 	"Manage": "Verwalten",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Vorlesen",
 	"Read Aloud": "Vorlesen",
 	"Reasoning Effort": "Schlussfolgerungsaufwand",
 	"Reasoning Effort": "Schlussfolgerungsaufwand",
 	"Record voice": "Stimme aufnehmen",
 	"Record voice": "Stimme aufnehmen",
-	"Redirecting you to OpenWebUI Community": "Sie werden zur OpenWebUI-Community weitergeleitet",
+	"Redirecting you to Open WebUI Community": "Sie werden zur OpenWebUI-Community weitergeleitet",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduziert die Wahrscheinlichkeit, Unsinn zu generieren. Ein höherer Wert (z.B. 100) liefert vielfältigere Antworten, während ein niedrigerer Wert (z.B. 10) konservativer ist. (Standard: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduziert die Wahrscheinlichkeit, Unsinn zu generieren. Ein höherer Wert (z.B. 100) liefert vielfältigere Antworten, während ein niedrigerer Wert (z.B. 10) konservativer ist. (Standard: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Beziehen Sie sich auf sich selbst als \"Benutzer\" (z. B. \"Benutzer lernt Spanisch\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Beziehen Sie sich auf sich selbst als \"Benutzer\" (z. B. \"Benutzer lernt Spanisch\")",
 	"References from": "Referenzen aus",
 	"References from": "Referenzen aus",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
 	"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
 	"Share": "Teilen",
 	"Share": "Teilen",
 	"Share Chat": "Unterhaltung teilen",
 	"Share Chat": "Unterhaltung teilen",
-	"Share to OpenWebUI Community": "Mit OpenWebUI Community teilen",
+	"Share to Open WebUI Community": "Mit OpenWebUI Community teilen",
 	"Show": "Anzeigen",
 	"Show": "Anzeigen",
 	"Show \"What's New\" modal on login": "\"Was gibt's Neues\"-Modal beim Anmelden anzeigen",
 	"Show \"What's New\" modal on login": "\"Was gibt's Neues\"-Modal beim Anmelden anzeigen",
 	"Show Admin Details in Account Pending Overlay": "Admin-Details im Account-Pending-Overlay anzeigen",
 	"Show Admin Details in Account Pending Overlay": "Admin-Details im Account-Pending-Overlay anzeigen",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dadurch wird die Wissensdatenbank zurückgesetzt und alle Dateien synchronisiert. Möchten Sie fortfahren?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dadurch wird die Wissensdatenbank zurückgesetzt und alle Dateien synchronisiert. Möchten Sie fortfahren?",
 	"Thorough explanation": "Ausführliche Erklärung",
 	"Thorough explanation": "Ausführliche Erklärung",
 	"Thought for {{DURATION}}": "Nachgedacht für {{DURATION}}",
 	"Thought for {{DURATION}}": "Nachgedacht für {{DURATION}}",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika-Server-URL erforderlich.",
 	"Tika Server URL required.": "Tika-Server-URL erforderlich.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/dg-DG/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "",
 	"Click here to": "",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Click to select",
 	"Click here to select": "Click to select",
 	"Click here to select a csv file.": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "Documents",
 	"Documents": "Documents",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "does not connect external, data stays safe locally.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "does not connect external, data stays safe locally.",
+	"Domain Filter List": "",
 	"Don't have an account?": "No account? Much sad.",
 	"Don't have an account?": "No account? Much sad.",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Enter Overlap of Chunks",
 	"Enter Chunk Overlap": "Enter Overlap of Chunks",
 	"Enter Chunk Size": "Enter Size of Chunk",
 	"Enter Chunk Size": "Enter Size of Chunk",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "",
 	"Enter Github Raw URL": "",
 	"Enter Google PSE API Key": "",
 	"Enter Google PSE API Key": "",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Doge Speak",
 	"Language": "Doge Speak",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Light",
 	"Light": "Light",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "",
 	"LTR": "",
-	"Made by OpenWebUI Community": "Made by OpenWebUI Community",
+	"Made by Open WebUI Community": "Made by Open WebUI Community",
 	"Make sure to enclose them with": "Make sure to enclose them with",
 	"Make sure to enclose them with": "Make sure to enclose them with",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "",
 	"Read Aloud": "",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Record Bark",
 	"Record voice": "Record Bark",
-	"Redirecting you to OpenWebUI Community": "Redirecting you to OpenWebUI Community",
+	"Redirecting you to Open WebUI Community": "Redirecting you to Open WebUI Community",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Settings saved successfully! Very success!",
 	"Settings saved successfully!": "Settings saved successfully! Very success!",
 	"Share": "",
 	"Share": "",
 	"Share Chat": "",
 	"Share Chat": "",
-	"Share to OpenWebUI Community": "Share to OpenWebUI Community much community",
+	"Share to Open WebUI Community": "Share to Open WebUI Community much community",
 	"Show": "Show much show",
 	"Show": "Show much show",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "",
 	"Thorough explanation": "",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/el-GR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Κάντε κλικ εδώ για να",
 	"Click here to": "Κάντε κλικ εδώ για να",
 	"Click here to download user import template file.": "Κάντε κλικ εδώ για να κατεβάσετε το αρχείο προτύπου εισαγωγής χρήστη.",
 	"Click here to download user import template file.": "Κάντε κλικ εδώ για να κατεβάσετε το αρχείο προτύπου εισαγωγής χρήστη.",
 	"Click here to learn more about faster-whisper and see the available models.": "Κάντε κλικ εδώ για να μάθετε περισσότερα σχετικά με το faster-whisper και να δείτε τα διαθέσιμα μοντέλα.",
 	"Click here to learn more about faster-whisper and see the available models.": "Κάντε κλικ εδώ για να μάθετε περισσότερα σχετικά με το faster-whisper και να δείτε τα διαθέσιμα μοντέλα.",
+	"Click here to see available models.": "",
 	"Click here to select": "Κάντε κλικ εδώ για επιλογή",
 	"Click here to select": "Κάντε κλικ εδώ για επιλογή",
 	"Click here to select a csv file.": "Κάντε κλικ εδώ για να επιλέξετε ένα αρχείο csv.",
 	"Click here to select a csv file.": "Κάντε κλικ εδώ για να επιλέξετε ένα αρχείο csv.",
 	"Click here to select a py file.": "Κάντε κλικ εδώ για να επιλέξετε ένα αρχείο py.",
 	"Click here to select a py file.": "Κάντε κλικ εδώ για να επιλέξετε ένα αρχείο py.",
@@ -290,6 +291,7 @@
 	"Documentation": "Τεκμηρίωση",
 	"Documentation": "Τεκμηρίωση",
 	"Documents": "Έγγραφα",
 	"Documents": "Έγγραφα",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "δεν κάνει καμία εξωτερική σύνδεση, και τα δεδομένα σας παραμένουν ασφαλή στον τοπικά φιλοξενούμενο διακομιστή σας.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "δεν κάνει καμία εξωτερική σύνδεση, και τα δεδομένα σας παραμένουν ασφαλή στον τοπικά φιλοξενούμενο διακομιστή σας.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Δεν έχετε λογαριασμό;",
 	"Don't have an account?": "Δεν έχετε λογαριασμό;",
 	"don't install random functions from sources you don't trust.": "μην εγκαθιστάτε τυχαίες λειτουργίες από πηγές που δεν εμπιστεύεστε.",
 	"don't install random functions from sources you don't trust.": "μην εγκαθιστάτε τυχαίες λειτουργίες από πηγές που δεν εμπιστεύεστε.",
 	"don't install random tools from sources you don't trust.": "μην εγκαθιστάτε τυχαία εργαλεία από πηγές που δεν εμπιστεύεστε.",
 	"don't install random tools from sources you don't trust.": "μην εγκαθιστάτε τυχαία εργαλεία από πηγές που δεν εμπιστεύεστε.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Εισάγετε την Επικάλυψη Τμημάτων",
 	"Enter Chunk Overlap": "Εισάγετε την Επικάλυψη Τμημάτων",
 	"Enter Chunk Size": "Εισάγετε το Μέγεθος Τμημάτων",
 	"Enter Chunk Size": "Εισάγετε το Μέγεθος Τμημάτων",
 	"Enter description": "Εισάγετε την περιγραφή",
 	"Enter description": "Εισάγετε την περιγραφή",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Εισάγετε το Github Raw URL",
 	"Enter Github Raw URL": "Εισάγετε το Github Raw URL",
 	"Enter Google PSE API Key": "Εισάγετε το Κλειδί API Google PSE",
 	"Enter Google PSE API Key": "Εισάγετε το Κλειδί API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Η γνώση διαγράφηκε με επιτυχία.",
 	"Knowledge deleted successfully.": "Η γνώση διαγράφηκε με επιτυχία.",
 	"Knowledge reset successfully.": "Η γνώση επαναφέρθηκε με επιτυχία.",
 	"Knowledge reset successfully.": "Η γνώση επαναφέρθηκε με επιτυχία.",
 	"Knowledge updated successfully": "Η γνώση ενημερώθηκε με επιτυχία",
 	"Knowledge updated successfully": "Η γνώση ενημερώθηκε με επιτυχία",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Ετικέτα",
 	"Label": "Ετικέτα",
 	"Landing Page Mode": "Λειτουργία Σελίδας Άφιξης",
 	"Landing Page Mode": "Λειτουργία Σελίδας Άφιξης",
 	"Language": "Γλώσσα",
 	"Language": "Γλώσσα",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Αφήστε κενό για να συμπεριλάβετε όλα τα μοντέλα από το endpoint \"{{URL}}/models\"",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Αφήστε κενό για να συμπεριλάβετε όλα τα μοντέλα από το endpoint \"{{URL}}/models\"",
 	"Leave empty to include all models or select specific models": "Αφήστε κενό για να χρησιμοποιήσετε όλα τα μοντέλα ή επιλέξτε συγκεκριμένα μοντέλα",
 	"Leave empty to include all models or select specific models": "Αφήστε κενό για να χρησιμοποιήσετε όλα τα μοντέλα ή επιλέξτε συγκεκριμένα μοντέλα",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Αφήστε κενό για να χρησιμοποιήσετε την προεπιλεγμένη προτροπή, ή εισάγετε μια προσαρμοσμένη προτροπή",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Αφήστε κενό για να χρησιμοποιήσετε την προεπιλεγμένη προτροπή, ή εισάγετε μια προσαρμοσμένη προτροπή",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Φως",
 	"Light": "Φως",
 	"Listening...": "Ακούγεται...",
 	"Listening...": "Ακούγεται...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Τοπικά Μοντέλα",
 	"Local Models": "Τοπικά Μοντέλα",
 	"Lost": "Χαμένος",
 	"Lost": "Χαμένος",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Δημιουργήθηκε από την Κοινότητα OpenWebUI",
+	"Made by Open WebUI Community": "Δημιουργήθηκε από την Κοινότητα OpenWebUI",
 	"Make sure to enclose them with": "Βεβαιωθείτε ότι τα περικλείετε με",
 	"Make sure to enclose them with": "Βεβαιωθείτε ότι τα περικλείετε με",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Βεβαιωθείτε ότι εξάγετε ένα αρχείο workflow.json ως μορφή API από το ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Βεβαιωθείτε ότι εξάγετε ένα αρχείο workflow.json ως μορφή API από το ComfyUI.",
 	"Manage": "Διαχείριση",
 	"Manage": "Διαχείριση",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Ανάγνωση Φωναχτά",
 	"Read Aloud": "Ανάγνωση Φωναχτά",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Εγγραφή φωνής",
 	"Record voice": "Εγγραφή φωνής",
-	"Redirecting you to OpenWebUI Community": "Μετακατεύθυνση στην Κοινότητα OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Μετακατεύθυνση στην Κοινότητα OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Μειώνει την πιθανότητα δημιουργίας ανοησιών. Μια υψηλότερη τιμή (π.χ. 100) θα δώσει πιο ποικίλες απαντήσεις, ενώ μια χαμηλότερη τιμή (π.χ. 10) θα δημιουργήσει πιο συντηρητικές απαντήσεις. (Προεπιλογή: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Μειώνει την πιθανότητα δημιουργίας ανοησιών. Μια υψηλότερη τιμή (π.χ. 100) θα δώσει πιο ποικίλες απαντήσεις, ενώ μια χαμηλότερη τιμή (π.χ. 10) θα δημιουργήσει πιο συντηρητικές απαντήσεις. (Προεπιλογή: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Αναφέρεστε στον εαυτό σας ως \"User\" (π.χ., \"User μαθαίνει Ισπανικά\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Αναφέρεστε στον εαυτό σας ως \"User\" (π.χ., \"User μαθαίνει Ισπανικά\")",
 	"References from": "Αναφορές από",
 	"References from": "Αναφορές από",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Οι Ρυθμίσεις αποθηκεύτηκαν με επιτυχία!",
 	"Settings saved successfully!": "Οι Ρυθμίσεις αποθηκεύτηκαν με επιτυχία!",
 	"Share": "Κοινή Χρήση",
 	"Share": "Κοινή Χρήση",
 	"Share Chat": "Κοινή Χρήση Συνομιλίας",
 	"Share Chat": "Κοινή Χρήση Συνομιλίας",
-	"Share to OpenWebUI Community": "Κοινή Χρήση στην Κοινότητα OpenWebUI",
+	"Share to Open WebUI Community": "Κοινή Χρήση στην Κοινότητα OpenWebUI",
 	"Show": "Εμφάνιση",
 	"Show": "Εμφάνιση",
 	"Show \"What's New\" modal on login": "Εμφάνιση του παράθυρου \"Τι νέο υπάρχει\" κατά την είσοδο",
 	"Show \"What's New\" modal on login": "Εμφάνιση του παράθυρου \"Τι νέο υπάρχει\" κατά την είσοδο",
 	"Show Admin Details in Account Pending Overlay": "Εμφάνιση Λεπτομερειών Διαχειριστή στο Υπέρθεση Εκκρεμής Λογαριασμού",
 	"Show Admin Details in Account Pending Overlay": "Εμφάνιση Λεπτομερειών Διαχειριστή στο Υπέρθεση Εκκρεμής Λογαριασμού",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Αυτό θα επαναφέρει τη βάση γνώσης και θα συγχρονίσει όλα τα αρχεία. Θέλετε να συνεχίσετε;",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Αυτό θα επαναφέρει τη βάση γνώσης και θα συγχρονίσει όλα τα αρχεία. Θέλετε να συνεχίσετε;",
 	"Thorough explanation": "Λεπτομερής εξήγηση",
 	"Thorough explanation": "Λεπτομερής εξήγηση",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Απαιτείται το URL διακομιστή Tika.",
 	"Tika Server URL required.": "Απαιτείται το URL διακομιστή Tika.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/en-GB/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "",
 	"Click here to": "",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "",
 	"Click here to select": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "",
 	"Documents": "",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "",
+	"Domain Filter List": "",
 	"Don't have an account?": "",
 	"Don't have an account?": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "",
 	"Enter Chunk Overlap": "",
 	"Enter Chunk Size": "",
 	"Enter Chunk Size": "",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "",
 	"Enter Github Raw URL": "",
 	"Enter Google PSE API Key": "",
 	"Enter Google PSE API Key": "",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "",
 	"Language": "",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "",
 	"Light": "",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "",
 	"LTR": "",
-	"Made by OpenWebUI Community": "",
+	"Made by Open WebUI Community": "",
 	"Make sure to enclose them with": "",
 	"Make sure to enclose them with": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "",
 	"Read Aloud": "",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "",
 	"Record voice": "",
-	"Redirecting you to OpenWebUI Community": "",
+	"Redirecting you to Open WebUI Community": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "",
 	"Settings saved successfully!": "",
 	"Share": "",
 	"Share": "",
 	"Share Chat": "",
 	"Share Chat": "",
-	"Share to OpenWebUI Community": "",
+	"Share to Open WebUI Community": "",
 	"Show": "",
 	"Show": "",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "",
 	"Thorough explanation": "",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 9 - 3
src/lib/i18n/locales/en-US/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "",
 	"Click here to": "",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "",
 	"Click here to select": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a csv file.": "",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "",
 	"Documents": "",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "",
+	"Domain Filter List": "",
 	"Don't have an account?": "",
 	"Don't have an account?": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "",
 	"Enter Chunk Overlap": "",
 	"Enter Chunk Size": "",
 	"Enter Chunk Size": "",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "",
 	"Enter Github Raw URL": "",
 	"Enter Google PSE API Key": "",
 	"Enter Google PSE API Key": "",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "",
 	"Language": "",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "",
 	"Light": "",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "",
 	"LTR": "",
-	"Made by OpenWebUI Community": "",
+	"Made by Open WebUI Community": "",
 	"Make sure to enclose them with": "",
 	"Make sure to enclose them with": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "",
 	"Read Aloud": "",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "",
 	"Record voice": "",
-	"Redirecting you to OpenWebUI Community": "",
+	"Redirecting you to Open WebUI Community": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "",
 	"Settings saved successfully!": "",
 	"Share": "",
 	"Share": "",
 	"Share Chat": "",
 	"Share Chat": "",
-	"Share to OpenWebUI Community": "",
+	"Share to Open WebUI Community": "",
 	"Show": "",
 	"Show": "",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",

文件差異過大導致無法顯示
+ 307 - 301
src/lib/i18n/locales/es-ES/translation.json


+ 10 - 3
src/lib/i18n/locales/eu-ES/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klikatu hemen",
 	"Click here to": "Klikatu hemen",
 	"Click here to download user import template file.": "Klikatu hemen erabiltzaileen inportazio txantiloia deskargatzeko.",
 	"Click here to download user import template file.": "Klikatu hemen erabiltzaileen inportazio txantiloia deskargatzeko.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikatu hemen faster-whisper-i buruz gehiago ikasteko eta eredu erabilgarriak ikusteko.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikatu hemen faster-whisper-i buruz gehiago ikasteko eta eredu erabilgarriak ikusteko.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klikatu hemen hautatzeko",
 	"Click here to select": "Klikatu hemen hautatzeko",
 	"Click here to select a csv file.": "Klikatu hemen csv fitxategi bat hautatzeko.",
 	"Click here to select a csv file.": "Klikatu hemen csv fitxategi bat hautatzeko.",
 	"Click here to select a py file.": "Klikatu hemen py fitxategi bat hautatzeko.",
 	"Click here to select a py file.": "Klikatu hemen py fitxategi bat hautatzeko.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentazioa",
 	"Documentation": "Dokumentazioa",
 	"Documents": "Dokumentuak",
 	"Documents": "Dokumentuak",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ez du kanpo konexiorik egiten, eta zure datuak modu seguruan mantentzen dira zure zerbitzari lokalean.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ez du kanpo konexiorik egiten, eta zure datuak modu seguruan mantentzen dira zure zerbitzari lokalean.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Ez duzu konturik?",
 	"Don't have an account?": "Ez duzu konturik?",
 	"don't install random functions from sources you don't trust.": "ez instalatu fidagarriak ez diren iturrietatik datozen ausazko funtzioak.",
 	"don't install random functions from sources you don't trust.": "ez instalatu fidagarriak ez diren iturrietatik datozen ausazko funtzioak.",
 	"don't install random tools from sources you don't trust.": "ez instalatu fidagarriak ez diren iturrietatik datozen ausazko tresnak.",
 	"don't install random tools from sources you don't trust.": "ez instalatu fidagarriak ez diren iturrietatik datozen ausazko tresnak.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Sartu Zatien Gainjartzea (chunk overlap)",
 	"Enter Chunk Overlap": "Sartu Zatien Gainjartzea (chunk overlap)",
 	"Enter Chunk Size": "Sartu Zati Tamaina",
 	"Enter Chunk Size": "Sartu Zati Tamaina",
 	"Enter description": "Sartu deskribapena",
 	"Enter description": "Sartu deskribapena",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Sartu Github Raw URLa",
 	"Enter Github Raw URL": "Sartu Github Raw URLa",
 	"Enter Google PSE API Key": "Sartu Google PSE API Gakoa",
 	"Enter Google PSE API Key": "Sartu Google PSE API Gakoa",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Ezagutza ongi ezabatu da.",
 	"Knowledge deleted successfully.": "Ezagutza ongi ezabatu da.",
 	"Knowledge reset successfully.": "Ezagutza ongi berrezarri da.",
 	"Knowledge reset successfully.": "Ezagutza ongi berrezarri da.",
 	"Knowledge updated successfully": "Ezagutza ongi eguneratu da.",
 	"Knowledge updated successfully": "Ezagutza ongi eguneratu da.",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Etiketa",
 	"Label": "Etiketa",
 	"Landing Page Mode": "Hasiera Orriaren Modua",
 	"Landing Page Mode": "Hasiera Orriaren Modua",
 	"Language": "Hizkuntza",
 	"Language": "Hizkuntza",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Utzi hutsik \"{{URL}}/models\" endpointuko eredu guztiak sartzeko",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Utzi hutsik \"{{URL}}/models\" endpointuko eredu guztiak sartzeko",
 	"Leave empty to include all models or select specific models": "Utzi hutsik eredu guztiak sartzeko edo hautatu eredu zehatzak",
 	"Leave empty to include all models or select specific models": "Utzi hutsik eredu guztiak sartzeko edo hautatu eredu zehatzak",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Utzi hutsik prompt lehenetsia erabiltzeko, edo sartu prompt pertsonalizatu bat",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Utzi hutsik prompt lehenetsia erabiltzeko, edo sartu prompt pertsonalizatu bat",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Argia",
 	"Light": "Argia",
 	"Listening...": "Entzuten...",
 	"Listening...": "Entzuten...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Modelo lokalak",
 	"Local Models": "Modelo lokalak",
 	"Lost": "Galduta",
 	"Lost": "Galduta",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "OpenWebUI Komunitateak egina",
+	"Made by Open WebUI Community": "OpenWebUI Komunitateak egina",
 	"Make sure to enclose them with": "Ziurtatu hauek gehitzen dituzula",
 	"Make sure to enclose them with": "Ziurtatu hauek gehitzen dituzula",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Ziurtatu workflow.json fitxategia API formatu gisa esportatzen duzula ComfyUI-tik.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Ziurtatu workflow.json fitxategia API formatu gisa esportatzen duzula ComfyUI-tik.",
 	"Manage": "Kudeatu",
 	"Manage": "Kudeatu",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Irakurri ozen",
 	"Read Aloud": "Irakurri ozen",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Grabatu ahotsa",
 	"Record voice": "Grabatu ahotsa",
-	"Redirecting you to OpenWebUI Community": "OpenWebUI Komunitatera berbideratzen",
+	"Redirecting you to Open WebUI Community": "OpenWebUI Komunitatera berbideratzen",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Zentzugabekeriak sortzeko probabilitatea murrizten du. Balio altuago batek (adib. 100) erantzun anitzagoak emango ditu, balio baxuago batek (adib. 10) kontserbadoreagoa izango den bitartean. (Lehenetsia: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Zentzugabekeriak sortzeko probabilitatea murrizten du. Balio altuago batek (adib. 100) erantzun anitzagoak emango ditu, balio baxuago batek (adib. 10) kontserbadoreagoa izango den bitartean. (Lehenetsia: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Egin erreferentzia zure buruari \"Erabiltzaile\" gisa (adib., \"Erabiltzailea gaztelania ikasten ari da\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Egin erreferentzia zure buruari \"Erabiltzaile\" gisa (adib., \"Erabiltzailea gaztelania ikasten ari da\")",
 	"References from": "Erreferentziak hemendik",
 	"References from": "Erreferentziak hemendik",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Ezarpenak ongi gorde dira!",
 	"Settings saved successfully!": "Ezarpenak ongi gorde dira!",
 	"Share": "Partekatu",
 	"Share": "Partekatu",
 	"Share Chat": "Partekatu txata",
 	"Share Chat": "Partekatu txata",
-	"Share to OpenWebUI Community": "Partekatu OpenWebUI komunitatearekin",
+	"Share to Open WebUI Community": "Partekatu OpenWebUI komunitatearekin",
 	"Show": "Erakutsi",
 	"Show": "Erakutsi",
 	"Show \"What's New\" modal on login": "Erakutsi \"Berritasunak\" modala saioa hastean",
 	"Show \"What's New\" modal on login": "Erakutsi \"Berritasunak\" modala saioa hastean",
 	"Show Admin Details in Account Pending Overlay": "Erakutsi administratzaile xehetasunak kontu zain geruzan",
 	"Show Admin Details in Account Pending Overlay": "Erakutsi administratzaile xehetasunak kontu zain geruzan",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Honek ezagutza-basea berrezarri eta fitxategi guztiak sinkronizatuko ditu. Jarraitu nahi duzu?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Honek ezagutza-basea berrezarri eta fitxategi guztiak sinkronizatuko ditu. Jarraitu nahi duzu?",
 	"Thorough explanation": "Azalpen sakona",
 	"Thorough explanation": "Azalpen sakona",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika zerbitzariaren URLa beharrezkoa da.",
 	"Tika Server URL required.": "Tika zerbitzariaren URLa beharrezkoa da.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/fa-IR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "برای کمک اینجا را کلیک کنید.",
 	"Click here to": "برای کمک اینجا را کلیک کنید.",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "برای انتخاب اینجا کلیک کنید",
 	"Click here to select": "برای انتخاب اینجا کلیک کنید",
 	"Click here to select a csv file.": "برای انتخاب یک فایل csv اینجا را کلیک کنید.",
 	"Click here to select a csv file.": "برای انتخاب یک فایل csv اینجا را کلیک کنید.",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "اسناد",
 	"Documents": "اسناد",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "هیچ اتصال خارجی ایجاد نمی کند و داده های شما به طور ایمن در سرور میزبان محلی شما باقی می ماند.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "هیچ اتصال خارجی ایجاد نمی کند و داده های شما به طور ایمن در سرور میزبان محلی شما باقی می ماند.",
+	"Domain Filter List": "",
 	"Don't have an account?": "حساب کاربری ندارید؟",
 	"Don't have an account?": "حساب کاربری ندارید؟",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "مقدار Chunk Overlap را وارد کنید",
 	"Enter Chunk Overlap": "مقدار Chunk Overlap را وارد کنید",
 	"Enter Chunk Size": "مقدار Chunk Size را وارد کنید",
 	"Enter Chunk Size": "مقدار Chunk Size را وارد کنید",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "ادرس Github Raw را وارد کنید",
 	"Enter Github Raw URL": "ادرس Github Raw را وارد کنید",
 	"Enter Google PSE API Key": "کلید API گوگل PSE را وارد کنید",
 	"Enter Google PSE API Key": "کلید API گوگل PSE را وارد کنید",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "زبان",
 	"Language": "زبان",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "روشن",
 	"Light": "روشن",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "ساخته شده توسط OpenWebUI Community",
+	"Made by Open WebUI Community": "ساخته شده توسط OpenWebUI Community",
 	"Make sure to enclose them with": "مطمئن شوید که آنها را با این محصور کنید:",
 	"Make sure to enclose them with": "مطمئن شوید که آنها را با این محصور کنید:",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "خواندن به صورت صوتی",
 	"Read Aloud": "خواندن به صورت صوتی",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "ضبط صدا",
 	"Record voice": "ضبط صدا",
-	"Redirecting you to OpenWebUI Community": "در حال هدایت به OpenWebUI Community",
+	"Redirecting you to Open WebUI Community": "در حال هدایت به OpenWebUI Community",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "تنظیمات با موفقیت ذخیره شد!",
 	"Settings saved successfully!": "تنظیمات با موفقیت ذخیره شد!",
 	"Share": "اشتراک\u200cگذاری",
 	"Share": "اشتراک\u200cگذاری",
 	"Share Chat": "اشتراک\u200cگذاری چت",
 	"Share Chat": "اشتراک\u200cگذاری چت",
-	"Share to OpenWebUI Community": "اشتراک گذاری با OpenWebUI Community",
+	"Share to Open WebUI Community": "اشتراک گذاری با OpenWebUI Community",
 	"Show": "نمایش",
 	"Show": "نمایش",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "توضیح کامل",
 	"Thorough explanation": "توضیح کامل",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/fi-FI/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klikkaa tästä",
 	"Click here to": "Klikkaa tästä",
 	"Click here to download user import template file.": "Lataa käyttäjien tuontipohjatiedosto klikkaamalla tästä.",
 	"Click here to download user import template file.": "Lataa käyttäjien tuontipohjatiedosto klikkaamalla tästä.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikkaa tästä oppiaksesi lisää faster-whisperista ja nähdäksesi saatavilla olevat mallit.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikkaa tästä oppiaksesi lisää faster-whisperista ja nähdäksesi saatavilla olevat mallit.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klikkaa tästä valitaksesi",
 	"Click here to select": "Klikkaa tästä valitaksesi",
 	"Click here to select a csv file.": "Klikkaa tästä valitaksesi CSV-tiedosto.",
 	"Click here to select a csv file.": "Klikkaa tästä valitaksesi CSV-tiedosto.",
 	"Click here to select a py file.": "Klikkaa tästä valitaksesi py-tiedosto.",
 	"Click here to select a py file.": "Klikkaa tästä valitaksesi py-tiedosto.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentaatio",
 	"Documentation": "Dokumentaatio",
 	"Documents": "Asiakirjat",
 	"Documents": "Asiakirjat",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ei tee ulkoisia yhteyksiä, ja tietosi pysyvät turvallisesti paikallisesti isännöidyllä palvelimellasi.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ei tee ulkoisia yhteyksiä, ja tietosi pysyvät turvallisesti paikallisesti isännöidyllä palvelimellasi.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Eikö sinulla ole tiliä?",
 	"Don't have an account?": "Eikö sinulla ole tiliä?",
 	"don't install random functions from sources you don't trust.": "älä asenna satunnaisia toimintoja lähteistä, joihin et luota.",
 	"don't install random functions from sources you don't trust.": "älä asenna satunnaisia toimintoja lähteistä, joihin et luota.",
 	"don't install random tools from sources you don't trust.": "älä asenna satunnaisia työkaluja lähteistä, joihin et luota.",
 	"don't install random tools from sources you don't trust.": "älä asenna satunnaisia työkaluja lähteistä, joihin et luota.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Syötä osien päällekkäisyys",
 	"Enter Chunk Overlap": "Syötä osien päällekkäisyys",
 	"Enter Chunk Size": "Syötä osien koko",
 	"Enter Chunk Size": "Syötä osien koko",
 	"Enter description": "Kirjoita kuvaus",
 	"Enter description": "Kirjoita kuvaus",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Kirjoita Github Raw -URL-osoite",
 	"Enter Github Raw URL": "Kirjoita Github Raw -URL-osoite",
 	"Enter Google PSE API Key": "Kirjoita Google PSE API -avain",
 	"Enter Google PSE API Key": "Kirjoita Google PSE API -avain",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Tietokanta poistettu onnistuneesti.",
 	"Knowledge deleted successfully.": "Tietokanta poistettu onnistuneesti.",
 	"Knowledge reset successfully.": "Tietokanta nollattu onnistuneesti.",
 	"Knowledge reset successfully.": "Tietokanta nollattu onnistuneesti.",
 	"Knowledge updated successfully": "Tietokanta päivitetty onnistuneesti",
 	"Knowledge updated successfully": "Tietokanta päivitetty onnistuneesti",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Tunniste",
 	"Label": "Tunniste",
 	"Landing Page Mode": "Etusivun tila",
 	"Landing Page Mode": "Etusivun tila",
 	"Language": "Kieli",
 	"Language": "Kieli",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Jätä tyhjäksi, jos haluat sisällyttää kaikki mallit \"{{URL}}/models\" -päätepistestä",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Jätä tyhjäksi, jos haluat sisällyttää kaikki mallit \"{{URL}}/models\" -päätepistestä",
 	"Leave empty to include all models or select specific models": "Jätä tyhjäksi, jos haluat sisällyttää kaikki mallit tai valitse tietyt mallit",
 	"Leave empty to include all models or select specific models": "Jätä tyhjäksi, jos haluat sisällyttää kaikki mallit tai valitse tietyt mallit",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Jätä tyhjäksi käyttääksesi oletuskehotetta tai kirjoita mukautettu kehote",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Jätä tyhjäksi käyttääksesi oletuskehotetta tai kirjoita mukautettu kehote",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Vaalea",
 	"Light": "Vaalea",
 	"Listening...": "Kuuntelee...",
 	"Listening...": "Kuuntelee...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Paikalliset mallit",
 	"Local Models": "Paikalliset mallit",
 	"Lost": "Mennyt",
 	"Lost": "Mennyt",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Tehnyt OpenWebUI-yhteisö",
+	"Made by Open WebUI Community": "Tehnyt OpenWebUI-yhteisö",
 	"Make sure to enclose them with": "Varmista, että suljet ne",
 	"Make sure to enclose them with": "Varmista, että suljet ne",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Muista viedä workflow.json-tiedosto API-muodossa ComfyUI:sta.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Muista viedä workflow.json-tiedosto API-muodossa ComfyUI:sta.",
 	"Manage": "Hallitse",
 	"Manage": "Hallitse",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Lue ääneen",
 	"Read Aloud": "Lue ääneen",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Nauhoita ääni",
 	"Record voice": "Nauhoita ääni",
-	"Redirecting you to OpenWebUI Community": "Ohjataan sinut OpenWebUI-yhteisöön",
+	"Redirecting you to Open WebUI Community": "Ohjataan sinut OpenWebUI-yhteisöön",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Vähentää merkityksetöntä sisältöä tuottavan todennäköisyyttä. Korkeampi arvo (esim. 100) antaa monipuolisempia vastauksia, kun taas alhaisempi arvo (esim. 10) on konservatiivisempi. (Oletus: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Vähentää merkityksetöntä sisältöä tuottavan todennäköisyyttä. Korkeampi arvo (esim. 100) antaa monipuolisempia vastauksia, kun taas alhaisempi arvo (esim. 10) on konservatiivisempi. (Oletus: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Viittaa itseen \"Käyttäjänä\" (esim. \"Käyttäjä opiskelee espanjaa\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Viittaa itseen \"Käyttäjänä\" (esim. \"Käyttäjä opiskelee espanjaa\")",
 	"References from": "Viitteet lähteistä",
 	"References from": "Viitteet lähteistä",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Asetukset tallennettu onnistuneesti!",
 	"Settings saved successfully!": "Asetukset tallennettu onnistuneesti!",
 	"Share": "Jaa",
 	"Share": "Jaa",
 	"Share Chat": "Jaa keskustelu",
 	"Share Chat": "Jaa keskustelu",
-	"Share to OpenWebUI Community": "Jaa OpenWebUI-yhteisöön",
+	"Share to Open WebUI Community": "Jaa OpenWebUI-yhteisöön",
 	"Show": "Näytä",
 	"Show": "Näytä",
 	"Show \"What's New\" modal on login": "Näytä \"Mitä uutta\" -modaali kirjautumisen yhteydessä",
 	"Show \"What's New\" modal on login": "Näytä \"Mitä uutta\" -modaali kirjautumisen yhteydessä",
 	"Show Admin Details in Account Pending Overlay": "Näytä ylläpitäjän tiedot odottavan tilin päällä",
 	"Show Admin Details in Account Pending Overlay": "Näytä ylläpitäjän tiedot odottavan tilin päällä",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Tämä nollaa tietokannan ja synkronoi kaikki tiedostot. Haluatko jatkaa?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Tämä nollaa tietokannan ja synkronoi kaikki tiedostot. Haluatko jatkaa?",
 	"Thorough explanation": "Perusteellinen selitys",
 	"Thorough explanation": "Perusteellinen selitys",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika Server URL vaaditaan.",
 	"Tika Server URL required.": "Tika Server URL vaaditaan.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/fr-CA/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Cliquez ici pour",
 	"Click here to": "Cliquez ici pour",
 	"Click here to download user import template file.": "Cliquez ici pour télécharger le fichier modèle d'importation utilisateur.",
 	"Click here to download user import template file.": "Cliquez ici pour télécharger le fichier modèle d'importation utilisateur.",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Cliquez ici pour sélectionner",
 	"Click here to select": "Cliquez ici pour sélectionner",
 	"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier CSV.",
 	"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier CSV.",
 	"Click here to select a py file.": "Cliquez ici pour sélectionner un fichier .py.",
 	"Click here to select a py file.": "Cliquez ici pour sélectionner un fichier .py.",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentation",
 	"Documentation": "Documentation",
 	"Documents": "Documents",
 	"Documents": "Documents",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ne fait aucune connexion externe et garde vos données en sécurité sur votre serveur local.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ne fait aucune connexion externe et garde vos données en sécurité sur votre serveur local.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Vous n'avez pas de compte ?",
 	"Don't have an account?": "Vous n'avez pas de compte ?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Entrez le chevauchement de chunk",
 	"Enter Chunk Overlap": "Entrez le chevauchement de chunk",
 	"Enter Chunk Size": "Entrez la taille de bloc",
 	"Enter Chunk Size": "Entrez la taille de bloc",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Entrez l'URL brute de GitHub",
 	"Enter Github Raw URL": "Entrez l'URL brute de GitHub",
 	"Enter Google PSE API Key": "Entrez la clé API Google PSE",
 	"Enter Google PSE API Key": "Entrez la clé API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Langue",
 	"Language": "Langue",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Lumineux",
 	"Light": "Lumineux",
 	"Listening...": "En train d'écouter...",
 	"Listening...": "En train d'écouter...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Modèles locaux",
 	"Local Models": "Modèles locaux",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
+	"Made by Open WebUI Community": "Réalisé par la communauté OpenWebUI",
 	"Make sure to enclose them with": "Assurez-vous de les inclure dans",
 	"Make sure to enclose them with": "Assurez-vous de les inclure dans",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Gérer",
 	"Manage": "Gérer",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Lire à haute voix",
 	"Read Aloud": "Lire à haute voix",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Enregistrer la voix",
 	"Record voice": "Enregistrer la voix",
-	"Redirecting you to OpenWebUI Community": "Redirection vers la communauté OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Redirection vers la communauté OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Paramètres enregistrés avec succès !",
 	"Settings saved successfully!": "Paramètres enregistrés avec succès !",
 	"Share": "Partager",
 	"Share": "Partager",
 	"Share Chat": "Partage de conversation",
 	"Share Chat": "Partage de conversation",
-	"Share to OpenWebUI Community": "Partager avec la communauté OpenWebUI",
+	"Share to Open WebUI Community": "Partager avec la communauté OpenWebUI",
 	"Show": "Montrer",
 	"Show": "Montrer",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Afficher les détails de l'administrateur dans la superposition en attente du compte",
 	"Show Admin Details in Account Pending Overlay": "Afficher les détails de l'administrateur dans la superposition en attente du compte",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Explication approfondie",
 	"Thorough explanation": "Explication approfondie",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/fr-FR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Cliquez ici pour",
 	"Click here to": "Cliquez ici pour",
 	"Click here to download user import template file.": "Cliquez ici pour télécharger le fichier modèle d'importation des utilisateurs.",
 	"Click here to download user import template file.": "Cliquez ici pour télécharger le fichier modèle d'importation des utilisateurs.",
 	"Click here to learn more about faster-whisper and see the available models.": "Cliquez ici pour en savoir plus sur faster-whisper et voir les modèles disponibles.",
 	"Click here to learn more about faster-whisper and see the available models.": "Cliquez ici pour en savoir plus sur faster-whisper et voir les modèles disponibles.",
+	"Click here to see available models.": "",
 	"Click here to select": "Cliquez ici pour sélectionner",
 	"Click here to select": "Cliquez ici pour sélectionner",
 	"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier .csv.",
 	"Click here to select a csv file.": "Cliquez ici pour sélectionner un fichier .csv.",
 	"Click here to select a py file.": "Cliquez ici pour sélectionner un fichier .py.",
 	"Click here to select a py file.": "Cliquez ici pour sélectionner un fichier .py.",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentation",
 	"Documentation": "Documentation",
 	"Documents": "Documents",
 	"Documents": "Documents",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "n'établit aucune connexion externe et garde vos données en sécurité sur votre serveur local.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "n'établit aucune connexion externe et garde vos données en sécurité sur votre serveur local.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Vous n'avez pas de compte ?",
 	"Don't have an account?": "Vous n'avez pas de compte ?",
 	"don't install random functions from sources you don't trust.": "n'installez pas de fonctions aléatoires provenant de sources auxquelles vous ne faites pas confiance.",
 	"don't install random functions from sources you don't trust.": "n'installez pas de fonctions aléatoires provenant de sources auxquelles vous ne faites pas confiance.",
 	"don't install random tools from sources you don't trust.": "n'installez pas d'outils aléatoires provenant de sources auxquelles vous ne faites pas confiance.",
 	"don't install random tools from sources you don't trust.": "n'installez pas d'outils aléatoires provenant de sources auxquelles vous ne faites pas confiance.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Entrez le chevauchement des chunks",
 	"Enter Chunk Overlap": "Entrez le chevauchement des chunks",
 	"Enter Chunk Size": "Entrez la taille des chunks",
 	"Enter Chunk Size": "Entrez la taille des chunks",
 	"Enter description": "Entrez la description",
 	"Enter description": "Entrez la description",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Entrez l'URL brute de GitHub",
 	"Enter Github Raw URL": "Entrez l'URL brute de GitHub",
 	"Enter Google PSE API Key": "Entrez la clé API Google PSE",
 	"Enter Google PSE API Key": "Entrez la clé API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Connaissance supprimée avec succès.",
 	"Knowledge deleted successfully.": "Connaissance supprimée avec succès.",
 	"Knowledge reset successfully.": "Connaissance réinitialisée avec succès.",
 	"Knowledge reset successfully.": "Connaissance réinitialisée avec succès.",
 	"Knowledge updated successfully": "Connaissance mise à jour avec succès",
 	"Knowledge updated successfully": "Connaissance mise à jour avec succès",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Étiquette",
 	"Label": "Étiquette",
 	"Landing Page Mode": "Mode de la page d'accueil",
 	"Landing Page Mode": "Mode de la page d'accueil",
 	"Language": "Langue",
 	"Language": "Langue",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Laissez vide pour inclure tous les modèles depuis le point de terminaison \"{{URL}}/models\"",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Laissez vide pour inclure tous les modèles depuis le point de terminaison \"{{URL}}/models\"",
 	"Leave empty to include all models or select specific models": "Laissez vide pour inclure tous les modèles ou sélectionnez des modèles spécifiques",
 	"Leave empty to include all models or select specific models": "Laissez vide pour inclure tous les modèles ou sélectionnez des modèles spécifiques",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Laissez vide pour utiliser le prompt par défaut, ou entrez un prompt personnalisé",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Laissez vide pour utiliser le prompt par défaut, ou entrez un prompt personnalisé",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Clair",
 	"Light": "Clair",
 	"Listening...": "Écoute en cours...",
 	"Listening...": "Écoute en cours...",
 	"Llama.cpp": "Llama.cpp",
 	"Llama.cpp": "Llama.cpp",
@@ -574,7 +580,7 @@
 	"Local Models": "Modèles locaux",
 	"Local Models": "Modèles locaux",
 	"Lost": "Perdu",
 	"Lost": "Perdu",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Réalisé par la communauté OpenWebUI",
+	"Made by Open WebUI Community": "Réalisé par la communauté OpenWebUI",
 	"Make sure to enclose them with": "Assurez-vous de les inclure dans",
 	"Make sure to enclose them with": "Assurez-vous de les inclure dans",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Veillez à exporter un fichier workflow.json au format API depuis ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Veillez à exporter un fichier workflow.json au format API depuis ComfyUI.",
 	"Manage": "Gérer",
 	"Manage": "Gérer",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Lire à haute voix",
 	"Read Aloud": "Lire à haute voix",
 	"Reasoning Effort": "Effort de raisonnement",
 	"Reasoning Effort": "Effort de raisonnement",
 	"Record voice": "Enregistrer la voix",
 	"Record voice": "Enregistrer la voix",
-	"Redirecting you to OpenWebUI Community": "Redirection vers la communauté OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Redirection vers la communauté OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Réduit la probabilité de générer des non-sens. Une valeur plus élevée (par exemple 100) donnera des réponses plus diversifiées, tandis qu'une valeur plus basse (par exemple 10) sera plus conservatrice. (Par défaut : 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Réduit la probabilité de générer des non-sens. Une valeur plus élevée (par exemple 100) donnera des réponses plus diversifiées, tandis qu'une valeur plus basse (par exemple 10) sera plus conservatrice. (Par défaut : 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)",
 	"References from": "Références de",
 	"References from": "Références de",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Paramètres enregistrés avec succès !",
 	"Settings saved successfully!": "Paramètres enregistrés avec succès !",
 	"Share": "Partager",
 	"Share": "Partager",
 	"Share Chat": "Partage de conversation",
 	"Share Chat": "Partage de conversation",
-	"Share to OpenWebUI Community": "Partager avec la communauté OpenWebUI",
+	"Share to Open WebUI Community": "Partager avec la communauté OpenWebUI",
 	"Show": "Afficher",
 	"Show": "Afficher",
 	"Show \"What's New\" modal on login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion",
 	"Show \"What's New\" modal on login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion",
 	"Show Admin Details in Account Pending Overlay": "Afficher les coordonnées de l'administrateur aux comptes en attente",
 	"Show Admin Details in Account Pending Overlay": "Afficher les coordonnées de l'administrateur aux comptes en attente",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Cela réinitialisera la base de connaissances et synchronisera tous les fichiers. Souhaitez-vous continuer ?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Cela réinitialisera la base de connaissances et synchronisera tous les fichiers. Souhaitez-vous continuer ?",
 	"Thorough explanation": "Explication approfondie",
 	"Thorough explanation": "Explication approfondie",
 	"Thought for {{DURATION}}": "Réflexion de {{DURATION}}",
 	"Thought for {{DURATION}}": "Réflexion de {{DURATION}}",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/he-IL/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "לחץ כאן כדי",
 	"Click here to": "לחץ כאן כדי",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "לחץ כאן לבחירה",
 	"Click here to select": "לחץ כאן לבחירה",
 	"Click here to select a csv file.": "לחץ כאן לבחירת קובץ csv.",
 	"Click here to select a csv file.": "לחץ כאן לבחירת קובץ csv.",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "מסמכים",
 	"Documents": "מסמכים",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "לא מבצע חיבורים חיצוניים, והנתונים שלך נשמרים באופן מאובטח בשרת המקומי שלך.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "לא מבצע חיבורים חיצוניים, והנתונים שלך נשמרים באופן מאובטח בשרת המקומי שלך.",
+	"Domain Filter List": "",
 	"Don't have an account?": "אין לך חשבון?",
 	"Don't have an account?": "אין לך חשבון?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "הזן חפיפת נתונים",
 	"Enter Chunk Overlap": "הזן חפיפת נתונים",
 	"Enter Chunk Size": "הזן גודל נתונים",
 	"Enter Chunk Size": "הזן גודל נתונים",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "הזן כתובת URL של Github Raw",
 	"Enter Github Raw URL": "הזן כתובת URL של Github Raw",
 	"Enter Google PSE API Key": "הזן מפתח API של Google PSE",
 	"Enter Google PSE API Key": "הזן מפתח API של Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "שפה",
 	"Language": "שפה",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "בהיר",
 	"Light": "בהיר",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "נוצר על ידי קהילת OpenWebUI",
+	"Made by Open WebUI Community": "נוצר על ידי קהילת OpenWebUI",
 	"Make sure to enclose them with": "ודא להקיף אותם עם",
 	"Make sure to enclose them with": "ודא להקיף אותם עם",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "קרא בקול",
 	"Read Aloud": "קרא בקול",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "הקלט קול",
 	"Record voice": "הקלט קול",
-	"Redirecting you to OpenWebUI Community": "מפנה אותך לקהילת OpenWebUI",
+	"Redirecting you to Open WebUI Community": "מפנה אותך לקהילת OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "ההגדרות נשמרו בהצלחה!",
 	"Settings saved successfully!": "ההגדרות נשמרו בהצלחה!",
 	"Share": "שתף",
 	"Share": "שתף",
 	"Share Chat": "שתף צ'אט",
 	"Share Chat": "שתף צ'אט",
-	"Share to OpenWebUI Community": "שתף לקהילת OpenWebUI",
+	"Share to Open WebUI Community": "שתף לקהילת OpenWebUI",
 	"Show": "הצג",
 	"Show": "הצג",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "תיאור מפורט",
 	"Thorough explanation": "תיאור מפורט",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/hi-IN/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "यहां क्लिक करें",
 	"Click here to": "यहां क्लिक करें",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "चयन करने के लिए यहां क्लिक करें।",
 	"Click here to select": "चयन करने के लिए यहां क्लिक करें।",
 	"Click here to select a csv file.": "सीएसवी फ़ाइल का चयन करने के लिए यहां क्लिक करें।",
 	"Click here to select a csv file.": "सीएसवी फ़ाइल का चयन करने के लिए यहां क्लिक करें।",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "दस्तावेज़",
 	"Documents": "दस्तावेज़",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "कोई बाहरी कनेक्शन नहीं बनाता है, और आपका डेटा आपके स्थानीय रूप से होस्ट किए गए सर्वर पर सुरक्षित रूप से रहता है।",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "कोई बाहरी कनेक्शन नहीं बनाता है, और आपका डेटा आपके स्थानीय रूप से होस्ट किए गए सर्वर पर सुरक्षित रूप से रहता है।",
+	"Domain Filter List": "",
 	"Don't have an account?": "कोई खाता नहीं है?",
 	"Don't have an account?": "कोई खाता नहीं है?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "चंक ओवरलैप दर्ज करें",
 	"Enter Chunk Overlap": "चंक ओवरलैप दर्ज करें",
 	"Enter Chunk Size": "खंड आकार दर्ज करें",
 	"Enter Chunk Size": "खंड आकार दर्ज करें",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Github Raw URL दर्ज करें",
 	"Enter Github Raw URL": "Github Raw URL दर्ज करें",
 	"Enter Google PSE API Key": "Google PSE API कुंजी दर्ज करें",
 	"Enter Google PSE API Key": "Google PSE API कुंजी दर्ज करें",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "भाषा",
 	"Language": "भाषा",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "सुन",
 	"Light": "सुन",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "OpenWebUI समुदाय द्वारा निर्मित",
+	"Made by Open WebUI Community": "OpenWebUI समुदाय द्वारा निर्मित",
 	"Make sure to enclose them with": "उन्हें संलग्न करना सुनिश्चित करें",
 	"Make sure to enclose them with": "उन्हें संलग्न करना सुनिश्चित करें",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "जोर से पढ़ें",
 	"Read Aloud": "जोर से पढ़ें",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "आवाज रिकॉर्ड करना",
 	"Record voice": "आवाज रिकॉर्ड करना",
-	"Redirecting you to OpenWebUI Community": "आपको OpenWebUI समुदाय पर पुनर्निर्देशित किया जा रहा है",
+	"Redirecting you to Open WebUI Community": "आपको OpenWebUI समुदाय पर पुनर्निर्देशित किया जा रहा है",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "सेटिंग्स सफलतापूर्वक सहेजी गईं!",
 	"Settings saved successfully!": "सेटिंग्स सफलतापूर्वक सहेजी गईं!",
 	"Share": "साझा करें",
 	"Share": "साझा करें",
 	"Share Chat": "चैट साझा करें",
 	"Share Chat": "चैट साझा करें",
-	"Share to OpenWebUI Community": "OpenWebUI समुदाय में साझा करें",
+	"Share to Open WebUI Community": "OpenWebUI समुदाय में साझा करें",
 	"Show": "दिखाओ",
 	"Show": "दिखाओ",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "विस्तृत व्याख्या",
 	"Thorough explanation": "विस्तृत व्याख्या",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/hr-HR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Kliknite ovdje za",
 	"Click here to": "Kliknite ovdje za",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Kliknite ovdje za odabir",
 	"Click here to select": "Kliknite ovdje za odabir",
 	"Click here to select a csv file.": "Kliknite ovdje da odaberete csv datoteku.",
 	"Click here to select a csv file.": "Kliknite ovdje da odaberete csv datoteku.",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentacija",
 	"Documentation": "Dokumentacija",
 	"Documents": "Dokumenti",
 	"Documents": "Dokumenti",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ne uspostavlja vanjske veze, a vaši podaci ostaju sigurno na vašem lokalno hostiranom poslužitelju.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ne uspostavlja vanjske veze, a vaši podaci ostaju sigurno na vašem lokalno hostiranom poslužitelju.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nemate račun?",
 	"Don't have an account?": "Nemate račun?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Unesite preklapanje dijelova",
 	"Enter Chunk Overlap": "Unesite preklapanje dijelova",
 	"Enter Chunk Size": "Unesite veličinu dijela",
 	"Enter Chunk Size": "Unesite veličinu dijela",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Unesite Github sirovi URL",
 	"Enter Github Raw URL": "Unesite Github sirovi URL",
 	"Enter Google PSE API Key": "Unesite Google PSE API ključ",
 	"Enter Google PSE API Key": "Unesite Google PSE API ključ",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Jezik",
 	"Language": "Jezik",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Svijetlo",
 	"Light": "Svijetlo",
 	"Listening...": "Slušam...",
 	"Listening...": "Slušam...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokalni modeli",
 	"Local Models": "Lokalni modeli",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Izradio OpenWebUI Community",
+	"Made by Open WebUI Community": "Izradio OpenWebUI Community",
 	"Make sure to enclose them with": "Provjerite da ih zatvorite s",
 	"Make sure to enclose them with": "Provjerite da ih zatvorite s",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Upravljaj",
 	"Manage": "Upravljaj",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Čitaj naglas",
 	"Read Aloud": "Čitaj naglas",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Snimanje glasa",
 	"Record voice": "Snimanje glasa",
-	"Redirecting you to OpenWebUI Community": "Preusmjeravanje na OpenWebUI zajednicu",
+	"Redirecting you to Open WebUI Community": "Preusmjeravanje na OpenWebUI zajednicu",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Nazivajte se \"Korisnik\" (npr. \"Korisnik uči španjolski\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Nazivajte se \"Korisnik\" (npr. \"Korisnik uči španjolski\")",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Postavke su uspješno spremljene!",
 	"Settings saved successfully!": "Postavke su uspješno spremljene!",
 	"Share": "Podijeli",
 	"Share": "Podijeli",
 	"Share Chat": "Podijeli razgovor",
 	"Share Chat": "Podijeli razgovor",
-	"Share to OpenWebUI Community": "Podijeli u OpenWebUI zajednici",
+	"Share to Open WebUI Community": "Podijeli u OpenWebUI zajednici",
 	"Show": "Pokaži",
 	"Show": "Pokaži",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Detaljno objašnjenje",
 	"Thorough explanation": "Detaljno objašnjenje",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/hu-HU/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Kattints ide",
 	"Click here to": "Kattints ide",
 	"Click here to download user import template file.": "Kattints ide a felhasználó importálási sablon letöltéséhez.",
 	"Click here to download user import template file.": "Kattints ide a felhasználó importálási sablon letöltéséhez.",
 	"Click here to learn more about faster-whisper and see the available models.": "Kattints ide, hogy többet tudj meg a faster-whisperről és lásd az elérhető modelleket.",
 	"Click here to learn more about faster-whisper and see the available models.": "Kattints ide, hogy többet tudj meg a faster-whisperről és lásd az elérhető modelleket.",
+	"Click here to see available models.": "",
 	"Click here to select": "Kattints ide a kiválasztáshoz",
 	"Click here to select": "Kattints ide a kiválasztáshoz",
 	"Click here to select a csv file.": "Kattints ide egy CSV fájl kiválasztásához.",
 	"Click here to select a csv file.": "Kattints ide egy CSV fájl kiválasztásához.",
 	"Click here to select a py file.": "Kattints ide egy py fájl kiválasztásához.",
 	"Click here to select a py file.": "Kattints ide egy py fájl kiválasztásához.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentáció",
 	"Documentation": "Dokumentáció",
 	"Documents": "Dokumentumok",
 	"Documents": "Dokumentumok",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nem létesít külső kapcsolatokat, és az adataid biztonságban maradnak a helyileg hosztolt szervereden.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nem létesít külső kapcsolatokat, és az adataid biztonságban maradnak a helyileg hosztolt szervereden.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nincs még fiókod?",
 	"Don't have an account?": "Nincs még fiókod?",
 	"don't install random functions from sources you don't trust.": "ne telepíts véletlenszerű funkciókat olyan forrásokból, amelyekben nem bízol.",
 	"don't install random functions from sources you don't trust.": "ne telepíts véletlenszerű funkciókat olyan forrásokból, amelyekben nem bízol.",
 	"don't install random tools from sources you don't trust.": "ne telepíts véletlenszerű eszközöket olyan forrásokból, amelyekben nem bízol.",
 	"don't install random tools from sources you don't trust.": "ne telepíts véletlenszerű eszközöket olyan forrásokból, amelyekben nem bízol.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Add meg a darab átfedést",
 	"Enter Chunk Overlap": "Add meg a darab átfedést",
 	"Enter Chunk Size": "Add meg a darab méretet",
 	"Enter Chunk Size": "Add meg a darab méretet",
 	"Enter description": "Add meg a leírást",
 	"Enter description": "Add meg a leírást",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Add meg a Github Raw URL-t",
 	"Enter Github Raw URL": "Add meg a Github Raw URL-t",
 	"Enter Google PSE API Key": "Add meg a Google PSE API kulcsot",
 	"Enter Google PSE API Key": "Add meg a Google PSE API kulcsot",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Tudásbázis sikeresen törölve.",
 	"Knowledge deleted successfully.": "Tudásbázis sikeresen törölve.",
 	"Knowledge reset successfully.": "Tudásbázis sikeresen visszaállítva.",
 	"Knowledge reset successfully.": "Tudásbázis sikeresen visszaállítva.",
 	"Knowledge updated successfully": "Tudásbázis sikeresen frissítve",
 	"Knowledge updated successfully": "Tudásbázis sikeresen frissítve",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Kezdőlap mód",
 	"Landing Page Mode": "Kezdőlap mód",
 	"Language": "Nyelv",
 	"Language": "Nyelv",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "Hagyja üresen az összes modell használatához, vagy válasszon ki konkrét modelleket",
 	"Leave empty to include all models or select specific models": "Hagyja üresen az összes modell használatához, vagy válasszon ki konkrét modelleket",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Hagyja üresen az alapértelmezett prompt használatához, vagy adjon meg egyéni promptot",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Hagyja üresen az alapértelmezett prompt használatához, vagy adjon meg egyéni promptot",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Világos",
 	"Light": "Világos",
 	"Listening...": "Hallgatás...",
 	"Listening...": "Hallgatás...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Helyi modellek",
 	"Local Models": "Helyi modellek",
 	"Lost": "Elveszett",
 	"Lost": "Elveszett",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Az OpenWebUI közösség által készítve",
+	"Made by Open WebUI Community": "Az OpenWebUI közösség által készítve",
 	"Make sure to enclose them with": "Győződjön meg róla, hogy körülveszi őket",
 	"Make sure to enclose them with": "Győződjön meg róla, hogy körülveszi őket",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Győződjön meg róla, hogy exportál egy workflow.json fájlt API formátumban a ComfyUI-ból.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Győződjön meg róla, hogy exportál egy workflow.json fájlt API formátumban a ComfyUI-ból.",
 	"Manage": "Kezelés",
 	"Manage": "Kezelés",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Felolvasás",
 	"Read Aloud": "Felolvasás",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Hang rögzítése",
 	"Record voice": "Hang rögzítése",
-	"Redirecting you to OpenWebUI Community": "Átirányítás az OpenWebUI közösséghez",
+	"Redirecting you to Open WebUI Community": "Átirányítás az OpenWebUI közösséghez",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Hivatkozzon magára \"Felhasználó\"-ként (pl. \"A Felhasználó spanyolul tanul\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Hivatkozzon magára \"Felhasználó\"-ként (pl. \"A Felhasználó spanyolul tanul\")",
 	"References from": "Hivatkozások innen",
 	"References from": "Hivatkozások innen",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Beállítások sikeresen mentve!",
 	"Settings saved successfully!": "Beállítások sikeresen mentve!",
 	"Share": "Megosztás",
 	"Share": "Megosztás",
 	"Share Chat": "Beszélgetés megosztása",
 	"Share Chat": "Beszélgetés megosztása",
-	"Share to OpenWebUI Community": "Megosztás az OpenWebUI közösséggel",
+	"Share to Open WebUI Community": "Megosztás az OpenWebUI közösséggel",
 	"Show": "Mutat",
 	"Show": "Mutat",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Admin részletek megjelenítése a függő fiók átfedésben",
 	"Show Admin Details in Account Pending Overlay": "Admin részletek megjelenítése a függő fiók átfedésben",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Ez visszaállítja a tudásbázist és szinkronizálja az összes fájlt. Szeretné folytatni?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Ez visszaállítja a tudásbázist és szinkronizálja az összes fájlt. Szeretné folytatni?",
 	"Thorough explanation": "Alapos magyarázat",
 	"Thorough explanation": "Alapos magyarázat",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika szerver URL szükséges.",
 	"Tika Server URL required.": "Tika szerver URL szükséges.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/id-ID/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klik di sini untuk",
 	"Click here to": "Klik di sini untuk",
 	"Click here to download user import template file.": "Klik di sini untuk mengunduh file templat impor pengguna.",
 	"Click here to download user import template file.": "Klik di sini untuk mengunduh file templat impor pengguna.",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Klik di sini untuk memilih",
 	"Click here to select": "Klik di sini untuk memilih",
 	"Click here to select a csv file.": "Klik di sini untuk memilih file csv.",
 	"Click here to select a csv file.": "Klik di sini untuk memilih file csv.",
 	"Click here to select a py file.": "Klik di sini untuk memilih file py.",
 	"Click here to select a py file.": "Klik di sini untuk memilih file py.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentasi",
 	"Documentation": "Dokumentasi",
 	"Documents": "Dokumen",
 	"Documents": "Dokumen",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "tidak membuat koneksi eksternal apa pun, dan data Anda tetap aman di server yang dihosting secara lokal.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "tidak membuat koneksi eksternal apa pun, dan data Anda tetap aman di server yang dihosting secara lokal.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Tidak memiliki akun?",
 	"Don't have an account?": "Tidak memiliki akun?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Masukkan Tumpang Tindih Chunk",
 	"Enter Chunk Overlap": "Masukkan Tumpang Tindih Chunk",
 	"Enter Chunk Size": "Masukkan Ukuran Potongan",
 	"Enter Chunk Size": "Masukkan Ukuran Potongan",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Masukkan URL Mentah Github",
 	"Enter Github Raw URL": "Masukkan URL Mentah Github",
 	"Enter Google PSE API Key": "Masukkan Kunci API Google PSE",
 	"Enter Google PSE API Key": "Masukkan Kunci API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Bahasa",
 	"Language": "Bahasa",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Cahaya",
 	"Light": "Cahaya",
 	"Listening...": "Mendengarkan",
 	"Listening...": "Mendengarkan",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Model Lokal",
 	"Local Models": "Model Lokal",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Dibuat oleh Komunitas OpenWebUI",
+	"Made by Open WebUI Community": "Dibuat oleh Komunitas OpenWebUI",
 	"Make sure to enclose them with": "Pastikan untuk melampirkannya dengan",
 	"Make sure to enclose them with": "Pastikan untuk melampirkannya dengan",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Mengelola",
 	"Manage": "Mengelola",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Baca dengan Keras",
 	"Read Aloud": "Baca dengan Keras",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Rekam suara",
 	"Record voice": "Rekam suara",
-	"Redirecting you to OpenWebUI Community": "Mengarahkan Anda ke Komunitas OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Mengarahkan Anda ke Komunitas OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Merujuk diri Anda sebagai \"Pengguna\" (misalnya, \"Pengguna sedang belajar bahasa Spanyol\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Merujuk diri Anda sebagai \"Pengguna\" (misalnya, \"Pengguna sedang belajar bahasa Spanyol\")",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Pengaturan berhasil disimpan!",
 	"Settings saved successfully!": "Pengaturan berhasil disimpan!",
 	"Share": "Berbagi",
 	"Share": "Berbagi",
 	"Share Chat": "Bagikan Obrolan",
 	"Share Chat": "Bagikan Obrolan",
-	"Share to OpenWebUI Community": "Bagikan ke Komunitas OpenWebUI",
+	"Share to Open WebUI Community": "Bagikan ke Komunitas OpenWebUI",
 	"Show": "Tampilkan",
 	"Show": "Tampilkan",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Tampilkan Detail Admin di Hamparan Akun Tertunda",
 	"Show Admin Details in Account Pending Overlay": "Tampilkan Detail Admin di Hamparan Akun Tertunda",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Penjelasan menyeluruh",
 	"Thorough explanation": "Penjelasan menyeluruh",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ie-GA/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Cliceáil anseo chun",
 	"Click here to": "Cliceáil anseo chun",
 	"Click here to download user import template file.": "Cliceáil anseo chun an comhad iompórtála úsáideora a íoslódáil.",
 	"Click here to download user import template file.": "Cliceáil anseo chun an comhad iompórtála úsáideora a íoslódáil.",
 	"Click here to learn more about faster-whisper and see the available models.": "Cliceáil anseo chun níos mó a fhoghlaim faoi cogar níos tapúla agus na múnlaí atá ar fáil a fheiceáil.",
 	"Click here to learn more about faster-whisper and see the available models.": "Cliceáil anseo chun níos mó a fhoghlaim faoi cogar níos tapúla agus na múnlaí atá ar fáil a fheiceáil.",
+	"Click here to see available models.": "",
 	"Click here to select": "Cliceáil anseo chun roghnú",
 	"Click here to select": "Cliceáil anseo chun roghnú",
 	"Click here to select a csv file.": "Cliceáil anseo chun comhad csv a roghnú.",
 	"Click here to select a csv file.": "Cliceáil anseo chun comhad csv a roghnú.",
 	"Click here to select a py file.": "Cliceáil anseo chun comhad py a roghnú.",
 	"Click here to select a py file.": "Cliceáil anseo chun comhad py a roghnú.",
@@ -290,6 +291,7 @@
 	"Documentation": "Doiciméadú",
 	"Documentation": "Doiciméadú",
 	"Documents": "Doiciméid",
 	"Documents": "Doiciméid",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ní dhéanann sé aon naisc sheachtracha, agus fanann do chuid sonraí go slán ar do fhreastalaí a óstáiltear go háitiúil.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ní dhéanann sé aon naisc sheachtracha, agus fanann do chuid sonraí go slán ar do fhreastalaí a óstáiltear go háitiúil.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Níl cuntas agat?",
 	"Don't have an account?": "Níl cuntas agat?",
 	"don't install random functions from sources you don't trust.": "ná suiteáil feidhmeanna randamacha ó fhoinsí nach bhfuil muinín agat.",
 	"don't install random functions from sources you don't trust.": "ná suiteáil feidhmeanna randamacha ó fhoinsí nach bhfuil muinín agat.",
 	"don't install random tools from sources you don't trust.": "ná suiteáil uirlisí randamacha ó fhoinsí nach bhfuil muinín agat.",
 	"don't install random tools from sources you don't trust.": "ná suiteáil uirlisí randamacha ó fhoinsí nach bhfuil muinín agat.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Cuir isteach Chunk Forluí",
 	"Enter Chunk Overlap": "Cuir isteach Chunk Forluí",
 	"Enter Chunk Size": "Cuir isteach Méid an Chunc",
 	"Enter Chunk Size": "Cuir isteach Méid an Chunc",
 	"Enter description": "Iontráil cur síos",
 	"Enter description": "Iontráil cur síos",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "Cuir isteach Eochair Exa API",
 	"Enter Exa API Key": "Cuir isteach Eochair Exa API",
 	"Enter Github Raw URL": "Cuir isteach URL Github Raw",
 	"Enter Github Raw URL": "Cuir isteach URL Github Raw",
 	"Enter Google PSE API Key": "Cuir isteach Eochair API Google PSE",
 	"Enter Google PSE API Key": "Cuir isteach Eochair API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "D'éirigh leis an eolas a scriosadh.",
 	"Knowledge deleted successfully.": "D'éirigh leis an eolas a scriosadh.",
 	"Knowledge reset successfully.": "D'éirigh le hathshocrú eolais.",
 	"Knowledge reset successfully.": "D'éirigh le hathshocrú eolais.",
 	"Knowledge updated successfully": "D'éirigh leis an eolas a nuashonrú",
 	"Knowledge updated successfully": "D'éirigh leis an eolas a nuashonrú",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Lipéad",
 	"Label": "Lipéad",
 	"Landing Page Mode": "Mód Leathanach Tuirlingthe",
 	"Landing Page Mode": "Mód Leathanach Tuirlingthe",
 	"Language": "Teanga",
 	"Language": "Teanga",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Fág folamh chun gach múnla ón gcríochphointe \"{{URL}}/models\" a chur san áireamh",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Fág folamh chun gach múnla ón gcríochphointe \"{{URL}}/models\" a chur san áireamh",
 	"Leave empty to include all models or select specific models": "Fág folamh chun gach múnla a chur san áireamh nó roghnaigh múnlaí sonracha",
 	"Leave empty to include all models or select specific models": "Fág folamh chun gach múnla a chur san áireamh nó roghnaigh múnlaí sonracha",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Fág folamh chun an leid réamhshocraithe a úsáid, nó cuir isteach leid saincheaptha",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Fág folamh chun an leid réamhshocraithe a úsáid, nó cuir isteach leid saincheaptha",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Solas",
 	"Light": "Solas",
 	"Listening...": "Éisteacht...",
 	"Listening...": "Éisteacht...",
 	"Llama.cpp": "Llama.cpp",
 	"Llama.cpp": "Llama.cpp",
@@ -574,7 +580,7 @@
 	"Local Models": "Múnlaí Áitiúla",
 	"Local Models": "Múnlaí Áitiúla",
 	"Lost": "Cailleadh",
 	"Lost": "Cailleadh",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Déanta ag OpenWebUI Community",
+	"Made by Open WebUI Community": "Déanta ag OpenWebUI Community",
 	"Make sure to enclose them with": "Déan cinnte iad a cheangal le",
 	"Make sure to enclose them with": "Déan cinnte iad a cheangal le",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Déan cinnte comhad workflow.json a onnmhairiú mar fhormáid API ó ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Déan cinnte comhad workflow.json a onnmhairiú mar fhormáid API ó ComfyUI.",
 	"Manage": "Bainistiú",
 	"Manage": "Bainistiú",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Léigh Ard",
 	"Read Aloud": "Léigh Ard",
 	"Reasoning Effort": "Iarracht Réasúnúcháin",
 	"Reasoning Effort": "Iarracht Réasúnúcháin",
 	"Record voice": "Taifead guth",
 	"Record voice": "Taifead guth",
-	"Redirecting you to OpenWebUI Community": "Tú a atreorú chuig OpenWebUI Community",
+	"Redirecting you to Open WebUI Community": "Tú a atreorú chuig OpenWebUI Community",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Laghdaíonn sé an dóchúlacht go giniúint nonsense. Tabharfaidh luach níos airde (m.sh. 100) freagraí níos éagsúla, agus beidh luach níos ísle (m.sh. 10) níos coimeádaí. (Réamhshocrú: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Laghdaíonn sé an dóchúlacht go giniúint nonsense. Tabharfaidh luach níos airde (m.sh. 100) freagraí níos éagsúla, agus beidh luach níos ísle (m.sh. 10) níos coimeádaí. (Réamhshocrú: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Tagairt duit féin mar \"Úsáideoir\" (m.sh., \"Tá an úsáideoir ag foghlaim Spáinnis\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Tagairt duit féin mar \"Úsáideoir\" (m.sh., \"Tá an úsáideoir ag foghlaim Spáinnis\")",
 	"References from": "Tagairtí ó",
 	"References from": "Tagairtí ó",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Socruithe sábhálta go rathúil!",
 	"Settings saved successfully!": "Socruithe sábhálta go rathúil!",
 	"Share": "Comhroinn",
 	"Share": "Comhroinn",
 	"Share Chat": "Comhroinn Comhrá",
 	"Share Chat": "Comhroinn Comhrá",
-	"Share to OpenWebUI Community": "Comhroinn le Pobal OpenWebUI",
+	"Share to Open WebUI Community": "Comhroinn le Pobal OpenWebUI",
 	"Show": "Taispeáin",
 	"Show": "Taispeáin",
 	"Show \"What's New\" modal on login": "Taispeáin módúil \"Cad atá Nua\" ar logáil isteach",
 	"Show \"What's New\" modal on login": "Taispeáin módúil \"Cad atá Nua\" ar logáil isteach",
 	"Show Admin Details in Account Pending Overlay": "Taispeáin Sonraí Riaracháin sa Chuntas ar Feitheamh Forleagan",
 	"Show Admin Details in Account Pending Overlay": "Taispeáin Sonraí Riaracháin sa Chuntas ar Feitheamh Forleagan",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Déanfaidh sé seo an bonn eolais a athshocrú agus gach comhad a shioncronú. Ar mhaith leat leanúint ar aghaidh?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Déanfaidh sé seo an bonn eolais a athshocrú agus gach comhad a shioncronú. Ar mhaith leat leanúint ar aghaidh?",
 	"Thorough explanation": "Míniú críochnúil",
 	"Thorough explanation": "Míniú críochnúil",
 	"Thought for {{DURATION}}": "Smaoineamh ar {{DURATION}}",
 	"Thought for {{DURATION}}": "Smaoineamh ar {{DURATION}}",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Teastaíonn URL Freastalaí Tika.",
 	"Tika Server URL required.": "Teastaíonn URL Freastalaí Tika.",
 	"Tiktoken": "Tictoken",
 	"Tiktoken": "Tictoken",

+ 10 - 3
src/lib/i18n/locales/it-IT/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Clicca qui per",
 	"Click here to": "Clicca qui per",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Clicca qui per selezionare",
 	"Click here to select": "Clicca qui per selezionare",
 	"Click here to select a csv file.": "Clicca qui per selezionare un file csv.",
 	"Click here to select a csv file.": "Clicca qui per selezionare un file csv.",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "Documenti",
 	"Documents": "Documenti",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "non effettua connessioni esterne e i tuoi dati rimangono al sicuro sul tuo server ospitato localmente.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "non effettua connessioni esterne e i tuoi dati rimangono al sicuro sul tuo server ospitato localmente.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Non hai un account?",
 	"Don't have an account?": "Non hai un account?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Inserisci la sovrapposizione chunk",
 	"Enter Chunk Overlap": "Inserisci la sovrapposizione chunk",
 	"Enter Chunk Size": "Inserisci la dimensione chunk",
 	"Enter Chunk Size": "Inserisci la dimensione chunk",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Immettere l'URL grezzo di Github",
 	"Enter Github Raw URL": "Immettere l'URL grezzo di Github",
 	"Enter Google PSE API Key": "Inserisci la chiave API PSE di Google",
 	"Enter Google PSE API Key": "Inserisci la chiave API PSE di Google",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Lingua",
 	"Language": "Lingua",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Chiaro",
 	"Light": "Chiaro",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Realizzato dalla comunità OpenWebUI",
+	"Made by Open WebUI Community": "Realizzato dalla comunità OpenWebUI",
 	"Make sure to enclose them with": "Assicurati di racchiuderli con",
 	"Make sure to enclose them with": "Assicurati di racchiuderli con",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Leggi ad alta voce",
 	"Read Aloud": "Leggi ad alta voce",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Registra voce",
 	"Record voice": "Registra voce",
-	"Redirecting you to OpenWebUI Community": "Reindirizzamento alla comunità OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Reindirizzamento alla comunità OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Impostazioni salvate con successo!",
 	"Settings saved successfully!": "Impostazioni salvate con successo!",
 	"Share": "Condividi",
 	"Share": "Condividi",
 	"Share Chat": "Condividi chat",
 	"Share Chat": "Condividi chat",
-	"Share to OpenWebUI Community": "Condividi con la comunità OpenWebUI",
+	"Share to Open WebUI Community": "Condividi con la comunità OpenWebUI",
 	"Show": "Mostra",
 	"Show": "Mostra",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Spiegazione dettagliata",
 	"Thorough explanation": "Spiegazione dettagliata",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ja-JP/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "ここをクリックして",
 	"Click here to": "ここをクリックして",
 	"Click here to download user import template file.": "ユーザーテンプレートをインポートするにはここをクリックしてください。",
 	"Click here to download user import template file.": "ユーザーテンプレートをインポートするにはここをクリックしてください。",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "選択するにはここをクリックしてください",
 	"Click here to select": "選択するにはここをクリックしてください",
 	"Click here to select a csv file.": "CSVファイルを選択するにはここをクリックしてください。",
 	"Click here to select a csv file.": "CSVファイルを選択するにはここをクリックしてください。",
 	"Click here to select a py file.": "Pythonスクリプトファイルを選択するにはここをクリックしてください。",
 	"Click here to select a py file.": "Pythonスクリプトファイルを選択するにはここをクリックしてください。",
@@ -290,6 +291,7 @@
 	"Documentation": "ドキュメント",
 	"Documentation": "ドキュメント",
 	"Documents": "ドキュメント",
 	"Documents": "ドキュメント",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "外部接続を行わず、データはローカルでホストされているサーバー上に安全に保持されます。",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "外部接続を行わず、データはローカルでホストされているサーバー上に安全に保持されます。",
+	"Domain Filter List": "",
 	"Don't have an account?": "アカウントをお持ちではありませんか?",
 	"Don't have an account?": "アカウントをお持ちではありませんか?",
 	"don't install random functions from sources you don't trust.": "信頼出来ないソースからランダムFunctionをインストールしないでください。",
 	"don't install random functions from sources you don't trust.": "信頼出来ないソースからランダムFunctionをインストールしないでください。",
 	"don't install random tools from sources you don't trust.": "信頼出来ないソースからランダムツールをインストールしないでください。",
 	"don't install random tools from sources you don't trust.": "信頼出来ないソースからランダムツールをインストールしないでください。",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "チャンクオーバーラップを入力してください",
 	"Enter Chunk Overlap": "チャンクオーバーラップを入力してください",
 	"Enter Chunk Size": "チャンクサイズを入力してください",
 	"Enter Chunk Size": "チャンクサイズを入力してください",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Github Raw URLを入力",
 	"Enter Github Raw URL": "Github Raw URLを入力",
 	"Enter Google PSE API Key": "Google PSE APIキーの入力",
 	"Enter Google PSE API Key": "Google PSE APIキーの入力",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "ナレッジベースの削除に成功しました",
 	"Knowledge deleted successfully.": "ナレッジベースの削除に成功しました",
 	"Knowledge reset successfully.": "ナレッジベースのリセットに成功しました",
 	"Knowledge reset successfully.": "ナレッジベースのリセットに成功しました",
 	"Knowledge updated successfully": "ナレッジベースのアップデートに成功しました",
 	"Knowledge updated successfully": "ナレッジベースのアップデートに成功しました",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "ランディングページモード",
 	"Landing Page Mode": "ランディングページモード",
 	"Language": "言語",
 	"Language": "言語",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "カスタムプロンプトを入力。空欄ならデフォルトプロンプト",
 	"Leave empty to use the default prompt, or enter a custom prompt": "カスタムプロンプトを入力。空欄ならデフォルトプロンプト",
+	"Leave model field empty to use the default model.": "",
 	"Light": "ライト",
 	"Light": "ライト",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "ローカルモデル",
 	"Local Models": "ローカルモデル",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "OpenWebUI コミュニティによって作成",
+	"Made by Open WebUI Community": "OpenWebUI コミュニティによって作成",
 	"Make sure to enclose them with": "必ず次で囲んでください",
 	"Make sure to enclose them with": "必ず次で囲んでください",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "管理",
 	"Manage": "管理",
@@ -754,7 +760,7 @@
 	"Read Aloud": "読み上げ",
 	"Read Aloud": "読み上げ",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "音声を録音",
 	"Record voice": "音声を録音",
-	"Redirecting you to OpenWebUI Community": "OpenWebUI コミュニティにリダイレクトしています",
+	"Redirecting you to Open WebUI Community": "OpenWebUI コミュニティにリダイレクトしています",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "設定が正常に保存されました!",
 	"Settings saved successfully!": "設定が正常に保存されました!",
 	"Share": "共有",
 	"Share": "共有",
 	"Share Chat": "チャットを共有",
 	"Share Chat": "チャットを共有",
-	"Share to OpenWebUI Community": "OpenWebUI コミュニティに共有",
+	"Share to Open WebUI Community": "OpenWebUI コミュニティに共有",
 	"Show": "表示",
 	"Show": "表示",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "詳細な説明",
 	"Thorough explanation": "詳細な説明",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ka-GE/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "დააკლიკე აქ",
 	"Click here to": "დააკლიკე აქ",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "ასარჩევად, დააკლიკე აქ",
 	"Click here to select": "ასარჩევად, დააკლიკე აქ",
 	"Click here to select a csv file.": "ასარჩევად, დააკლიკე აქ",
 	"Click here to select a csv file.": "ასარჩევად, დააკლიკე აქ",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "დოკუმენტები",
 	"Documents": "დოკუმენტები",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "არ ამყარებს გარე კავშირებს და თქვენი მონაცემები უსაფრთხოდ რჩება თქვენს ადგილობრივ სერვერზე.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "არ ამყარებს გარე კავშირებს და თქვენი მონაცემები უსაფრთხოდ რჩება თქვენს ადგილობრივ სერვერზე.",
+	"Domain Filter List": "",
 	"Don't have an account?": "არ გაქვს ანგარიში?",
 	"Don't have an account?": "არ გაქვს ანგარიში?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "შეიყვანეთ ნაწილის გადახურვა",
 	"Enter Chunk Overlap": "შეიყვანეთ ნაწილის გადახურვა",
 	"Enter Chunk Size": "შეიყვანე ბლოკის ზომა",
 	"Enter Chunk Size": "შეიყვანე ბლოკის ზომა",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "შეიყვანეთ Github Raw URL",
 	"Enter Github Raw URL": "შეიყვანეთ Github Raw URL",
 	"Enter Google PSE API Key": "შეიყვანეთ Google PSE API გასაღები",
 	"Enter Google PSE API Key": "შეიყვანეთ Google PSE API გასაღები",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "ენა",
 	"Language": "ენა",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "მსუბუქი",
 	"Light": "მსუბუქი",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "დამზადებულია OpenWebUI საზოგადოების მიერ",
+	"Made by Open WebUI Community": "დამზადებულია OpenWebUI საზოგადოების მიერ",
 	"Make sure to enclose them with": "დარწმუნდით, რომ დაურთეთ ისინი",
 	"Make sure to enclose them with": "დარწმუნდით, რომ დაურთეთ ისინი",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "ხმის ჩაწერა",
 	"Read Aloud": "ხმის ჩაწერა",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "ხმის ჩაწერა",
 	"Record voice": "ხმის ჩაწერა",
-	"Redirecting you to OpenWebUI Community": "გადამისამართდებით OpenWebUI საზოგადოებაში",
+	"Redirecting you to Open WebUI Community": "გადამისამართდებით OpenWebUI საზოგადოებაში",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "პარამეტრები წარმატებით განახლდა!",
 	"Settings saved successfully!": "პარამეტრები წარმატებით განახლდა!",
 	"Share": "გაზიარება",
 	"Share": "გაზიარება",
 	"Share Chat": "გაზიარება",
 	"Share Chat": "გაზიარება",
-	"Share to OpenWebUI Community": "გააზიარე OpenWebUI საზოგადოებაში ",
+	"Share to Open WebUI Community": "გააზიარე OpenWebUI საზოგადოებაში ",
 	"Show": "ჩვენება",
 	"Show": "ჩვენება",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "ვრცლად აღწერა",
 	"Thorough explanation": "ვრცლად აღწერა",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ko-KR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "여기를 클릭하면",
 	"Click here to": "여기를 클릭하면",
 	"Click here to download user import template file.": "사용자 삽입 템플렛 파일을 다운받으려면 여기를 클릭하세요",
 	"Click here to download user import template file.": "사용자 삽입 템플렛 파일을 다운받으려면 여기를 클릭하세요",
 	"Click here to learn more about faster-whisper and see the available models.": "빠른 속삭임에 대해 배우거나 가능한 모델을 보려면 여기를 클릭하세요",
 	"Click here to learn more about faster-whisper and see the available models.": "빠른 속삭임에 대해 배우거나 가능한 모델을 보려면 여기를 클릭하세요",
+	"Click here to see available models.": "",
 	"Click here to select": "선택하려면 여기를 클릭하세요.",
 	"Click here to select": "선택하려면 여기를 클릭하세요.",
 	"Click here to select a csv file.": "csv 파일을 선택하려면 여기를 클릭하세요.",
 	"Click here to select a csv file.": "csv 파일을 선택하려면 여기를 클릭하세요.",
 	"Click here to select a py file.": "py 파일을 선택하려면 여기를 클릭하세요.",
 	"Click here to select a py file.": "py 파일을 선택하려면 여기를 클릭하세요.",
@@ -290,6 +291,7 @@
 	"Documentation": "문서 조사",
 	"Documentation": "문서 조사",
 	"Documents": "문서",
 	"Documents": "문서",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "외부와 어떠한 연결도 하지 않으며, 데이터는 로컬에서 호스팅되는 서버에 안전하게 유지됩니다.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "외부와 어떠한 연결도 하지 않으며, 데이터는 로컬에서 호스팅되는 서버에 안전하게 유지됩니다.",
+	"Domain Filter List": "",
 	"Don't have an account?": "계정이 없으신가요?",
 	"Don't have an account?": "계정이 없으신가요?",
 	"don't install random functions from sources you don't trust.": "불분명한 출처를 가진 임의의 함수를 설치하지마세요",
 	"don't install random functions from sources you don't trust.": "불분명한 출처를 가진 임의의 함수를 설치하지마세요",
 	"don't install random tools from sources you don't trust.": "불분명한 출처를 가진 임의의 도구를 설치하지마세요",
 	"don't install random tools from sources you don't trust.": "불분명한 출처를 가진 임의의 도구를 설치하지마세요",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "청크 오버랩 입력",
 	"Enter Chunk Overlap": "청크 오버랩 입력",
 	"Enter Chunk Size": "청크 크기 입력",
 	"Enter Chunk Size": "청크 크기 입력",
 	"Enter description": "설명 입력",
 	"Enter description": "설명 입력",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Github Raw URL 입력",
 	"Enter Github Raw URL": "Github Raw URL 입력",
 	"Enter Google PSE API Key": "Google PSE API 키 입력",
 	"Enter Google PSE API Key": "Google PSE API 키 입력",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "성공적으로 지식 기반이 삭제되었습니다",
 	"Knowledge deleted successfully.": "성공적으로 지식 기반이 삭제되었습니다",
 	"Knowledge reset successfully.": "성공적으로 지식 기반이 초기화되었습니다",
 	"Knowledge reset successfully.": "성공적으로 지식 기반이 초기화되었습니다",
 	"Knowledge updated successfully": "성공적으로 지식 기반이 업데이트되었습니다",
 	"Knowledge updated successfully": "성공적으로 지식 기반이 업데이트되었습니다",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "랜딩페이지 모드",
 	"Landing Page Mode": "랜딩페이지 모드",
 	"Language": "언어",
 	"Language": "언어",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "특정 모델을 선택하거나 모든 모델을 포함하고 싶으면 빈칸으로 남겨두세요",
 	"Leave empty to include all models or select specific models": "특정 모델을 선택하거나 모든 모델을 포함하고 싶으면 빈칸으로 남겨두세요",
 	"Leave empty to use the default prompt, or enter a custom prompt": "기본 프롬프트를 사용하기 위해 빈칸으로 남겨두거나, 커스텀 프롬프트를 입력하세요",
 	"Leave empty to use the default prompt, or enter a custom prompt": "기본 프롬프트를 사용하기 위해 빈칸으로 남겨두거나, 커스텀 프롬프트를 입력하세요",
+	"Leave model field empty to use the default model.": "",
 	"Light": "라이트",
 	"Light": "라이트",
 	"Listening...": "듣는 중...",
 	"Listening...": "듣는 중...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "로컬 모델",
 	"Local Models": "로컬 모델",
 	"Lost": "패배",
 	"Lost": "패배",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "OpenWebUI 커뮤니티에 의해 개발됨",
+	"Made by Open WebUI Community": "OpenWebUI 커뮤니티에 의해 개발됨",
 	"Make sure to enclose them with": "꼭 다음으로 감싸세요:",
 	"Make sure to enclose them with": "꼭 다음으로 감싸세요:",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "꼭 workflow.json 파일을 ComfyUI의 API 형식대로 내보내세요",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "꼭 workflow.json 파일을 ComfyUI의 API 형식대로 내보내세요",
 	"Manage": "관리",
 	"Manage": "관리",
@@ -754,7 +760,7 @@
 	"Read Aloud": "읽어주기",
 	"Read Aloud": "읽어주기",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "음성 녹음",
 	"Record voice": "음성 녹음",
-	"Redirecting you to OpenWebUI Community": "OpenWebUI 커뮤니티로 리디렉션 중",
+	"Redirecting you to Open WebUI Community": "OpenWebUI 커뮤니티로 리디렉션 중",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "스스로를 \"사용자\" 라고 지칭하세요. (예: \"사용자는 영어를 배우고 있습니다\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "스스로를 \"사용자\" 라고 지칭하세요. (예: \"사용자는 영어를 배우고 있습니다\")",
 	"References from": "출처",
 	"References from": "출처",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "설정이 성공적으로 저장되었습니다!",
 	"Settings saved successfully!": "설정이 성공적으로 저장되었습니다!",
 	"Share": "공유",
 	"Share": "공유",
 	"Share Chat": "채팅 공유",
 	"Share Chat": "채팅 공유",
-	"Share to OpenWebUI Community": "OpenWebUI 커뮤니티에 공유",
+	"Share to Open WebUI Community": "OpenWebUI 커뮤니티에 공유",
 	"Show": "보기",
 	"Show": "보기",
 	"Show \"What's New\" modal on login": "로그인시 \"새로운 기능\" 모달 보기",
 	"Show \"What's New\" modal on login": "로그인시 \"새로운 기능\" 모달 보기",
 	"Show Admin Details in Account Pending Overlay": "사용자용 계정 보류 설명창에, 관리자 상세 정보 노출",
 	"Show Admin Details in Account Pending Overlay": "사용자용 계정 보류 설명창에, 관리자 상세 정보 노출",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "지식 기반과 모든 파일 연동을 초기화합니다. 계속 하시겠습니까?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "지식 기반과 모든 파일 연동을 초기화합니다. 계속 하시겠습니까?",
 	"Thorough explanation": "완전한 설명",
 	"Thorough explanation": "완전한 설명",
 	"Thought for {{DURATION}}": "{{DURATION}} 동안 생각함",
 	"Thought for {{DURATION}}": "{{DURATION}} 동안 생각함",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "티카(Tika)",
 	"Tika": "티카(Tika)",
 	"Tika Server URL required.": "티카 서버 URL이 필요합니다",
 	"Tika Server URL required.": "티카 서버 URL이 필요합니다",
 	"Tiktoken": "틱토큰 (Tiktoken)",
 	"Tiktoken": "틱토큰 (Tiktoken)",

+ 10 - 3
src/lib/i18n/locales/lt-LT/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Paspauskite čia, kad:",
 	"Click here to": "Paspauskite čia, kad:",
 	"Click here to download user import template file.": "Pasauskite čia norėdami sukurti naudotojo įkėlimo šablono rinkmeną",
 	"Click here to download user import template file.": "Pasauskite čia norėdami sukurti naudotojo įkėlimo šablono rinkmeną",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Spauskite čia norėdami pasirinkti",
 	"Click here to select": "Spauskite čia norėdami pasirinkti",
 	"Click here to select a csv file.": "Spauskite čia tam, kad pasirinkti csv failą",
 	"Click here to select a csv file.": "Spauskite čia tam, kad pasirinkti csv failą",
 	"Click here to select a py file.": "Spauskite čia norėdami pasirinkti py failą",
 	"Click here to select a py file.": "Spauskite čia norėdami pasirinkti py failą",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentacija",
 	"Documentation": "Dokumentacija",
 	"Documents": "Dokumentai",
 	"Documents": "Dokumentai",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "neturi jokių išorinių ryšių ir duomenys lieka serveryje.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "neturi jokių išorinių ryšių ir duomenys lieka serveryje.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Neturite paskyros?",
 	"Don't have an account?": "Neturite paskyros?",
 	"don't install random functions from sources you don't trust.": "neinstaliuokite funkcijų iš nepatikimų šaltinių",
 	"don't install random functions from sources you don't trust.": "neinstaliuokite funkcijų iš nepatikimų šaltinių",
 	"don't install random tools from sources you don't trust.": "neinstaliuokite įrankių iš nepatikimų šaltinių",
 	"don't install random tools from sources you don't trust.": "neinstaliuokite įrankių iš nepatikimų šaltinių",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Įveskite blokų persidengimą",
 	"Enter Chunk Overlap": "Įveskite blokų persidengimą",
 	"Enter Chunk Size": "Įveskite blokų dydį",
 	"Enter Chunk Size": "Įveskite blokų dydį",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Įveskite GitHub Raw nuorodą",
 	"Enter Github Raw URL": "Įveskite GitHub Raw nuorodą",
 	"Enter Google PSE API Key": "Įveskite Google PSE API raktą",
 	"Enter Google PSE API Key": "Įveskite Google PSE API raktą",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Kalba",
 	"Language": "Kalba",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Šviesus",
 	"Light": "Šviesus",
 	"Listening...": "Klausoma...",
 	"Listening...": "Klausoma...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokalūs modeliai",
 	"Local Models": "Lokalūs modeliai",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Sukurta OpenWebUI bendruomenės",
+	"Made by Open WebUI Community": "Sukurta OpenWebUI bendruomenės",
 	"Make sure to enclose them with": "Užtikrinktie, kad įtraukiate viduje:",
 	"Make sure to enclose them with": "Užtikrinktie, kad įtraukiate viduje:",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Tvarkyti",
 	"Manage": "Tvarkyti",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Skaityti garsiai",
 	"Read Aloud": "Skaityti garsiai",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Įrašyti balsą",
 	"Record voice": "Įrašyti balsą",
-	"Redirecting you to OpenWebUI Community": "Perkeliam Jus į OpenWebUI bendruomenę",
+	"Redirecting you to Open WebUI Community": "Perkeliam Jus į OpenWebUI bendruomenę",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Vadinkite save Naudotoju (pvz. Naudotojas mokosi prancūzų kalbos)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Vadinkite save Naudotoju (pvz. Naudotojas mokosi prancūzų kalbos)",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Parametrai sėkmingai išsaugoti!",
 	"Settings saved successfully!": "Parametrai sėkmingai išsaugoti!",
 	"Share": "Dalintis",
 	"Share": "Dalintis",
 	"Share Chat": "Dalintis pokalbiu",
 	"Share Chat": "Dalintis pokalbiu",
-	"Share to OpenWebUI Community": "Dalintis su OpenWebUI bendruomene",
+	"Share to Open WebUI Community": "Dalintis su OpenWebUI bendruomene",
 	"Show": "Rodyti",
 	"Show": "Rodyti",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Rodyti administratoriaus duomenis laukiant paskyros patvirtinimo",
 	"Show Admin Details in Account Pending Overlay": "Rodyti administratoriaus duomenis laukiant paskyros patvirtinimo",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Platus paaiškinimas",
 	"Thorough explanation": "Platus paaiškinimas",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Reiklainga Tika serverio nuorodą",
 	"Tika Server URL required.": "Reiklainga Tika serverio nuorodą",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ms-MY/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klik disini untuk",
 	"Click here to": "Klik disini untuk",
 	"Click here to download user import template file.": "Klik disini untuk memuat turun fail templat import pengguna",
 	"Click here to download user import template file.": "Klik disini untuk memuat turun fail templat import pengguna",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Klik disini untuk memilih",
 	"Click here to select": "Klik disini untuk memilih",
 	"Click here to select a csv file.": "Klik disini untuk memilih fail csv",
 	"Click here to select a csv file.": "Klik disini untuk memilih fail csv",
 	"Click here to select a py file.": "Klik disini untuk memilih fail py",
 	"Click here to select a py file.": "Klik disini untuk memilih fail py",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentasi",
 	"Documentation": "Dokumentasi",
 	"Documents": "Dokumen",
 	"Documents": "Dokumen",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "tidak membuat sebarang sambungan luaran, dan data anda kekal selamat pada pelayan yang dihoskan ditempat anda",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "tidak membuat sebarang sambungan luaran, dan data anda kekal selamat pada pelayan yang dihoskan ditempat anda",
+	"Domain Filter List": "",
 	"Don't have an account?": "Anda tidak mempunyai akaun?",
 	"Don't have an account?": "Anda tidak mempunyai akaun?",
 	"don't install random functions from sources you don't trust.": "jangan pasang mana-mana fungsi daripada sumber yang anda tidak percayai.",
 	"don't install random functions from sources you don't trust.": "jangan pasang mana-mana fungsi daripada sumber yang anda tidak percayai.",
 	"don't install random tools from sources you don't trust.": "jangan pasang mana-mana alat daripada sumber yang anda tidak percayai.",
 	"don't install random tools from sources you don't trust.": "jangan pasang mana-mana alat daripada sumber yang anda tidak percayai.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Masukkan Tindihan 'Chunk'",
 	"Enter Chunk Overlap": "Masukkan Tindihan 'Chunk'",
 	"Enter Chunk Size": "Masukkan Saiz 'Chunk'",
 	"Enter Chunk Size": "Masukkan Saiz 'Chunk'",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Masukkan URL 'Github Raw'",
 	"Enter Github Raw URL": "Masukkan URL 'Github Raw'",
 	"Enter Google PSE API Key": "Masukkan kunci API Google PSE",
 	"Enter Google PSE API Key": "Masukkan kunci API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Bahasa",
 	"Language": "Bahasa",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Cerah",
 	"Light": "Cerah",
 	"Listening...": "Mendengar...",
 	"Listening...": "Mendengar...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Model Tempatan",
 	"Local Models": "Model Tempatan",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Dicipta oleh Komuniti OpenWebUI",
+	"Made by Open WebUI Community": "Dicipta oleh Komuniti OpenWebUI",
 	"Make sure to enclose them with": "Pastikan untuk melampirkannya dengan",
 	"Make sure to enclose them with": "Pastikan untuk melampirkannya dengan",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Urus",
 	"Manage": "Urus",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Baca dengan lantang",
 	"Read Aloud": "Baca dengan lantang",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Rakam suara",
 	"Record voice": "Rakam suara",
-	"Redirecting you to OpenWebUI Community": "Membawa anda ke Komuniti OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Membawa anda ke Komuniti OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Rujuk diri anda sebagai \"User\" (cth, \"Pengguna sedang belajar bahasa Sepanyol\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Rujuk diri anda sebagai \"User\" (cth, \"Pengguna sedang belajar bahasa Sepanyol\")",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Tetapan berjaya disimpan!",
 	"Settings saved successfully!": "Tetapan berjaya disimpan!",
 	"Share": "Kongsi",
 	"Share": "Kongsi",
 	"Share Chat": "Kongsi Perbualan",
 	"Share Chat": "Kongsi Perbualan",
-	"Share to OpenWebUI Community": "Kongsi kepada Komuniti OpenWebUI",
+	"Share to Open WebUI Community": "Kongsi kepada Komuniti OpenWebUI",
 	"Show": "Tunjukkan",
 	"Show": "Tunjukkan",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Tunjukkan Butiran Pentadbir dalam Akaun Menunggu Tindanan",
 	"Show Admin Details in Account Pending Overlay": "Tunjukkan Butiran Pentadbir dalam Akaun Menunggu Tindanan",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Penjelasan menyeluruh",
 	"Thorough explanation": "Penjelasan menyeluruh",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "URL Pelayan Tika diperlukan.",
 	"Tika Server URL required.": "URL Pelayan Tika diperlukan.",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/nb-NO/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klikk her for å",
 	"Click here to": "Klikk her for å",
 	"Click here to download user import template file.": "Klikk her for å hente ned malfilen for import av brukere.",
 	"Click here to download user import template file.": "Klikk her for å hente ned malfilen for import av brukere.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikk her for å lære mer om faster-whisper, og se de tilgjengelige modellene.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klikk her for å lære mer om faster-whisper, og se de tilgjengelige modellene.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klikk her for å velge",
 	"Click here to select": "Klikk her for å velge",
 	"Click here to select a csv file.": "Klikk her for å velge en CSV-fil.",
 	"Click here to select a csv file.": "Klikk her for å velge en CSV-fil.",
 	"Click here to select a py file.": "Klikk her for å velge en PY-fil.",
 	"Click here to select a py file.": "Klikk her for å velge en PY-fil.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentasjon",
 	"Documentation": "Dokumentasjon",
 	"Documents": "Dokumenter",
 	"Documents": "Dokumenter",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ikke ingen tilkobling til eksterne tjenester. Dataene dine forblir sikkert på den lokale serveren.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ikke ingen tilkobling til eksterne tjenester. Dataene dine forblir sikkert på den lokale serveren.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Har du ingen konto?",
 	"Don't have an account?": "Har du ingen konto?",
 	"don't install random functions from sources you don't trust.": "ikke installer tilfeldige funksjoner fra kilder du ikke stoler på.",
 	"don't install random functions from sources you don't trust.": "ikke installer tilfeldige funksjoner fra kilder du ikke stoler på.",
 	"don't install random tools from sources you don't trust.": "ikke installer tilfeldige verktøy fra kilder du ikke stoler på.",
 	"don't install random tools from sources you don't trust.": "ikke installer tilfeldige verktøy fra kilder du ikke stoler på.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Angi Chunk-overlapp",
 	"Enter Chunk Overlap": "Angi Chunk-overlapp",
 	"Enter Chunk Size": "Angi Chunk-størrelse",
 	"Enter Chunk Size": "Angi Chunk-størrelse",
 	"Enter description": "Angi beskrivelse",
 	"Enter description": "Angi beskrivelse",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Angi Github Raw-URL",
 	"Enter Github Raw URL": "Angi Github Raw-URL",
 	"Enter Google PSE API Key": "Angi API-nøkkel for Google PSE",
 	"Enter Google PSE API Key": "Angi API-nøkkel for Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Kunnskap slettet.",
 	"Knowledge deleted successfully.": "Kunnskap slettet.",
 	"Knowledge reset successfully.": "Tilbakestilling av kunnskap vellykket.",
 	"Knowledge reset successfully.": "Tilbakestilling av kunnskap vellykket.",
 	"Knowledge updated successfully": "Kunnskap oppdatert",
 	"Knowledge updated successfully": "Kunnskap oppdatert",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Etikett",
 	"Label": "Etikett",
 	"Landing Page Mode": "Modus for startside",
 	"Landing Page Mode": "Modus for startside",
 	"Language": "Språk",
 	"Language": "Språk",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "La stå tomt for å inkludere alle modeller fra endepunktet \"{{URL}}/api/models\"",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "La stå tomt for å inkludere alle modeller fra endepunktet \"{{URL}}/api/models\"",
 	"Leave empty to include all models or select specific models": "La stå tomt for å inkludere alle modeller",
 	"Leave empty to include all models or select specific models": "La stå tomt for å inkludere alle modeller",
 	"Leave empty to use the default prompt, or enter a custom prompt": "La stå tomt for å bruke standard ledetekst, eller angi en tilpasset ledetekst",
 	"Leave empty to use the default prompt, or enter a custom prompt": "La stå tomt for å bruke standard ledetekst, eller angi en tilpasset ledetekst",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Lys",
 	"Light": "Lys",
 	"Listening...": "Lytter ...",
 	"Listening...": "Lytter ...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokale modeller",
 	"Local Models": "Lokale modeller",
 	"Lost": "Tapt",
 	"Lost": "Tapt",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Laget av OpenWebUI-fellesskapet",
+	"Made by Open WebUI Community": "Laget av OpenWebUI-fellesskapet",
 	"Make sure to enclose them with": "Sørg for å omslutte dem med",
 	"Make sure to enclose them with": "Sørg for å omslutte dem med",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Sørg for å eksportere en workflow.json-fil i API-formatet fra ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Sørg for å eksportere en workflow.json-fil i API-formatet fra ComfyUI.",
 	"Manage": "Administrer",
 	"Manage": "Administrer",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Les høyt",
 	"Read Aloud": "Les høyt",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Ta opp tale",
 	"Record voice": "Ta opp tale",
-	"Redirecting you to OpenWebUI Community": "Omdirigerer deg til OpenWebUI-fellesskapet",
+	"Redirecting you to Open WebUI Community": "Omdirigerer deg til OpenWebUI-fellesskapet",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduserer sannsynligheten for å generere meningsløse svar. En høyere verdi (f.eks. 100) vil gi mer varierte svar, mens en lavere verdi (f.eks. 10) vil være mer konservativ. (Standard: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduserer sannsynligheten for å generere meningsløse svar. En høyere verdi (f.eks. 100) vil gi mer varierte svar, mens en lavere verdi (f.eks. 10) vil være mer konservativ. (Standard: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Omtal deg selv som \"Bruker\" (f.eks. \"Bruker lærer spansk\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Omtal deg selv som \"Bruker\" (f.eks. \"Bruker lærer spansk\")",
 	"References from": "Henviser fra",
 	"References from": "Henviser fra",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Innstillinger lagret!",
 	"Settings saved successfully!": "Innstillinger lagret!",
 	"Share": "Del",
 	"Share": "Del",
 	"Share Chat": "Del chat",
 	"Share Chat": "Del chat",
-	"Share to OpenWebUI Community": "Del med OpenWebUI-fellesskapet",
+	"Share to Open WebUI Community": "Del med OpenWebUI-fellesskapet",
 	"Show": "Vis",
 	"Show": "Vis",
 	"Show \"What's New\" modal on login": "Vis \"Hva er nytt\"-modal ved innlogging",
 	"Show \"What's New\" modal on login": "Vis \"Hva er nytt\"-modal ved innlogging",
 	"Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i ventende kontovisning",
 	"Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i ventende kontovisning",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dette tilbakestiller kunnskapsbasen og synkroniserer alle filer. Vil du fortsette?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dette tilbakestiller kunnskapsbasen og synkroniserer alle filer. Vil du fortsette?",
 	"Thorough explanation": "Grundig forklaring",
 	"Thorough explanation": "Grundig forklaring",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Server-URL for Tika kreves.",
 	"Tika Server URL required.": "Server-URL for Tika kreves.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/nl-NL/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Klik hier om",
 	"Click here to": "Klik hier om",
 	"Click here to download user import template file.": "Klik hier om het sjabloonbestand voor gebruikersimport te downloaden.",
 	"Click here to download user import template file.": "Klik hier om het sjabloonbestand voor gebruikersimport te downloaden.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klik hier om meer te leren over faster-whisper en de beschikbare modellen te bekijken.",
 	"Click here to learn more about faster-whisper and see the available models.": "Klik hier om meer te leren over faster-whisper en de beschikbare modellen te bekijken.",
+	"Click here to see available models.": "",
 	"Click here to select": "Klik hier om te selecteren",
 	"Click here to select": "Klik hier om te selecteren",
 	"Click here to select a csv file.": "Klik hier om een csv file te selecteren.",
 	"Click here to select a csv file.": "Klik hier om een csv file te selecteren.",
 	"Click here to select a py file.": "Klik hier om een py-bestand te selecteren.",
 	"Click here to select a py file.": "Klik hier om een py-bestand te selecteren.",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentatie",
 	"Documentation": "Documentatie",
 	"Documents": "Documenten",
 	"Documents": "Documenten",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "maakt geen externe verbindingen, en je gegevens blijven veilig op je lokaal gehoste server.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "maakt geen externe verbindingen, en je gegevens blijven veilig op je lokaal gehoste server.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Heb je geen account?",
 	"Don't have an account?": "Heb je geen account?",
 	"don't install random functions from sources you don't trust.": "installeer geen willekeurige functies van bronnen die je niet vertrouwd",
 	"don't install random functions from sources you don't trust.": "installeer geen willekeurige functies van bronnen die je niet vertrouwd",
 	"don't install random tools from sources you don't trust.": "installeer geen willekeurige gereedschappen van bronnen die je niet vertrouwd",
 	"don't install random tools from sources you don't trust.": "installeer geen willekeurige gereedschappen van bronnen die je niet vertrouwd",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Voeg Chunk Overlap toe",
 	"Enter Chunk Overlap": "Voeg Chunk Overlap toe",
 	"Enter Chunk Size": "Voeg Chunk Size toe",
 	"Enter Chunk Size": "Voeg Chunk Size toe",
 	"Enter description": "Voer beschrijving in",
 	"Enter description": "Voer beschrijving in",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Voer de Github Raw-URL in",
 	"Enter Github Raw URL": "Voer de Github Raw-URL in",
 	"Enter Google PSE API Key": "Voer de Google PSE API-sleutel in",
 	"Enter Google PSE API Key": "Voer de Google PSE API-sleutel in",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Kennis succesvol verwijderd",
 	"Knowledge deleted successfully.": "Kennis succesvol verwijderd",
 	"Knowledge reset successfully.": "Kennis succesvol gereset",
 	"Knowledge reset successfully.": "Kennis succesvol gereset",
 	"Knowledge updated successfully": "Kennis succesvol bijgewerkt",
 	"Knowledge updated successfully": "Kennis succesvol bijgewerkt",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Label",
 	"Label": "Label",
 	"Landing Page Mode": "Landingspaginamodus",
 	"Landing Page Mode": "Landingspaginamodus",
 	"Language": "Taal",
 	"Language": "Taal",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Laat leeg om alle modellen van het \"{{URL}}/models\" endpoint toe te voegen",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Laat leeg om alle modellen van het \"{{URL}}/models\" endpoint toe te voegen",
 	"Leave empty to include all models or select specific models": "Laat leeg om alle modellen mee te nemen, of selecteer specifieke modellen",
 	"Leave empty to include all models or select specific models": "Laat leeg om alle modellen mee te nemen, of selecteer specifieke modellen",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Laat leeg om de standaard prompt te gebruiken, of selecteer een aangepaste prompt",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Laat leeg om de standaard prompt te gebruiken, of selecteer een aangepaste prompt",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Licht",
 	"Light": "Licht",
 	"Listening...": "Aan het luisteren...",
 	"Listening...": "Aan het luisteren...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokale modellen",
 	"Local Models": "Lokale modellen",
 	"Lost": "Verloren",
 	"Lost": "Verloren",
 	"LTR": "LNR",
 	"LTR": "LNR",
-	"Made by OpenWebUI Community": "Gemaakt door OpenWebUI Community",
+	"Made by Open WebUI Community": "Gemaakt door OpenWebUI Community",
 	"Make sure to enclose them with": "Zorg ervoor dat je ze omringt met",
 	"Make sure to enclose them with": "Zorg ervoor dat je ze omringt met",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Zorg ervoor dat je een workflow.json-bestand als API-formaat exporteert vanuit ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Zorg ervoor dat je een workflow.json-bestand als API-formaat exporteert vanuit ComfyUI.",
 	"Manage": "Beheren",
 	"Manage": "Beheren",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Voorlezen",
 	"Read Aloud": "Voorlezen",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Neem stem op",
 	"Record voice": "Neem stem op",
-	"Redirecting you to OpenWebUI Community": "Je wordt doorgestuurd naar OpenWebUI Community",
+	"Redirecting you to Open WebUI Community": "Je wordt doorgestuurd naar OpenWebUI Community",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Vermindert de kans op het genereren van onzin. Een hogere waarde (bijv. 100) zal meer diverse antwoorden geven, terwijl een lagere waarde (bijv. 10) conservatiever zal zijn. (Standaard: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Vermindert de kans op het genereren van onzin. Een hogere waarde (bijv. 100) zal meer diverse antwoorden geven, terwijl een lagere waarde (bijv. 10) conservatiever zal zijn. (Standaard: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refereer naar jezelf als \"user\" (bv. \"User is Spaans aan het leren\"",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refereer naar jezelf als \"user\" (bv. \"User is Spaans aan het leren\"",
 	"References from": "Referenties van",
 	"References from": "Referenties van",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Instellingen succesvol opgeslagen!",
 	"Settings saved successfully!": "Instellingen succesvol opgeslagen!",
 	"Share": "Delen",
 	"Share": "Delen",
 	"Share Chat": "Deel chat",
 	"Share Chat": "Deel chat",
-	"Share to OpenWebUI Community": "Deel naar OpenWebUI-community",
+	"Share to Open WebUI Community": "Deel naar OpenWebUI-community",
 	"Show": "Toon",
 	"Show": "Toon",
 	"Show \"What's New\" modal on login": "Toon \"Wat is nieuw\" bij inloggen",
 	"Show \"What's New\" modal on login": "Toon \"Wat is nieuw\" bij inloggen",
 	"Show Admin Details in Account Pending Overlay": "Admin-details weergeven in overlay in afwachting van account",
 	"Show Admin Details in Account Pending Overlay": "Admin-details weergeven in overlay in afwachting van account",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dit zal de kennisdatabase resetten en alle bestanden synchroniseren. Wilt u doorgaan?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Dit zal de kennisdatabase resetten en alle bestanden synchroniseren. Wilt u doorgaan?",
 	"Thorough explanation": "Gevorderde uitleg",
 	"Thorough explanation": "Gevorderde uitleg",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Tika Server-URL vereist",
 	"Tika Server URL required.": "Tika Server-URL vereist",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/pa-IN/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ",
 	"Click here to": "ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "ਚੁਣਨ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ",
 	"Click here to select": "ਚੁਣਨ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ",
 	"Click here to select a csv file.": "CSV ਫਾਈਲ ਚੁਣਨ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ।",
 	"Click here to select a csv file.": "CSV ਫਾਈਲ ਚੁਣਨ ਲਈ ਇੱਥੇ ਕਲਿੱਕ ਕਰੋ।",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "ਡਾਕੂਮੈਂਟ",
 	"Documents": "ਡਾਕੂਮੈਂਟ",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ਕੋਈ ਬਾਹਰੀ ਕਨੈਕਸ਼ਨ ਨਹੀਂ ਬਣਾਉਂਦਾ, ਅਤੇ ਤੁਹਾਡਾ ਡਾਟਾ ਤੁਹਾਡੇ ਸਥਾਨਕ ਸਰਵਰ 'ਤੇ ਸੁਰੱਖਿਅਤ ਰਹਿੰਦਾ ਹੈ।",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "ਕੋਈ ਬਾਹਰੀ ਕਨੈਕਸ਼ਨ ਨਹੀਂ ਬਣਾਉਂਦਾ, ਅਤੇ ਤੁਹਾਡਾ ਡਾਟਾ ਤੁਹਾਡੇ ਸਥਾਨਕ ਸਰਵਰ 'ਤੇ ਸੁਰੱਖਿਅਤ ਰਹਿੰਦਾ ਹੈ।",
+	"Domain Filter List": "",
 	"Don't have an account?": "ਖਾਤਾ ਨਹੀਂ ਹੈ?",
 	"Don't have an account?": "ਖਾਤਾ ਨਹੀਂ ਹੈ?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "ਚੰਕ ਓਵਰਲੈਪ ਦਰਜ ਕਰੋ",
 	"Enter Chunk Overlap": "ਚੰਕ ਓਵਰਲੈਪ ਦਰਜ ਕਰੋ",
 	"Enter Chunk Size": "ਚੰਕ ਆਕਾਰ ਦਰਜ ਕਰੋ",
 	"Enter Chunk Size": "ਚੰਕ ਆਕਾਰ ਦਰਜ ਕਰੋ",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Github ਕੱਚਾ URL ਦਾਖਲ ਕਰੋ",
 	"Enter Github Raw URL": "Github ਕੱਚਾ URL ਦਾਖਲ ਕਰੋ",
 	"Enter Google PSE API Key": "Google PSE API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ",
 	"Enter Google PSE API Key": "Google PSE API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "ਭਾਸ਼ਾ",
 	"Language": "ਭਾਸ਼ਾ",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "ਹਲਕਾ",
 	"Light": "ਹਲਕਾ",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਦੁਆਰਾ ਬਣਾਇਆ ਗਿਆ",
+	"Made by Open WebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਦੁਆਰਾ ਬਣਾਇਆ ਗਿਆ",
 	"Make sure to enclose them with": "ਸੁਨਿਸ਼ਚਿਤ ਕਰੋ ਕਿ ਉਨ੍ਹਾਂ ਨੂੰ ਘੇਰੋ",
 	"Make sure to enclose them with": "ਸੁਨਿਸ਼ਚਿਤ ਕਰੋ ਕਿ ਉਨ੍ਹਾਂ ਨੂੰ ਘੇਰੋ",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "ਜੋਰ ਨਾਲ ਪੜ੍ਹੋ",
 	"Read Aloud": "ਜੋਰ ਨਾਲ ਪੜ੍ਹੋ",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "ਆਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ",
 	"Record voice": "ਆਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ",
-	"Redirecting you to OpenWebUI Community": "ਤੁਹਾਨੂੰ ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਵੱਲ ਰੀਡਾਇਰੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ",
+	"Redirecting you to Open WebUI Community": "ਤੁਹਾਨੂੰ ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਵੱਲ ਰੀਡਾਇਰੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "ਸੈਟਿੰਗਾਂ ਸਫਲਤਾਪੂਰਵਕ ਸੰਭਾਲੀਆਂ ਗਈਆਂ!",
 	"Settings saved successfully!": "ਸੈਟਿੰਗਾਂ ਸਫਲਤਾਪੂਰਵਕ ਸੰਭਾਲੀਆਂ ਗਈਆਂ!",
 	"Share": "ਸਾਂਝਾ ਕਰੋ",
 	"Share": "ਸਾਂਝਾ ਕਰੋ",
 	"Share Chat": "ਗੱਲਬਾਤ ਸਾਂਝੀ ਕਰੋ",
 	"Share Chat": "ਗੱਲਬਾਤ ਸਾਂਝੀ ਕਰੋ",
-	"Share to OpenWebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਨਾਲ ਸਾਂਝਾ ਕਰੋ",
+	"Share to Open WebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਨਾਲ ਸਾਂਝਾ ਕਰੋ",
 	"Show": "ਦਿਖਾਓ",
 	"Show": "ਦਿਖਾਓ",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "ਵਿਸਥਾਰ ਨਾਲ ਵਿਆਖਿਆ",
 	"Thorough explanation": "ਵਿਸਥਾਰ ਨਾਲ ਵਿਆਖਿਆ",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/pl-PL/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Kliknij tutaj, żeby",
 	"Click here to": "Kliknij tutaj, żeby",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Kliknij tutaj, aby wybrać",
 	"Click here to select": "Kliknij tutaj, aby wybrać",
 	"Click here to select a csv file.": "Kliknij tutaj, żeby wybrać plik CSV",
 	"Click here to select a csv file.": "Kliknij tutaj, żeby wybrać plik CSV",
 	"Click here to select a py file.": "",
 	"Click here to select a py file.": "",
@@ -290,6 +291,7 @@
 	"Documentation": "",
 	"Documentation": "",
 	"Documents": "Dokumenty",
 	"Documents": "Dokumenty",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nie nawiązuje żadnych zewnętrznych połączeń, a Twoje dane pozostają bezpiecznie na Twoim lokalnie hostowanym serwerze.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nie nawiązuje żadnych zewnętrznych połączeń, a Twoje dane pozostają bezpiecznie na Twoim lokalnie hostowanym serwerze.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nie masz konta?",
 	"Don't have an account?": "Nie masz konta?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Wprowadź zakchodzenie bloku",
 	"Enter Chunk Overlap": "Wprowadź zakchodzenie bloku",
 	"Enter Chunk Size": "Wprowadź rozmiar bloku",
 	"Enter Chunk Size": "Wprowadź rozmiar bloku",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Wprowadź nieprzetworzony adres URL usługi Github",
 	"Enter Github Raw URL": "Wprowadź nieprzetworzony adres URL usługi Github",
 	"Enter Google PSE API Key": "Wprowadź klucz API Google PSE",
 	"Enter Google PSE API Key": "Wprowadź klucz API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Język",
 	"Language": "Język",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Jasny",
 	"Light": "Jasny",
 	"Listening...": "",
 	"Listening...": "",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "",
 	"Local Models": "",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Stworzone przez społeczność OpenWebUI",
+	"Made by Open WebUI Community": "Stworzone przez społeczność OpenWebUI",
 	"Make sure to enclose them with": "Upewnij się, że są one zamknięte w",
 	"Make sure to enclose them with": "Upewnij się, że są one zamknięte w",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "",
 	"Manage": "",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Czytaj na głos",
 	"Read Aloud": "Czytaj na głos",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Nagraj głos",
 	"Record voice": "Nagraj głos",
-	"Redirecting you to OpenWebUI Community": "Przekierowujemy Cię do społeczności OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Przekierowujemy Cię do społeczności OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Ustawienia zapisane pomyślnie!",
 	"Settings saved successfully!": "Ustawienia zapisane pomyślnie!",
 	"Share": "Udostępnij",
 	"Share": "Udostępnij",
 	"Share Chat": "Udostępnij czat",
 	"Share Chat": "Udostępnij czat",
-	"Share to OpenWebUI Community": "Dziel się z społecznością OpenWebUI",
+	"Share to Open WebUI Community": "Dziel się z społecznością OpenWebUI",
 	"Show": "Pokaż",
 	"Show": "Pokaż",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "",
 	"Show Admin Details in Account Pending Overlay": "",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Dokładne wyjaśnienie",
 	"Thorough explanation": "Dokładne wyjaśnienie",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/pt-BR/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Clique aqui para",
 	"Click here to": "Clique aqui para",
 	"Click here to download user import template file.": "Clique aqui para baixar o arquivo de modelo de importação de usuários.",
 	"Click here to download user import template file.": "Clique aqui para baixar o arquivo de modelo de importação de usuários.",
 	"Click here to learn more about faster-whisper and see the available models.": "Clique aqui para aprender mais sobre Whisper e ver os modelos disponíveis.",
 	"Click here to learn more about faster-whisper and see the available models.": "Clique aqui para aprender mais sobre Whisper e ver os modelos disponíveis.",
+	"Click here to see available models.": "",
 	"Click here to select": "Clique aqui para enviar",
 	"Click here to select": "Clique aqui para enviar",
 	"Click here to select a csv file.": "Clique aqui para enviar um arquivo csv.",
 	"Click here to select a csv file.": "Clique aqui para enviar um arquivo csv.",
 	"Click here to select a py file.": "Clique aqui para enviar um arquivo python.",
 	"Click here to select a py file.": "Clique aqui para enviar um arquivo python.",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentação",
 	"Documentation": "Documentação",
 	"Documents": "Documentos",
 	"Documents": "Documentos",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "não faz nenhuma conexão externa, e seus dados permanecem seguros no seu servidor local.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "não faz nenhuma conexão externa, e seus dados permanecem seguros no seu servidor local.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Não tem uma conta?",
 	"Don't have an account?": "Não tem uma conta?",
 	"don't install random functions from sources you don't trust.": "não instale funções aleatórias de fontes que você não confia.",
 	"don't install random functions from sources you don't trust.": "não instale funções aleatórias de fontes que você não confia.",
 	"don't install random tools from sources you don't trust.": "não instale ferramentas aleatórias de fontes que você não confia.",
 	"don't install random tools from sources you don't trust.": "não instale ferramentas aleatórias de fontes que você não confia.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Digite a Sobreposição de Chunk",
 	"Enter Chunk Overlap": "Digite a Sobreposição de Chunk",
 	"Enter Chunk Size": "Digite o Tamanho do Chunk",
 	"Enter Chunk Size": "Digite o Tamanho do Chunk",
 	"Enter description": "Digite a descrição",
 	"Enter description": "Digite a descrição",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Digite a URL bruta do Github",
 	"Enter Github Raw URL": "Digite a URL bruta do Github",
 	"Enter Google PSE API Key": "Digite a Chave API do Google PSE",
 	"Enter Google PSE API Key": "Digite a Chave API do Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Conhecimento excluído com sucesso.",
 	"Knowledge deleted successfully.": "Conhecimento excluído com sucesso.",
 	"Knowledge reset successfully.": "Conhecimento resetado com sucesso.",
 	"Knowledge reset successfully.": "Conhecimento resetado com sucesso.",
 	"Knowledge updated successfully": "Conhecimento atualizado com sucesso",
 	"Knowledge updated successfully": "Conhecimento atualizado com sucesso",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "Rótulo",
 	"Label": "Rótulo",
 	"Landing Page Mode": "Modo Landing Page",
 	"Landing Page Mode": "Modo Landing Page",
 	"Language": "Idioma",
 	"Language": "Idioma",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Deixe vazio para incluir todos os modelos do endpoint \"{{URL}}/models\"",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "Deixe vazio para incluir todos os modelos do endpoint \"{{URL}}/models\"",
 	"Leave empty to include all models or select specific models": "Deixe vazio para incluir todos os modelos ou selecione modelos especificos",
 	"Leave empty to include all models or select specific models": "Deixe vazio para incluir todos os modelos ou selecione modelos especificos",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Deixe vazio para usar o prompt padrão, ou insira um prompt personalizado",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Deixe vazio para usar o prompt padrão, ou insira um prompt personalizado",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Claro",
 	"Light": "Claro",
 	"Listening...": "Escutando...",
 	"Listening...": "Escutando...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Modelos Locais",
 	"Local Models": "Modelos Locais",
 	"Lost": "Perdeu",
 	"Lost": "Perdeu",
 	"LTR": "Esquerda para Direita",
 	"LTR": "Esquerda para Direita",
-	"Made by OpenWebUI Community": "Feito pela Comunidade OpenWebUI",
+	"Made by Open WebUI Community": "Feito pela Comunidade OpenWebUI",
 	"Make sure to enclose them with": "Certifique-se de encerrá-los com",
 	"Make sure to enclose them with": "Certifique-se de encerrá-los com",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Certifique-se de exportar um arquivo workflow.json como o formato API do ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Certifique-se de exportar um arquivo workflow.json como o formato API do ComfyUI.",
 	"Manage": "Gerenciar",
 	"Manage": "Gerenciar",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Ler em Voz Alta",
 	"Read Aloud": "Ler em Voz Alta",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Gravar voz",
 	"Record voice": "Gravar voz",
-	"Redirecting you to OpenWebUI Community": "Redirecionando você para a Comunidade OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Redirecionando você para a Comunidade OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduz a probabilidade de gerar absurdos. Um valor mais alto (por exemplo, 100) dará respostas mais diversas, enquanto um valor mais baixo (por exemplo, 10) será mais conservador. (Padrão: 40)",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "Reduz a probabilidade de gerar absurdos. Um valor mais alto (por exemplo, 100) dará respostas mais diversas, enquanto um valor mais baixo (por exemplo, 10) será mais conservador. (Padrão: 40)",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refira-se como \"Usuário\" (por exemplo, \"Usuário está aprendendo espanhol\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refira-se como \"Usuário\" (por exemplo, \"Usuário está aprendendo espanhol\")",
 	"References from": "Referências de",
 	"References from": "Referências de",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Configurações salvas com sucesso!",
 	"Settings saved successfully!": "Configurações salvas com sucesso!",
 	"Share": "Compartilhar",
 	"Share": "Compartilhar",
 	"Share Chat": "Compartilhar Chat",
 	"Share Chat": "Compartilhar Chat",
-	"Share to OpenWebUI Community": "Compartilhar com a Comunidade OpenWebUI",
+	"Share to Open WebUI Community": "Compartilhar com a Comunidade OpenWebUI",
 	"Show": "Mostrar",
 	"Show": "Mostrar",
 	"Show \"What's New\" modal on login": "Mostrar \"O que há de Novo\" no login",
 	"Show \"What's New\" modal on login": "Mostrar \"O que há de Novo\" no login",
 	"Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na Sobreposição de Conta Pendentes",
 	"Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na Sobreposição de Conta Pendentes",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Esta ação resetará a base de conhecimento e sincronizará todos os arquivos. Deseja continuar?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Esta ação resetará a base de conhecimento e sincronizará todos os arquivos. Deseja continuar?",
 	"Thorough explanation": "Explicação detalhada",
 	"Thorough explanation": "Explicação detalhada",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "URL do servidor Tika necessária.",
 	"Tika Server URL required.": "URL do servidor Tika necessária.",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/pt-PT/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Clique aqui para",
 	"Click here to": "Clique aqui para",
 	"Click here to download user import template file.": "",
 	"Click here to download user import template file.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Clique aqui para selecionar",
 	"Click here to select": "Clique aqui para selecionar",
 	"Click here to select a csv file.": "Clique aqui para selecionar um ficheiro csv.",
 	"Click here to select a csv file.": "Clique aqui para selecionar um ficheiro csv.",
 	"Click here to select a py file.": "Clique aqui para selecionar um ficheiro py",
 	"Click here to select a py file.": "Clique aqui para selecionar um ficheiro py",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentação",
 	"Documentation": "Documentação",
 	"Documents": "Documentos",
 	"Documents": "Documentos",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "não faz conexões externas e os seus dados permanecem seguros no seu servidor alojado localmente.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "não faz conexões externas e os seus dados permanecem seguros no seu servidor alojado localmente.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Não tem uma conta?",
 	"Don't have an account?": "Não tem uma conta?",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random functions from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
 	"don't install random tools from sources you don't trust.": "",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Escreva a Sobreposição de Fragmento",
 	"Enter Chunk Overlap": "Escreva a Sobreposição de Fragmento",
 	"Enter Chunk Size": "Escreva o Tamanho do Fragmento",
 	"Enter Chunk Size": "Escreva o Tamanho do Fragmento",
 	"Enter description": "",
 	"Enter description": "",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Escreva o URL cru do Github",
 	"Enter Github Raw URL": "Escreva o URL cru do Github",
 	"Enter Google PSE API Key": "Escreva a chave da API PSE do Google",
 	"Enter Google PSE API Key": "Escreva a chave da API PSE do Google",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "",
 	"Knowledge deleted successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge reset successfully.": "",
 	"Knowledge updated successfully": "",
 	"Knowledge updated successfully": "",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "",
 	"Landing Page Mode": "",
 	"Language": "Idioma",
 	"Language": "Idioma",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Claro",
 	"Light": "Claro",
 	"Listening...": "A escutar...",
 	"Listening...": "A escutar...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Modelos Locais",
 	"Local Models": "Modelos Locais",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Feito pela Comunidade OpenWebUI",
+	"Made by Open WebUI Community": "Feito pela Comunidade OpenWebUI",
 	"Make sure to enclose them with": "Certifique-se de colocá-los entre",
 	"Make sure to enclose them with": "Certifique-se de colocá-los entre",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "",
 	"Manage": "Gerir",
 	"Manage": "Gerir",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Ler em Voz Alta",
 	"Read Aloud": "Ler em Voz Alta",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Gravar voz",
 	"Record voice": "Gravar voz",
-	"Redirecting you to OpenWebUI Community": "Redirecionando-o para a Comunidade OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Redirecionando-o para a Comunidade OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refera-se a si próprio como \"User\" (por exemplo, \"User está a aprender Espanhol\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refera-se a si próprio como \"User\" (por exemplo, \"User está a aprender Espanhol\")",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Configurações guardadas com sucesso!",
 	"Settings saved successfully!": "Configurações guardadas com sucesso!",
 	"Share": "Partilhar",
 	"Share": "Partilhar",
 	"Share Chat": "Partilhar Conversa",
 	"Share Chat": "Partilhar Conversa",
-	"Share to OpenWebUI Community": "Partilhar com a Comunidade OpenWebUI",
+	"Share to Open WebUI Community": "Partilhar com a Comunidade OpenWebUI",
 	"Show": "Mostrar",
 	"Show": "Mostrar",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na sobreposição de Conta Pendente",
 	"Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na sobreposição de Conta Pendente",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "",
 	"Thorough explanation": "Explicação Minuciosa",
 	"Thorough explanation": "Explicação Minuciosa",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "",
 	"Tika": "",
 	"Tika Server URL required.": "",
 	"Tika Server URL required.": "",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/ro-RO/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Apasă aici pentru",
 	"Click here to": "Apasă aici pentru",
 	"Click here to download user import template file.": "Apasă aici pentru a descărca fișierul șablon de import utilizator.",
 	"Click here to download user import template file.": "Apasă aici pentru a descărca fișierul șablon de import utilizator.",
 	"Click here to learn more about faster-whisper and see the available models.": "Faceți clic aici pentru a afla mai multe despre faster-whisper și pentru a vedea modelele disponibile.",
 	"Click here to learn more about faster-whisper and see the available models.": "Faceți clic aici pentru a afla mai multe despre faster-whisper și pentru a vedea modelele disponibile.",
+	"Click here to see available models.": "",
 	"Click here to select": "Apasă aici pentru a selecta",
 	"Click here to select": "Apasă aici pentru a selecta",
 	"Click here to select a csv file.": "Apasă aici pentru a selecta un fișier csv.",
 	"Click here to select a csv file.": "Apasă aici pentru a selecta un fișier csv.",
 	"Click here to select a py file.": "Apasă aici pentru a selecta un fișier py.",
 	"Click here to select a py file.": "Apasă aici pentru a selecta un fișier py.",
@@ -290,6 +291,7 @@
 	"Documentation": "Documentație",
 	"Documentation": "Documentație",
 	"Documents": "Documente",
 	"Documents": "Documente",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nu face nicio conexiune externă, iar datele tale rămân în siguranță pe serverul găzduit local.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nu face nicio conexiune externă, iar datele tale rămân în siguranță pe serverul găzduit local.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nu ai un cont?",
 	"Don't have an account?": "Nu ai un cont?",
 	"don't install random functions from sources you don't trust.": "nu instala funcții aleatorii din surse în care nu ai încredere.",
 	"don't install random functions from sources you don't trust.": "nu instala funcții aleatorii din surse în care nu ai încredere.",
 	"don't install random tools from sources you don't trust.": "nu instala instrumente aleatorii din surse în care nu ai încredere.",
 	"don't install random tools from sources you don't trust.": "nu instala instrumente aleatorii din surse în care nu ai încredere.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Introduceți Suprapunerea Blocului",
 	"Enter Chunk Overlap": "Introduceți Suprapunerea Blocului",
 	"Enter Chunk Size": "Introduceți Dimensiunea Blocului",
 	"Enter Chunk Size": "Introduceți Dimensiunea Blocului",
 	"Enter description": "Introduceți descrierea",
 	"Enter description": "Introduceți descrierea",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Introduceți URL-ul Raw de pe Github",
 	"Enter Github Raw URL": "Introduceți URL-ul Raw de pe Github",
 	"Enter Google PSE API Key": "Introduceți Cheia API Google PSE",
 	"Enter Google PSE API Key": "Introduceți Cheia API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Cunoștințele au fost șterse cu succes.",
 	"Knowledge deleted successfully.": "Cunoștințele au fost șterse cu succes.",
 	"Knowledge reset successfully.": "Resetarea cunoștințelor a fost efectuată cu succes.",
 	"Knowledge reset successfully.": "Resetarea cunoștințelor a fost efectuată cu succes.",
 	"Knowledge updated successfully": "Cunoașterea a fost actualizată cu succes",
 	"Knowledge updated successfully": "Cunoașterea a fost actualizată cu succes",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Modul Pagină de Aterizare",
 	"Landing Page Mode": "Modul Pagină de Aterizare",
 	"Language": "Limbă",
 	"Language": "Limbă",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "Lăsați gol pentru a include toate modelele sau selectați modele specifice",
 	"Leave empty to include all models or select specific models": "Lăsați gol pentru a include toate modelele sau selectați modele specifice",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Lăsați gol pentru a utiliza promptul implicit sau introduceți un prompt personalizat",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Lăsați gol pentru a utiliza promptul implicit sau introduceți un prompt personalizat",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Luminos",
 	"Light": "Luminos",
 	"Listening...": "Ascult...",
 	"Listening...": "Ascult...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Modele Locale",
 	"Local Models": "Modele Locale",
 	"Lost": "Pierdut",
 	"Lost": "Pierdut",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Realizat de Comunitatea OpenWebUI",
+	"Made by Open WebUI Community": "Realizat de Comunitatea OpenWebUI",
 	"Make sure to enclose them with": "Asigurați-vă că le închideți cu",
 	"Make sure to enclose them with": "Asigurați-vă că le închideți cu",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Asigură-te că exporți un fișier {{workflow.json}} în format API din {{ComfyUI}}.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Asigură-te că exporți un fișier {{workflow.json}} în format API din {{ComfyUI}}.",
 	"Manage": "Gestionează",
 	"Manage": "Gestionează",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Citește cu Voce Tare",
 	"Read Aloud": "Citește cu Voce Tare",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Înregistrează vocea",
 	"Record voice": "Înregistrează vocea",
-	"Redirecting you to OpenWebUI Community": "Vă redirecționăm către Comunitatea OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Vă redirecționăm către Comunitatea OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referiți-vă la dvs. ca \"Utilizator\" (de ex., \"Utilizatorul învață spaniolă\")",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referiți-vă la dvs. ca \"Utilizator\" (de ex., \"Utilizatorul învață spaniolă\")",
 	"References from": "Referințe din",
 	"References from": "Referințe din",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Setările au fost salvate cu succes!",
 	"Settings saved successfully!": "Setările au fost salvate cu succes!",
 	"Share": "Partajează",
 	"Share": "Partajează",
 	"Share Chat": "Partajează Conversația",
 	"Share Chat": "Partajează Conversația",
-	"Share to OpenWebUI Community": "Partajează cu Comunitatea OpenWebUI",
+	"Share to Open WebUI Community": "Partajează cu Comunitatea OpenWebUI",
 	"Show": "Afișează",
 	"Show": "Afișează",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Afișează Detaliile Administratorului în Suprapunerea Contului În Așteptare",
 	"Show Admin Details in Account Pending Overlay": "Afișează Detaliile Administratorului în Suprapunerea Contului În Așteptare",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Aceasta va reseta baza de cunoștințe și va sincroniza toate fișierele. Doriți să continuați?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Aceasta va reseta baza de cunoștințe și va sincroniza toate fișierele. Doriți să continuați?",
 	"Thorough explanation": "Explicație detaliată",
 	"Thorough explanation": "Explicație detaliată",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Este necesar URL-ul serverului Tika.",
 	"Tika Server URL required.": "Este necesar URL-ul serverului Tika.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

+ 10 - 3
src/lib/i18n/locales/ru-RU/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Нажмите здесь, чтобы",
 	"Click here to": "Нажмите здесь, чтобы",
 	"Click here to download user import template file.": "Нажмите здесь, чтобы загрузить файл шаблона импорта пользователя",
 	"Click here to download user import template file.": "Нажмите здесь, чтобы загрузить файл шаблона импорта пользователя",
 	"Click here to learn more about faster-whisper and see the available models.": "",
 	"Click here to learn more about faster-whisper and see the available models.": "",
+	"Click here to see available models.": "",
 	"Click here to select": "Нажмите здесь, чтобы выбрать",
 	"Click here to select": "Нажмите здесь, чтобы выбрать",
 	"Click here to select a csv file.": "Нажмите здесь, чтобы выбрать csv-файл.",
 	"Click here to select a csv file.": "Нажмите здесь, чтобы выбрать csv-файл.",
 	"Click here to select a py file.": "Нажмите здесь, чтобы выбрать py-файл",
 	"Click here to select a py file.": "Нажмите здесь, чтобы выбрать py-файл",
@@ -290,6 +291,7 @@
 	"Documentation": "Документация",
 	"Documentation": "Документация",
 	"Documents": "Документы",
 	"Documents": "Документы",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "не устанавливает никаких внешних соединений, и ваши данные надежно хранятся на вашем локальном сервере.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "не устанавливает никаких внешних соединений, и ваши данные надежно хранятся на вашем локальном сервере.",
+	"Domain Filter List": "",
 	"Don't have an account?": "У вас нет аккаунта?",
 	"Don't have an account?": "У вас нет аккаунта?",
 	"don't install random functions from sources you don't trust.": "не устанавливайте случайные функции из источников, которым вы не доверяете.",
 	"don't install random functions from sources you don't trust.": "не устанавливайте случайные функции из источников, которым вы не доверяете.",
 	"don't install random tools from sources you don't trust.": "не устанавливайте случайные инструменты из источников, которым вы не доверяете.",
 	"don't install random tools from sources you don't trust.": "не устанавливайте случайные инструменты из источников, которым вы не доверяете.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Введите перекрытие фрагмента",
 	"Enter Chunk Overlap": "Введите перекрытие фрагмента",
 	"Enter Chunk Size": "Введите размер фрагмента",
 	"Enter Chunk Size": "Введите размер фрагмента",
 	"Enter description": "Введите описание",
 	"Enter description": "Введите описание",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Введите необработанный URL-адрес Github",
 	"Enter Github Raw URL": "Введите необработанный URL-адрес Github",
 	"Enter Google PSE API Key": "Введите ключ API Google PSE",
 	"Enter Google PSE API Key": "Введите ключ API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Знания успешно удалены.",
 	"Knowledge deleted successfully.": "Знания успешно удалены.",
 	"Knowledge reset successfully.": "Знания успешно сброшены.",
 	"Knowledge reset successfully.": "Знания успешно сброшены.",
 	"Knowledge updated successfully": "Знания успешно обновлены",
 	"Knowledge updated successfully": "Знания успешно обновлены",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Режим Целевой Страницы",
 	"Landing Page Mode": "Режим Целевой Страницы",
 	"Language": "Язык",
 	"Language": "Язык",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to include all models or select specific models": "",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Оставьте пустым, чтобы использовать промпт по умолчанию, или введите пользовательский промпт",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Оставьте пустым, чтобы использовать промпт по умолчанию, или введите пользовательский промпт",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Светлый",
 	"Light": "Светлый",
 	"Listening...": "Слушаю...",
 	"Listening...": "Слушаю...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Локальные модели",
 	"Local Models": "Локальные модели",
 	"Lost": "",
 	"Lost": "",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Сделано сообществом OpenWebUI",
+	"Made by Open WebUI Community": "Сделано сообществом OpenWebUI",
 	"Make sure to enclose them with": "Убедитесь, что они заключены в",
 	"Make sure to enclose them with": "Убедитесь, что они заключены в",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Убедитесь, что экспортируете файл workflow.json в формате API из ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Убедитесь, что экспортируете файл workflow.json в формате API из ComfyUI.",
 	"Manage": "Управлять",
 	"Manage": "Управлять",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Прочитать вслух",
 	"Read Aloud": "Прочитать вслух",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Записать голос",
 	"Record voice": "Записать голос",
-	"Redirecting you to OpenWebUI Community": "Перенаправляем вас в сообщество OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Перенаправляем вас в сообщество OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Называйте себя \"User\" (например, \"User is learning Spanish\").",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Называйте себя \"User\" (например, \"User is learning Spanish\").",
 	"References from": "",
 	"References from": "",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Настройки успешно сохранены!",
 	"Settings saved successfully!": "Настройки успешно сохранены!",
 	"Share": "Поделиться",
 	"Share": "Поделиться",
 	"Share Chat": "Поделиться чатом",
 	"Share Chat": "Поделиться чатом",
-	"Share to OpenWebUI Community": "Поделиться с сообществом OpenWebUI",
+	"Share to Open WebUI Community": "Поделиться с сообществом OpenWebUI",
 	"Show": "Показать",
 	"Show": "Показать",
 	"Show \"What's New\" modal on login": "Показывать окно «Что нового» при входе в систему",
 	"Show \"What's New\" modal on login": "Показывать окно «Что нового» при входе в систему",
 	"Show Admin Details in Account Pending Overlay": "Показывать данные администратора в оверлее ожидающей учетной записи",
 	"Show Admin Details in Account Pending Overlay": "Показывать данные администратора в оверлее ожидающей учетной записи",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Это сбросит базу знаний и синхронизирует все файлы. Хотите продолжить?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Это сбросит базу знаний и синхронизирует все файлы. Хотите продолжить?",
 	"Thorough explanation": "Подробное объяснение",
 	"Thorough explanation": "Подробное объяснение",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Требуется URL-адрес сервера Tika.",
 	"Tika Server URL required.": "Требуется URL-адрес сервера Tika.",
 	"Tiktoken": "",
 	"Tiktoken": "",

+ 10 - 3
src/lib/i18n/locales/sk-SK/translation.json

@@ -163,6 +163,7 @@
 	"Click here to": "Kliknite tu na",
 	"Click here to": "Kliknite tu na",
 	"Click here to download user import template file.": "Kliknite tu pre stiahnutie šablóny súboru na import užívateľov.",
 	"Click here to download user import template file.": "Kliknite tu pre stiahnutie šablóny súboru na import užívateľov.",
 	"Click here to learn more about faster-whisper and see the available models.": "Kliknite sem a dozviete sa viac o faster-whisper a pozrite si dostupné modely.",
 	"Click here to learn more about faster-whisper and see the available models.": "Kliknite sem a dozviete sa viac o faster-whisper a pozrite si dostupné modely.",
+	"Click here to see available models.": "",
 	"Click here to select": "Kliknite sem pre výber",
 	"Click here to select": "Kliknite sem pre výber",
 	"Click here to select a csv file.": "Kliknite sem pre výber súboru typu csv.",
 	"Click here to select a csv file.": "Kliknite sem pre výber súboru typu csv.",
 	"Click here to select a py file.": "Kliknite sem pre výber {{py}} súboru.",
 	"Click here to select a py file.": "Kliknite sem pre výber {{py}} súboru.",
@@ -290,6 +291,7 @@
 	"Documentation": "Dokumentácia",
 	"Documentation": "Dokumentácia",
 	"Documents": "Dokumenty",
 	"Documents": "Dokumenty",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nevytvára žiadne externé pripojenia a vaše dáta zostávajú bezpečne na vašom lokálnom serveri.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "nevytvára žiadne externé pripojenia a vaše dáta zostávajú bezpečne na vašom lokálnom serveri.",
+	"Domain Filter List": "",
 	"Don't have an account?": "Nemáte účet?",
 	"Don't have an account?": "Nemáte účet?",
 	"don't install random functions from sources you don't trust.": "Neinštalujte náhodné funkcie zo zdrojov, ktorým nedôverujete.",
 	"don't install random functions from sources you don't trust.": "Neinštalujte náhodné funkcie zo zdrojov, ktorým nedôverujete.",
 	"don't install random tools from sources you don't trust.": "Neinštalujte náhodné nástroje zo zdrojov, ktorým nedôverujete.",
 	"don't install random tools from sources you don't trust.": "Neinštalujte náhodné nástroje zo zdrojov, ktorým nedôverujete.",
@@ -349,6 +351,7 @@
 	"Enter Chunk Overlap": "Zadajte prekryv časti",
 	"Enter Chunk Overlap": "Zadajte prekryv časti",
 	"Enter Chunk Size": "Zadajte veľkosť časti",
 	"Enter Chunk Size": "Zadajte veľkosť časti",
 	"Enter description": "Zadajte popis",
 	"Enter description": "Zadajte popis",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "",
 	"Enter Exa API Key": "",
 	"Enter Exa API Key": "",
 	"Enter Github Raw URL": "Zadajte URL adresu Github Raw",
 	"Enter Github Raw URL": "Zadajte URL adresu Github Raw",
 	"Enter Google PSE API Key": "Zadajte kľúč rozhrania API Google PSE",
 	"Enter Google PSE API Key": "Zadajte kľúč rozhrania API Google PSE",
@@ -552,6 +555,8 @@
 	"Knowledge deleted successfully.": "Znalosti boli úspešne odstránené.",
 	"Knowledge deleted successfully.": "Znalosti boli úspešne odstránené.",
 	"Knowledge reset successfully.": "Úspešné obnovenie znalostí.",
 	"Knowledge reset successfully.": "Úspešné obnovenie znalostí.",
 	"Knowledge updated successfully": "Znalosti úspešne aktualizované",
 	"Knowledge updated successfully": "Znalosti úspešne aktualizované",
+	"Kokoro.js (Browser)": "",
+	"Kokoro.js Dtype": "",
 	"Label": "",
 	"Label": "",
 	"Landing Page Mode": "Režim vstupnej stránky",
 	"Landing Page Mode": "Režim vstupnej stránky",
 	"Language": "Jazyk",
 	"Language": "Jazyk",
@@ -566,6 +571,7 @@
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models from \"{{URL}}/models\" endpoint": "",
 	"Leave empty to include all models or select specific models": "Nechajte prázdne pre zahrnutie všetkých modelov alebo vyberte konkrétne modely.",
 	"Leave empty to include all models or select specific models": "Nechajte prázdne pre zahrnutie všetkých modelov alebo vyberte konkrétne modely.",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Nechajte prázdne pre použitie predvoleného podnetu, alebo zadajte vlastný podnet.",
 	"Leave empty to use the default prompt, or enter a custom prompt": "Nechajte prázdne pre použitie predvoleného podnetu, alebo zadajte vlastný podnet.",
+	"Leave model field empty to use the default model.": "",
 	"Light": "Svetlo",
 	"Light": "Svetlo",
 	"Listening...": "Počúvanie...",
 	"Listening...": "Počúvanie...",
 	"Llama.cpp": "",
 	"Llama.cpp": "",
@@ -574,7 +580,7 @@
 	"Local Models": "Lokálne modely",
 	"Local Models": "Lokálne modely",
 	"Lost": "Stratený",
 	"Lost": "Stratený",
 	"LTR": "LTR",
 	"LTR": "LTR",
-	"Made by OpenWebUI Community": "Vytvorené komunitou OpenWebUI",
+	"Made by Open WebUI Community": "Vytvorené komunitou OpenWebUI",
 	"Make sure to enclose them with": "Uistite sa, že sú uzavreté pomocou",
 	"Make sure to enclose them with": "Uistite sa, že sú uzavreté pomocou",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Uistite sa, že exportujete súbor workflow.json vo formáte API z ComfyUI.",
 	"Make sure to export a workflow.json file as API format from ComfyUI.": "Uistite sa, že exportujete súbor workflow.json vo formáte API z ComfyUI.",
 	"Manage": "Spravovať",
 	"Manage": "Spravovať",
@@ -754,7 +760,7 @@
 	"Read Aloud": "Čítať nahlas",
 	"Read Aloud": "Čítať nahlas",
 	"Reasoning Effort": "",
 	"Reasoning Effort": "",
 	"Record voice": "Nahrať hlas",
 	"Record voice": "Nahrať hlas",
-	"Redirecting you to OpenWebUI Community": "Presmerovanie na komunitu OpenWebUI",
+	"Redirecting you to Open WebUI Community": "Presmerovanie na komunitu OpenWebUI",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative. (Default: 40)": "",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na seba ako na \"užívateľa\" (napr. \"Užívateľ sa učí španielsky\").",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na seba ako na \"užívateľa\" (napr. \"Užívateľ sa učí španielsky\").",
 	"References from": "Referencie z",
 	"References from": "Referencie z",
@@ -869,7 +875,7 @@
 	"Settings saved successfully!": "Nastavenia boli úspešne uložené!",
 	"Settings saved successfully!": "Nastavenia boli úspešne uložené!",
 	"Share": "Zdieľať",
 	"Share": "Zdieľať",
 	"Share Chat": "Zdieľať chat",
 	"Share Chat": "Zdieľať chat",
-	"Share to OpenWebUI Community": "Zdieľať s komunitou OpenWebUI",
+	"Share to Open WebUI Community": "Zdieľať s komunitou OpenWebUI",
 	"Show": "Zobraziť",
 	"Show": "Zobraziť",
 	"Show \"What's New\" modal on login": "",
 	"Show \"What's New\" modal on login": "",
 	"Show Admin Details in Account Pending Overlay": "Zobraziť podrobnosti administrátora v prekryvnom okne s čakajúcim účtom",
 	"Show Admin Details in Account Pending Overlay": "Zobraziť podrobnosti administrátora v prekryvnom okne s čakajúcim účtom",
@@ -944,6 +950,7 @@
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Toto obnoví znalostnú databázu a synchronizuje všetky súbory. Prajete si pokračovať?",
 	"This will reset the knowledge base and sync all files. Do you wish to continue?": "Toto obnoví znalostnú databázu a synchronizuje všetky súbory. Prajete si pokračovať?",
 	"Thorough explanation": "Obsiahle vysvetlenie",
 	"Thorough explanation": "Obsiahle vysvetlenie",
 	"Thought for {{DURATION}}": "",
 	"Thought for {{DURATION}}": "",
+	"Thought for {{DURATION}} seconds": "",
 	"Tika": "Tika",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Je vyžadovaná URL adresa servera Tika.",
 	"Tika Server URL required.": "Je vyžadovaná URL adresa servera Tika.",
 	"Tiktoken": "Tiktoken",
 	"Tiktoken": "Tiktoken",

部分文件因文件數量過多而無法顯示