Преглед изворни кода

Merge branch 'dev' into cla

Tim Jaeryang Baek пре 3 месеци
родитељ
комит
08a35417f2
56 измењених фајлова са 1887 додато и 1276 уклоњено
  1. 1 1
      .github/pull_request_template.md
  2. 7 1
      LICENSE
  3. 1 2
      README.md
  4. 1 1
      backend/open_webui/__init__.py
  5. 42 0
      backend/open_webui/config.py
  6. 14 0
      backend/open_webui/env.py
  7. 25 2
      backend/open_webui/main.py
  8. 53 0
      backend/open_webui/retrieval/loaders/external.py
  9. 34 7
      backend/open_webui/retrieval/vector/dbs/qdrant.py
  10. 47 0
      backend/open_webui/retrieval/web/external.py
  11. 8 0
      backend/open_webui/retrieval/web/utils.py
  12. 7 0
      backend/open_webui/routers/auths.py
  13. 4 2
      backend/open_webui/routers/files.py
  14. 9 8
      backend/open_webui/routers/knowledge.py
  15. 7 1
      backend/open_webui/routers/ollama.py
  16. 6 0
      backend/open_webui/routers/openai.py
  17. 38 2
      backend/open_webui/routers/retrieval.py
  18. 31 0
      backend/open_webui/routers/users.py
  19. 10 6
      backend/open_webui/utils/middleware.py
  20. 41 1
      backend/open_webui/utils/oauth.py
  21. 70 45
      backend/open_webui/utils/tools.py
  22. 65 2
      src/lib/components/admin/Settings/WebSearch.svelte
  23. 1 1
      src/lib/components/channel/Channel.svelte
  24. 5 3
      src/lib/components/chat/Chat.svelte
  25. 1 1
      src/lib/components/chat/ChatControls.svelte
  26. 2 2
      src/lib/components/chat/MessageInput.svelte
  27. 59 87
      src/lib/components/chat/MessageInput/InputMenu.svelte
  28. 1 0
      src/lib/components/chat/Messages/Citations.svelte
  29. 7 4
      src/lib/components/chat/Messages/CitationsModal.svelte
  30. 4 4
      src/lib/components/chat/Messages/ContentRenderer.svelte
  31. 4 16
      src/lib/components/chat/Messages/Markdown.svelte
  32. 6 7
      src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte
  33. 8 7
      src/lib/components/chat/Messages/MultiResponseMessages.svelte
  34. 5 3
      src/lib/components/chat/Messages/UserMessage.svelte
  35. 1 1
      src/lib/components/chat/ModelSelector/Selector.svelte
  36. 11 5
      src/lib/components/chat/Settings/About.svelte
  37. 1 1
      src/lib/components/chat/Settings/Interface.svelte
  38. 3 4
      src/lib/components/common/Drawer.svelte
  39. 4 1
      src/lib/components/common/Textarea.svelte
  40. 36 7
      src/lib/components/workspace/Knowledge/KnowledgeBase.svelte
  41. 5 1
      src/lib/components/workspace/Models/ModelEditor.svelte
  42. 12 3
      src/lib/components/workspace/Prompts/PromptEditor.svelte
  43. 32 32
      src/lib/i18n/locales/ca-ES/translation.json
  44. 2 2
      src/lib/i18n/locales/de-DE/translation.json
  45. 96 96
      src/lib/i18n/locales/es-ES/translation.json
  46. 565 565
      src/lib/i18n/locales/fa-IR/translation.json
  47. 42 42
      src/lib/i18n/locales/fi-FI/translation.json
  48. 131 131
      src/lib/i18n/locales/ie-GA/translation.json
  49. 1 1
      src/lib/i18n/locales/ko-KR/translation.json
  50. 1 1
      src/lib/i18n/locales/lt-LT/translation.json
  51. 32 32
      src/lib/i18n/locales/pl-PL/translation.json
  52. 15 15
      src/lib/i18n/locales/zh-CN/translation.json
  53. 4 4
      src/lib/i18n/locales/zh-TW/translation.json
  54. 64 42
      src/lib/utils/index.ts
  55. 204 74
      src/lib/utils/onedrive-file-picker.ts
  56. 1 0
      src/routes/+layout.svelte

+ 1 - 1
.github/pull_request_template.md

@@ -73,4 +73,4 @@
 
 ### Contributor License Agreement
 
-By submitting this pull request, I confirm that I have read and fully agree to the [CONTRIBUTOR_LICENSE_AGREEMENT](CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.
+By submitting this pull request, I confirm that I have read and fully agree to the [CONTRIBUTOR_LICENSE_AGREEMENT](CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms.

+ 7 - 1
LICENSE

@@ -1,4 +1,4 @@
-Copyright (c) 2023-2025 Timothy Jaeryang Baek
+Copyright (c) 2023-2025 Timothy Jaeryang Baek (Open WebUI)
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
@@ -15,6 +15,12 @@ modification, are permitted provided that the following conditions are met:
    contributors may be used to endorse or promote products derived from
    this software without specific prior written permission.
 
+4. Notwithstanding any other provision of this License, and as a material condition of the rights granted herein, licensees are strictly prohibited from altering, removing, obscuring, or replacing any "Open WebUI" branding, including but not limited to the name, logo, or any visual, textual, or symbolic identifiers that distinguish the software and its interfaces, in any deployment or distribution, regardless of the number of users, except as explicitly set forth in Clauses 5 and 6 below.
+
+5. The branding restriction enumerated in Clause 4 shall not apply in the following limited circumstances: (i) deployments or distributions where the total number of end users (defined as individual natural persons with direct access to the application) does not exceed fifty (50) within any rolling thirty (30) day period; (ii) cases in which the licensee is an official contributor to the codebase—with a substantive code change successfully merged into the main branch of the official codebase maintained by the copyright holder—who has obtained specific prior written permission for branding adjustment from the copyright holder; or (iii) where the licensee has obtained a duly executed enterprise license expressly permitting such modification. For all other cases, any removal or alteration of the "Open WebUI" branding shall constitute a material breach of license.
+
+6. All code, modifications, or derivative works incorporated into this project prior to the incorporation of this branding clause remain licensed under the BSD 3-Clause License, and prior contributors retain all BSD-3 rights therein; if any such contributor requests the removal of their BSD-3-licensed code, the copyright holder will do so, and any replacement code will be licensed under the project's primary license then in effect. By contributing after this clause's adoption, you agree to the project's Contributor License Agreement (CLA) and to these updated terms for all new contributions.
+
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+ 1 - 2
README.md

@@ -7,7 +7,6 @@
 ![GitHub language count](https://img.shields.io/github/languages/count/open-webui/open-webui)
 ![GitHub top language](https://img.shields.io/github/languages/top/open-webui/open-webui)
 ![GitHub last commit](https://img.shields.io/github/last-commit/open-webui/open-webui?color=red)
-![Hits](https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2Follama-webui%2Follama-wbui&count_bg=%2379C83D&title_bg=%23555555&icon=&icon_color=%23E7E7E7&title=hits&edge_flat=false)
 [![Discord](https://img.shields.io/badge/Discord-Open_WebUI-blue?logo=discord&logoColor=white)](https://discord.gg/5rJgQTnV4s)
 [![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86)](https://github.com/sponsors/tjbck)
 
@@ -206,7 +205,7 @@ Discover upcoming features on our roadmap in the [Open WebUI Documentation](http
 
 ## License 📜
 
-This project is licensed under the [BSD-3-Clause License](LICENSE) - see the [LICENSE](LICENSE) file for details. 📄
+This project is licensed under the [Open WebUI License](LICENSE), a revised BSD-3-Clause license. You receive all the same rights as the classic BSD-3 license: you can use, modify, and distribute the software, including in proprietary and commercial products, with minimal restrictions. The only additional requirement is to preserve the "Open WebUI" branding, as detailed in the LICENSE file. For full terms, see the [LICENSE](LICENSE) document. 📄
 
 ## Support 💬
 

+ 1 - 1
backend/open_webui/__init__.py

@@ -76,7 +76,7 @@ def serve(
     from open_webui.env import UVICORN_WORKERS  # Import the workers setting
 
     uvicorn.run(
-        open_webui.main.app,
+        "open_webui.main:app",
         host=host,
         port=port,
         forwarded_allow_ips="*",

+ 42 - 0
backend/open_webui/config.py

@@ -509,6 +509,12 @@ ENABLE_OAUTH_GROUP_MANAGEMENT = PersistentConfig(
     os.environ.get("ENABLE_OAUTH_GROUP_MANAGEMENT", "False").lower() == "true",
 )
 
+ENABLE_OAUTH_GROUP_CREATION = PersistentConfig(
+    "ENABLE_OAUTH_GROUP_CREATION",
+    "oauth.enable_group_creation",
+    os.environ.get("ENABLE_OAUTH_GROUP_CREATION", "False").lower() == "true",
+)
+
 OAUTH_ROLES_CLAIM = PersistentConfig(
     "OAUTH_ROLES_CLAIM",
     "oauth.roles_claim",
@@ -1203,6 +1209,9 @@ ENABLE_USER_WEBHOOKS = PersistentConfig(
     os.environ.get("ENABLE_USER_WEBHOOKS", "True").lower() == "true",
 )
 
+# FastAPI / AnyIO settings
+THREAD_POOL_SIZE = int(os.getenv("THREAD_POOL_SIZE", "0"))
+
 
 def validate_cors_origins(origins):
     for origin in origins:
@@ -1693,6 +1702,9 @@ MILVUS_TOKEN = os.environ.get("MILVUS_TOKEN", None)
 # Qdrant
 QDRANT_URI = os.environ.get("QDRANT_URI", None)
 QDRANT_API_KEY = os.environ.get("QDRANT_API_KEY", None)
+QDRANT_ON_DISK = os.environ.get("QDRANT_ON_DISK", "false").lower() == "true"
+QDRANT_PREFER_GRPC = os.environ.get("QDRANT_PREFER_GRPC", "False").lower() == "true"
+QDRANT_GRPC_PORT = int(os.environ.get("QDRANT_GRPC_PORT", "6334"))
 
 # OpenSearch
 OPENSEARCH_URI = os.environ.get("OPENSEARCH_URI", "https://localhost:9200")
@@ -1760,6 +1772,13 @@ ONEDRIVE_CLIENT_ID = PersistentConfig(
     os.environ.get("ONEDRIVE_CLIENT_ID", ""),
 )
 
+ONEDRIVE_SHAREPOINT_URL = PersistentConfig(
+    "ONEDRIVE_SHAREPOINT_URL",
+    "onedrive.sharepoint_url",
+    os.environ.get("ONEDRIVE_SHAREPOINT_URL", ""),
+)
+
+
 # RAG Content Extraction
 CONTENT_EXTRACTION_ENGINE = PersistentConfig(
     "CONTENT_EXTRACTION_ENGINE",
@@ -2251,6 +2270,29 @@ FIRECRAWL_API_BASE_URL = PersistentConfig(
     os.environ.get("FIRECRAWL_API_BASE_URL", "https://api.firecrawl.dev"),
 )
 
+EXTERNAL_WEB_SEARCH_URL = PersistentConfig(
+    "EXTERNAL_WEB_SEARCH_URL",
+    "rag.web.search.external_web_search_url",
+    os.environ.get("EXTERNAL_WEB_SEARCH_URL", ""),
+)
+
+EXTERNAL_WEB_SEARCH_API_KEY = PersistentConfig(
+    "EXTERNAL_WEB_SEARCH_API_KEY",
+    "rag.web.search.external_web_search_api_key",
+    os.environ.get("EXTERNAL_WEB_SEARCH_API_KEY", ""),
+)
+
+EXTERNAL_WEB_LOADER_URL = PersistentConfig(
+    "EXTERNAL_WEB_LOADER_URL",
+    "rag.web.loader.external_web_loader_url",
+    os.environ.get("EXTERNAL_WEB_LOADER_URL", ""),
+)
+
+EXTERNAL_WEB_LOADER_API_KEY = PersistentConfig(
+    "EXTERNAL_WEB_LOADER_API_KEY",
+    "rag.web.loader.external_web_loader_api_key",
+    os.environ.get("EXTERNAL_WEB_LOADER_API_KEY", ""),
+)
 
 ####################################
 # Images

+ 14 - 0
backend/open_webui/env.py

@@ -354,6 +354,10 @@ BYPASS_MODEL_ACCESS_CONTROL = (
     os.environ.get("BYPASS_MODEL_ACCESS_CONTROL", "False").lower() == "true"
 )
 
+WEBUI_AUTH_SIGNOUT_REDIRECT_URL = os.environ.get(
+    "WEBUI_AUTH_SIGNOUT_REDIRECT_URL", None
+)
+
 ####################################
 # WEBUI_SECRET_KEY
 ####################################
@@ -409,6 +413,11 @@ else:
     except Exception:
         AIOHTTP_CLIENT_TIMEOUT = 300
 
+
+AIOHTTP_CLIENT_SESSION_SSL = (
+    os.environ.get("AIOHTTP_CLIENT_SESSION_SSL", "True").lower() == "true"
+)
+
 AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST = os.environ.get(
     "AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST",
     os.environ.get("AIOHTTP_CLIENT_TIMEOUT_OPENAI_MODEL_LIST", "10"),
@@ -437,6 +446,11 @@ else:
     except Exception:
         AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = 10
 
+
+AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL = (
+    os.environ.get("AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL", "True").lower() == "true"
+)
+
 ####################################
 # OFFLINE_MODE
 ####################################

+ 25 - 2
backend/open_webui/main.py

@@ -17,6 +17,7 @@ from sqlalchemy import text
 from typing import Optional
 from aiocache import cached
 import aiohttp
+import anyio.to_thread
 import requests
 
 
@@ -100,11 +101,14 @@ from open_webui.config import (
     # OpenAI
     ENABLE_OPENAI_API,
     ONEDRIVE_CLIENT_ID,
+    ONEDRIVE_SHAREPOINT_URL,
     OPENAI_API_BASE_URLS,
     OPENAI_API_KEYS,
     OPENAI_API_CONFIGS,
     # Direct Connections
     ENABLE_DIRECT_CONNECTIONS,
+    # Thread pool size for FastAPI/AnyIO
+    THREAD_POOL_SIZE,
     # Tool Server Configs
     TOOL_SERVER_CONNECTIONS,
     # Code Execution
@@ -240,12 +244,17 @@ from open_webui.config import (
     GOOGLE_DRIVE_CLIENT_ID,
     GOOGLE_DRIVE_API_KEY,
     ONEDRIVE_CLIENT_ID,
+    ONEDRIVE_SHAREPOINT_URL,
     ENABLE_RAG_HYBRID_SEARCH,
     ENABLE_RAG_LOCAL_WEB_FETCH,
     ENABLE_WEB_LOADER_SSL_VERIFICATION,
     ENABLE_GOOGLE_DRIVE_INTEGRATION,
     ENABLE_ONEDRIVE_INTEGRATION,
     UPLOAD_DIR,
+    EXTERNAL_WEB_SEARCH_URL,
+    EXTERNAL_WEB_SEARCH_API_KEY,
+    EXTERNAL_WEB_LOADER_URL,
+    EXTERNAL_WEB_LOADER_API_KEY,
     # WebUI
     WEBUI_AUTH,
     WEBUI_NAME,
@@ -341,6 +350,7 @@ from open_webui.env import (
     WEBUI_SESSION_COOKIE_SECURE,
     WEBUI_AUTH_TRUSTED_EMAIL_HEADER,
     WEBUI_AUTH_TRUSTED_NAME_HEADER,
+    WEBUI_AUTH_SIGNOUT_REDIRECT_URL,
     ENABLE_WEBSOCKET_SUPPORT,
     BYPASS_MODEL_ACCESS_CONTROL,
     RESET_CONFIG_ON_START,
@@ -432,6 +442,11 @@ async def lifespan(app: FastAPI):
     if LICENSE_KEY:
         get_license_data(app, LICENSE_KEY)
 
+    pool_size = THREAD_POOL_SIZE
+    if pool_size and pool_size > 0:
+        limiter = anyio.to_thread.current_default_thread_limiter()
+        limiter.total_tokens = pool_size
+
     asyncio.create_task(periodic_usage_pool_cleanup())
     yield
 
@@ -576,6 +591,7 @@ app.state.config.LDAP_CIPHERS = LDAP_CIPHERS
 
 app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
 app.state.AUTH_TRUSTED_NAME_HEADER = WEBUI_AUTH_TRUSTED_NAME_HEADER
+app.state.WEBUI_AUTH_SIGNOUT_REDIRECT_URL = WEBUI_AUTH_SIGNOUT_REDIRECT_URL
 app.state.EXTERNAL_PWA_MANIFEST_URL = EXTERNAL_PWA_MANIFEST_URL
 
 app.state.USER_COUNT = None
@@ -668,6 +684,10 @@ app.state.config.EXA_API_KEY = EXA_API_KEY
 app.state.config.PERPLEXITY_API_KEY = PERPLEXITY_API_KEY
 app.state.config.SOUGOU_API_SID = SOUGOU_API_SID
 app.state.config.SOUGOU_API_SK = SOUGOU_API_SK
+app.state.config.EXTERNAL_WEB_SEARCH_URL = EXTERNAL_WEB_SEARCH_URL
+app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = EXTERNAL_WEB_SEARCH_API_KEY
+app.state.config.EXTERNAL_WEB_LOADER_URL = EXTERNAL_WEB_LOADER_URL
+app.state.config.EXTERNAL_WEB_LOADER_API_KEY = EXTERNAL_WEB_LOADER_API_KEY
 
 
 app.state.config.PLAYWRIGHT_WS_URL = PLAYWRIGHT_WS_URL
@@ -1327,7 +1347,10 @@ async def get_app_config(request: Request):
                     "client_id": GOOGLE_DRIVE_CLIENT_ID.value,
                     "api_key": GOOGLE_DRIVE_API_KEY.value,
                 },
-                "onedrive": {"client_id": ONEDRIVE_CLIENT_ID.value},
+                "onedrive": {
+                    "client_id": ONEDRIVE_CLIENT_ID.value,
+                    "sharepoint_url": ONEDRIVE_SHAREPOINT_URL.value,
+                },
                 "license_metadata": app.state.LICENSE_METADATA,
                 **(
                     {
@@ -1439,7 +1462,7 @@ async def get_manifest_json():
             "start_url": "/",
             "display": "standalone",
             "background_color": "#343541",
-            "orientation": "natural",
+            "orientation": "any",
             "icons": [
                 {
                     "src": "/static/logo.png",

+ 53 - 0
backend/open_webui/retrieval/loaders/external.py

@@ -0,0 +1,53 @@
+import requests
+import logging
+from typing import Iterator, List, Union
+
+from langchain_core.document_loaders import BaseLoader
+from langchain_core.documents import Document
+from open_webui.env import SRC_LOG_LEVELS
+
+log = logging.getLogger(__name__)
+log.setLevel(SRC_LOG_LEVELS["RAG"])
+
+
+class ExternalLoader(BaseLoader):
+    def __init__(
+        self,
+        web_paths: Union[str, List[str]],
+        external_url: str,
+        external_api_key: str,
+        continue_on_failure: bool = True,
+        **kwargs,
+    ) -> None:
+        self.external_url = external_url
+        self.external_api_key = external_api_key
+        self.urls = web_paths if isinstance(web_paths, list) else [web_paths]
+        self.continue_on_failure = continue_on_failure
+
+    def lazy_load(self) -> Iterator[Document]:
+        batch_size = 20
+        for i in range(0, len(self.urls), batch_size):
+            urls = self.urls[i : i + batch_size]
+            try:
+                response = requests.post(
+                    self.external_url,
+                    headers={
+                        "User-Agent": "Open WebUI (https://github.com/open-webui/open-webui) RAG Bot",
+                        "Authorization": f"Bearer {self.external_api_key}",
+                    },
+                    json={
+                        "urls": urls,
+                    },
+                )
+                response.raise_for_status()
+                results = response.json()
+                for result in results:
+                    yield Document(
+                        page_content=result.get("page_content", ""),
+                        metadata=result.get("metadata", {}),
+                    )
+            except Exception as e:
+                if self.continue_on_failure:
+                    log.error(f"Error extracting content from batch {urls}: {e}")
+                else:
+                    raise e

+ 34 - 7
backend/open_webui/retrieval/vector/dbs/qdrant.py

@@ -1,12 +1,19 @@
 from typing import Optional
 import logging
+from urllib.parse import urlparse
 
 from qdrant_client import QdrantClient as Qclient
 from qdrant_client.http.models import PointStruct
 from qdrant_client.models import models
 
 from open_webui.retrieval.vector.main import VectorItem, SearchResult, GetResult
-from open_webui.config import QDRANT_URI, QDRANT_API_KEY
+from open_webui.config import (
+    QDRANT_URI,
+    QDRANT_API_KEY,
+    QDRANT_ON_DISK,
+    QDRANT_GRPC_PORT,
+    QDRANT_PREFER_GRPC,
+)
 from open_webui.env import SRC_LOG_LEVELS
 
 NO_LIMIT = 999999999
@@ -20,11 +27,29 @@ class QdrantClient:
         self.collection_prefix = "open-webui"
         self.QDRANT_URI = QDRANT_URI
         self.QDRANT_API_KEY = QDRANT_API_KEY
-        self.client = (
-            Qclient(url=self.QDRANT_URI, api_key=self.QDRANT_API_KEY)
-            if self.QDRANT_URI
-            else None
-        )
+        self.QDRANT_ON_DISK = QDRANT_ON_DISK
+        self.PREFER_GRPC = QDRANT_PREFER_GRPC
+        self.GRPC_PORT = QDRANT_GRPC_PORT
+
+        if not self.QDRANT_URI:
+            self.client = None
+            return
+
+        # Unified handling for either scheme
+        parsed = urlparse(self.QDRANT_URI)
+        host = parsed.hostname or self.QDRANT_URI
+        http_port = parsed.port or 6333  # default REST port
+
+        if self.PREFER_GRPC:
+            self.client = Qclient(
+                host=host,
+                port=http_port,
+                grpc_port=self.GRPC_PORT,
+                prefer_grpc=self.PREFER_GRPC,
+                api_key=self.QDRANT_API_KEY,
+            )
+        else:
+            self.client = Qclient(url=self.QDRANT_URI, api_key=self.QDRANT_API_KEY)
 
     def _result_to_get_result(self, points) -> GetResult:
         ids = []
@@ -50,7 +75,9 @@ class QdrantClient:
         self.client.create_collection(
             collection_name=collection_name_with_prefix,
             vectors_config=models.VectorParams(
-                size=dimension, distance=models.Distance.COSINE
+                size=dimension,
+                distance=models.Distance.COSINE,
+                on_disk=self.QDRANT_ON_DISK,
             ),
         )
 

+ 47 - 0
backend/open_webui/retrieval/web/external.py

@@ -0,0 +1,47 @@
+import logging
+from typing import Optional, List
+
+import requests
+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 search_external(
+    external_url: str,
+    external_api_key: str,
+    query: str,
+    count: int,
+    filter_list: Optional[List[str]] = None,
+) -> List[SearchResult]:
+    try:
+        response = requests.post(
+            external_url,
+            headers={
+                "User-Agent": "Open WebUI (https://github.com/open-webui/open-webui) RAG Bot",
+                "Authorization": f"Bearer {external_api_key}",
+            },
+            json={
+                "query": query,
+                "count": count,
+            },
+        )
+        response.raise_for_status()
+        results = response.json()
+        if filter_list:
+            results = get_filtered_results(results, filter_list)
+        results = [
+            SearchResult(
+                link=result.get("link"),
+                title=result.get("title"),
+                snippet=result.get("snippet"),
+            )
+            for result in results[:count]
+        ]
+        log.info(f"External search results: {results}")
+        return results
+    except Exception as e:
+        log.error(f"Error in External search: {e}")
+        return []

+ 8 - 0
backend/open_webui/retrieval/web/utils.py

@@ -25,6 +25,7 @@ from langchain_community.document_loaders.firecrawl import FireCrawlLoader
 from langchain_community.document_loaders.base import BaseLoader
 from langchain_core.documents import Document
 from open_webui.retrieval.loaders.tavily import TavilyLoader
+from open_webui.retrieval.loaders.external import ExternalLoader
 from open_webui.constants import ERROR_MESSAGES
 from open_webui.config import (
     ENABLE_RAG_LOCAL_WEB_FETCH,
@@ -35,6 +36,8 @@ from open_webui.config import (
     FIRECRAWL_API_KEY,
     TAVILY_API_KEY,
     TAVILY_EXTRACT_DEPTH,
+    EXTERNAL_WEB_LOADER_URL,
+    EXTERNAL_WEB_LOADER_API_KEY,
 )
 from open_webui.env import SRC_LOG_LEVELS
 
@@ -619,6 +622,11 @@ def get_web_loader(
         web_loader_args["api_key"] = TAVILY_API_KEY.value
         web_loader_args["extract_depth"] = TAVILY_EXTRACT_DEPTH.value
 
+    if WEB_LOADER_ENGINE.value == "external":
+        WebLoaderClass = ExternalLoader
+        web_loader_args["external_url"] = EXTERNAL_WEB_LOADER_URL.value
+        web_loader_args["external_api_key"] = EXTERNAL_WEB_LOADER_API_KEY.value
+
     if WebLoaderClass:
         web_loader = WebLoaderClass(**web_loader_args)
 

+ 7 - 0
backend/open_webui/routers/auths.py

@@ -27,6 +27,7 @@ from open_webui.env import (
     WEBUI_AUTH_TRUSTED_NAME_HEADER,
     WEBUI_AUTH_COOKIE_SAME_SITE,
     WEBUI_AUTH_COOKIE_SECURE,
+    WEBUI_AUTH_SIGNOUT_REDIRECT_URL,
     SRC_LOG_LEVELS,
 )
 from fastapi import APIRouter, Depends, HTTPException, Request, status
@@ -566,6 +567,12 @@ async def signout(request: Request, response: Response):
                     detail="Failed to sign out from the OpenID provider.",
                 )
 
+    if WEBUI_AUTH_SIGNOUT_REDIRECT_URL:
+        return RedirectResponse(
+            headers=response.headers,
+            url=WEBUI_AUTH_SIGNOUT_REDIRECT_URL,
+        )
+
     return {"status": True}
 
 

+ 4 - 2
backend/open_webui/routers/files.py

@@ -173,7 +173,8 @@ async def list_files(user=Depends(get_verified_user), content: bool = Query(True
 
     if not content:
         for file in files:
-            del file.data["content"]
+            if "content" in file.data:
+                del file.data["content"]
 
     return files
 
@@ -214,7 +215,8 @@ async def search_files(
 
     if not content:
         for file in matching_files:
-            del file.data["content"]
+            if "content" in file.data:
+                del file.data["content"]
 
     return matching_files
 

+ 9 - 8
backend/open_webui/routers/knowledge.py

@@ -9,7 +9,7 @@ from open_webui.models.knowledge import (
     KnowledgeResponse,
     KnowledgeUserResponse,
 )
-from open_webui.models.files import Files, FileModel
+from open_webui.models.files import Files, FileModel, FileMetadataResponse
 from open_webui.retrieval.vector.connector import VECTOR_DB_CLIENT
 from open_webui.routers.retrieval import (
     process_file,
@@ -235,7 +235,7 @@ async def reindex_knowledge_files(request: Request, user=Depends(get_verified_us
 
 
 class KnowledgeFilesResponse(KnowledgeResponse):
-    files: list[FileModel]
+    files: list[FileMetadataResponse]
 
 
 @router.get("/{id}", response_model=Optional[KnowledgeFilesResponse])
@@ -251,7 +251,7 @@ async def get_knowledge_by_id(id: str, user=Depends(get_verified_user)):
         ):
 
             file_ids = knowledge.data.get("file_ids", []) if knowledge.data else []
-            files = Files.get_files_by_ids(file_ids)
+            files = Files.get_file_metadatas_by_ids(file_ids)
 
             return KnowledgeFilesResponse(
                 **knowledge.model_dump(),
@@ -379,7 +379,7 @@ def add_file_to_knowledge_by_id(
             knowledge = Knowledges.update_knowledge_data_by_id(id=id, data=data)
 
             if knowledge:
-                files = Files.get_files_by_ids(file_ids)
+                files = Files.get_file_metadatas_by_ids(file_ids)
 
                 return KnowledgeFilesResponse(
                     **knowledge.model_dump(),
@@ -456,7 +456,7 @@ def update_file_from_knowledge_by_id(
         data = knowledge.data or {}
         file_ids = data.get("file_ids", [])
 
-        files = Files.get_files_by_ids(file_ids)
+        files = Files.get_file_metadatas_by_ids(file_ids)
 
         return KnowledgeFilesResponse(
             **knowledge.model_dump(),
@@ -538,7 +538,7 @@ def remove_file_from_knowledge_by_id(
             knowledge = Knowledges.update_knowledge_data_by_id(id=id, data=data)
 
             if knowledge:
-                files = Files.get_files_by_ids(file_ids)
+                files = Files.get_file_metadatas_by_ids(file_ids)
 
                 return KnowledgeFilesResponse(
                     **knowledge.model_dump(),
@@ -734,7 +734,7 @@ def add_files_to_knowledge_batch(
         error_details = [f"{err.file_id}: {err.error}" for err in result.errors]
         return KnowledgeFilesResponse(
             **knowledge.model_dump(),
-            files=Files.get_files_by_ids(existing_file_ids),
+            files=Files.get_file_metadatas_by_ids(existing_file_ids),
             warnings={
                 "message": "Some files failed to process",
                 "errors": error_details,
@@ -742,5 +742,6 @@ def add_files_to_knowledge_batch(
         )
 
     return KnowledgeFilesResponse(
-        **knowledge.model_dump(), files=Files.get_files_by_ids(existing_file_ids)
+        **knowledge.model_dump(),
+        files=Files.get_file_metadatas_by_ids(existing_file_ids),
     )

+ 7 - 1
backend/open_webui/routers/ollama.py

@@ -54,6 +54,7 @@ from open_webui.config import (
 from open_webui.env import (
     ENV,
     SRC_LOG_LEVELS,
+    AIOHTTP_CLIENT_SESSION_SSL,
     AIOHTTP_CLIENT_TIMEOUT,
     AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST,
     BYPASS_MODEL_ACCESS_CONTROL,
@@ -91,6 +92,7 @@ async def send_get_request(url, key=None, user: UserModel = None):
                         else {}
                     ),
                 },
+                ssl=AIOHTTP_CLIENT_SESSION_SSL,
             ) as response:
                 return await response.json()
     except Exception as e:
@@ -141,6 +143,7 @@ async def send_post_request(
                     else {}
                 ),
             },
+            ssl=AIOHTTP_CLIENT_SESSION_SSL,
         )
         r.raise_for_status()
 
@@ -234,6 +237,7 @@ async def verify_connection(
                         else {}
                     ),
                 },
+                ssl=AIOHTTP_CLIENT_SESSION_SSL,
             ) as r:
                 if r.status != 200:
                     detail = f"HTTP Error: {r.status}"
@@ -1482,7 +1486,9 @@ async def download_file_stream(
     timeout = aiohttp.ClientTimeout(total=600)  # Set the timeout
 
     async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
-        async with session.get(file_url, headers=headers) as response:
+        async with session.get(
+            file_url, headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL
+        ) as response:
             total_size = int(response.headers.get("content-length", 0)) + current_size
 
             with open(file_path, "ab+") as file:

+ 6 - 0
backend/open_webui/routers/openai.py

@@ -21,6 +21,7 @@ from open_webui.config import (
     CACHE_DIR,
 )
 from open_webui.env import (
+    AIOHTTP_CLIENT_SESSION_SSL,
     AIOHTTP_CLIENT_TIMEOUT,
     AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST,
     ENABLE_FORWARD_USER_INFO_HEADERS,
@@ -74,6 +75,7 @@ async def send_get_request(url, key=None, user: UserModel = None):
                         else {}
                     ),
                 },
+                ssl=AIOHTTP_CLIENT_SESSION_SSL,
             ) as response:
                 return await response.json()
     except Exception as e:
@@ -481,6 +483,7 @@ async def get_models(
                             else {}
                         ),
                     },
+                    ssl=AIOHTTP_CLIENT_SESSION_SSL,
                 ) as r:
                     if r.status != 200:
                         # Extract response error details if available
@@ -561,6 +564,7 @@ async def verify_connection(
                         else {}
                     ),
                 },
+                ssl=AIOHTTP_CLIENT_SESSION_SSL,
             ) as r:
                 if r.status != 200:
                     # Extract response error details if available
@@ -723,6 +727,7 @@ async def generate_chat_completion(
                     else {}
                 ),
             },
+            ssl=AIOHTTP_CLIENT_SESSION_SSL,
         )
 
         # Check if response is SSE
@@ -802,6 +807,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)):
                     else {}
                 ),
             },
+            ssl=AIOHTTP_CLIENT_SESSION_SSL,
         )
         r.raise_for_status()
 

+ 38 - 2
backend/open_webui/routers/retrieval.py

@@ -61,6 +61,7 @@ from open_webui.retrieval.web.bing import search_bing
 from open_webui.retrieval.web.exa import search_exa
 from open_webui.retrieval.web.perplexity import search_perplexity
 from open_webui.retrieval.web.sougou import search_sougou
+from open_webui.retrieval.web.external import search_external
 
 from open_webui.retrieval.utils import (
     get_embedding_function,
@@ -418,6 +419,10 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
             "FIRECRAWL_API_KEY": request.app.state.config.FIRECRAWL_API_KEY,
             "FIRECRAWL_API_BASE_URL": request.app.state.config.FIRECRAWL_API_BASE_URL,
             "TAVILY_EXTRACT_DEPTH": request.app.state.config.TAVILY_EXTRACT_DEPTH,
+            "EXTERNAL_WEB_SEARCH_URL": request.app.state.config.EXTERNAL_WEB_SEARCH_URL,
+            "EXTERNAL_WEB_SEARCH_API_KEY": request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY,
+            "EXTERNAL_WEB_LOADER_URL": request.app.state.config.EXTERNAL_WEB_LOADER_URL,
+            "EXTERNAL_WEB_LOADER_API_KEY": request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY,
             "YOUTUBE_LOADER_LANGUAGE": request.app.state.config.YOUTUBE_LOADER_LANGUAGE,
             "YOUTUBE_LOADER_PROXY_URL": request.app.state.config.YOUTUBE_LOADER_PROXY_URL,
             "YOUTUBE_LOADER_TRANSLATION": request.app.state.YOUTUBE_LOADER_TRANSLATION,
@@ -463,6 +468,10 @@ class WebConfig(BaseModel):
     FIRECRAWL_API_KEY: Optional[str] = None
     FIRECRAWL_API_BASE_URL: Optional[str] = None
     TAVILY_EXTRACT_DEPTH: Optional[str] = None
+    EXTERNAL_WEB_SEARCH_URL: Optional[str] = None
+    EXTERNAL_WEB_SEARCH_API_KEY: Optional[str] = None
+    EXTERNAL_WEB_LOADER_URL: Optional[str] = None
+    EXTERNAL_WEB_LOADER_API_KEY: Optional[str] = None
     YOUTUBE_LOADER_LANGUAGE: Optional[List[str]] = None
     YOUTUBE_LOADER_PROXY_URL: Optional[str] = None
     YOUTUBE_LOADER_TRANSLATION: Optional[str] = None
@@ -697,6 +706,18 @@ async def update_rag_config(
         request.app.state.config.FIRECRAWL_API_BASE_URL = (
             form_data.web.FIRECRAWL_API_BASE_URL
         )
+        request.app.state.config.EXTERNAL_WEB_SEARCH_URL = (
+            form_data.web.EXTERNAL_WEB_SEARCH_URL
+        )
+        request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = (
+            form_data.web.EXTERNAL_WEB_SEARCH_API_KEY
+        )
+        request.app.state.config.EXTERNAL_WEB_LOADER_URL = (
+            form_data.web.EXTERNAL_WEB_LOADER_URL
+        )
+        request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY = (
+            form_data.web.EXTERNAL_WEB_LOADER_API_KEY
+        )
         request.app.state.config.TAVILY_EXTRACT_DEPTH = (
             form_data.web.TAVILY_EXTRACT_DEPTH
         )
@@ -778,6 +799,10 @@ async def update_rag_config(
             "FIRECRAWL_API_KEY": request.app.state.config.FIRECRAWL_API_KEY,
             "FIRECRAWL_API_BASE_URL": request.app.state.config.FIRECRAWL_API_BASE_URL,
             "TAVILY_EXTRACT_DEPTH": request.app.state.config.TAVILY_EXTRACT_DEPTH,
+            "EXTERNAL_WEB_SEARCH_URL": request.app.state.config.EXTERNAL_WEB_SEARCH_URL,
+            "EXTERNAL_WEB_SEARCH_API_KEY": request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY,
+            "EXTERNAL_WEB_LOADER_URL": request.app.state.config.EXTERNAL_WEB_LOADER_URL,
+            "EXTERNAL_WEB_LOADER_API_KEY": request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY,
             "YOUTUBE_LOADER_LANGUAGE": request.app.state.config.YOUTUBE_LOADER_LANGUAGE,
             "YOUTUBE_LOADER_PROXY_URL": request.app.state.config.YOUTUBE_LOADER_PROXY_URL,
             "YOUTUBE_LOADER_TRANSLATION": request.app.state.YOUTUBE_LOADER_TRANSLATION,
@@ -1465,6 +1490,14 @@ def search_web(request: Request, engine: str, query: str) -> list[SearchResult]:
             raise Exception(
                 "No SOUGOU_API_SID or SOUGOU_API_SK found in environment variables"
             )
+    elif engine == "external":
+        return search_external(
+            request.app.state.config.EXTERNAL_WEB_SEARCH_URL,
+            request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY,
+            query,
+            request.app.state.config.WEB_SEARCH_RESULT_COUNT,
+            request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST,
+        )
     else:
         raise Exception("No search engine API key found in environment variables")
 
@@ -1477,8 +1510,11 @@ async def process_web_search(
         logging.info(
             f"trying to web search with {request.app.state.config.WEB_SEARCH_ENGINE, form_data.query}"
         )
-        web_results = search_web(
-            request, request.app.state.config.WEB_SEARCH_ENGINE, form_data.query
+        web_results = await run_in_threadpool(
+            search_web,
+            request,
+            request.app.state.config.WEB_SEARCH_ENGINE,
+            form_data.query,
         )
     except Exception as e:
         log.exception(e)

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

@@ -288,6 +288,21 @@ async def update_user_by_id(
     form_data: UserUpdateForm,
     session_user=Depends(get_admin_user),
 ):
+    # Prevent modification of the primary admin user by other admins
+    try:
+        first_user = Users.get_first_user()
+        if first_user and user_id == first_user.id and session_user.id != user_id:
+            raise HTTPException(
+                status_code=status.HTTP_403_FORBIDDEN,
+                detail=ERROR_MESSAGES.ACTION_PROHIBITED,
+            )
+    except Exception as e:
+        log.error(f"Error checking primary admin status: {e}")
+        raise HTTPException(
+            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+            detail="Could not verify primary admin status.",
+        )
+
     user = Users.get_user_by_id(user_id)
 
     if user:
@@ -335,6 +350,21 @@ async def update_user_by_id(
 
 @router.delete("/{user_id}", response_model=bool)
 async def delete_user_by_id(user_id: str, user=Depends(get_admin_user)):
+    # Prevent deletion of the primary admin user
+    try:
+        first_user = Users.get_first_user()
+        if first_user and user_id == first_user.id:
+            raise HTTPException(
+                status_code=status.HTTP_403_FORBIDDEN,
+                detail=ERROR_MESSAGES.ACTION_PROHIBITED,
+            )
+    except Exception as e:
+        log.error(f"Error checking primary admin status: {e}")
+        raise HTTPException(
+            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
+            detail="Could not verify primary admin status.",
+        )
+
     if user.id != user_id:
         result = Auths.delete_auth_by_id(user_id)
 
@@ -346,6 +376,7 @@ async def delete_user_by_id(user_id: str, user=Depends(get_admin_user)):
             detail=ERROR_MESSAGES.DELETE_USER_ERROR,
         )
 
+    # Prevent self-deletion
     raise HTTPException(
         status_code=status.HTTP_403_FORBIDDEN,
         detail=ERROR_MESSAGES.ACTION_PROHIBITED,

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

@@ -888,16 +888,20 @@ async def process_chat_payload(request, form_data, user, metadata, model):
     # If context is not empty, insert it into the messages
     if len(sources) > 0:
         context_string = ""
-        citated_file_idx = {}
-        for _, source in enumerate(sources, 1):
+        citation_idx = {}
+        for source in sources:
             if "document" in source:
                 for doc_context, doc_meta in zip(
                     source["document"], source["metadata"]
                 ):
-                    file_id = doc_meta.get("file_id")
-                    if file_id not in citated_file_idx:
-                        citated_file_idx[file_id] = len(citated_file_idx) + 1
-                    context_string += f'<source id="{citated_file_idx[file_id]}">{doc_context}</source>\n'
+                    citation_id = (
+                        doc_meta.get("source", None)
+                        or source.get("source", {}).get("id", None)
+                        or "N/A"
+                    )
+                    if citation_id not in citation_idx:
+                        citation_idx[citation_id] = len(citation_idx) + 1
+                    context_string += f'<source id="{citation_idx[citation_id]}">{doc_context}</source>\n'
 
         context_string = context_string.strip()
         prompt = get_last_user_message(form_data["messages"])

+ 41 - 1
backend/open_webui/utils/oauth.py

@@ -15,7 +15,7 @@ from starlette.responses import RedirectResponse
 
 from open_webui.models.auths import Auths
 from open_webui.models.users import Users
-from open_webui.models.groups import Groups, GroupModel, GroupUpdateForm
+from open_webui.models.groups import Groups, GroupModel, GroupUpdateForm, GroupForm
 from open_webui.config import (
     DEFAULT_USER_ROLE,
     ENABLE_OAUTH_SIGNUP,
@@ -23,6 +23,7 @@ from open_webui.config import (
     OAUTH_PROVIDERS,
     ENABLE_OAUTH_ROLE_MANAGEMENT,
     ENABLE_OAUTH_GROUP_MANAGEMENT,
+    ENABLE_OAUTH_GROUP_CREATION,
     OAUTH_ROLES_CLAIM,
     OAUTH_GROUPS_CLAIM,
     OAUTH_EMAIL_CLAIM,
@@ -57,6 +58,7 @@ auth_manager_config.ENABLE_OAUTH_SIGNUP = ENABLE_OAUTH_SIGNUP
 auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL = OAUTH_MERGE_ACCOUNTS_BY_EMAIL
 auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT
 auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT = ENABLE_OAUTH_GROUP_MANAGEMENT
+auth_manager_config.ENABLE_OAUTH_GROUP_CREATION = ENABLE_OAUTH_GROUP_CREATION
 auth_manager_config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM
 auth_manager_config.OAUTH_GROUPS_CLAIM = OAUTH_GROUPS_CLAIM
 auth_manager_config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM
@@ -152,6 +154,44 @@ class OAuthManager:
         user_current_groups: list[GroupModel] = Groups.get_groups_by_member_id(user.id)
         all_available_groups: list[GroupModel] = Groups.get_groups()
 
+        # Create groups if they don't exist and creation is enabled
+        if auth_manager_config.ENABLE_OAUTH_GROUP_CREATION:
+            log.debug("Checking for missing groups to create...")
+            all_group_names = {g.name for g in all_available_groups}
+            groups_created = False
+            # Determine creator ID: Prefer admin, fallback to current user if no admin exists
+            admin_user = Users.get_admin_user()
+            creator_id = admin_user.id if admin_user else user.id
+            log.debug(f"Using creator ID {creator_id} for potential group creation.")
+
+            for group_name in user_oauth_groups:
+                if group_name not in all_group_names:
+                    log.info(f"Group '{group_name}' not found via OAuth claim. Creating group...")
+                    try:
+                        new_group_form = GroupForm(
+                            name=group_name,
+                            description=f"Group '{group_name}' created automatically via OAuth.",
+                            permissions=default_permissions, # Use default permissions from function args
+                            user_ids=[], # Start with no users, user will be added later by subsequent logic
+                        )
+                        # Use determined creator ID (admin or fallback to current user)
+                        created_group = Groups.insert_new_group(creator_id, new_group_form)
+                        if created_group:
+                            log.info(f"Successfully created group '{group_name}' with ID {created_group.id} using creator ID {creator_id}")
+                            groups_created = True
+                            # Add to local set to prevent duplicate creation attempts in this run
+                            all_group_names.add(group_name)
+                        else:
+                             log.error(f"Failed to create group '{group_name}' via OAuth.")
+                    except Exception as e:
+                        log.error(f"Error creating group '{group_name}' via OAuth: {e}")
+
+            # Refresh the list of all available groups if any were created
+            if groups_created:
+                all_available_groups = Groups.get_groups()
+                log.debug("Refreshed list of all available groups after creation.")
+
+
         log.debug(f"Oauth Groups claim: {oauth_claim}")
         log.debug(f"User oauth groups: {user_oauth_groups}")
         log.debug(f"User's current groups: {[g.name for g in user_current_groups]}")

+ 70 - 45
backend/open_webui/utils/tools.py

@@ -36,7 +36,10 @@ from langchain_core.utils.function_calling import (
 from open_webui.models.tools import Tools
 from open_webui.models.users import UserModel
 from open_webui.utils.plugin import load_tool_module_by_id
-from open_webui.env import AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA
+from open_webui.env import (
+    AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA,
+    AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL,
+)
 
 import copy
 
@@ -371,51 +374,64 @@ def convert_openapi_to_tool_payload(openapi_spec):
 
     for path, methods in openapi_spec.get("paths", {}).items():
         for method, operation in methods.items():
-            tool = {
-                "type": "function",
-                "name": operation.get("operationId"),
-                "description": operation.get(
-                    "description", operation.get("summary", "No description available.")
-                ),
-                "parameters": {"type": "object", "properties": {}, "required": []},
-            }
-
-            # Extract path and query parameters
-            for param in operation.get("parameters", []):
-                param_name = param["name"]
-                param_schema = param.get("schema", {})
-                tool["parameters"]["properties"][param_name] = {
-                    "type": param_schema.get("type"),
-                    "description": param_schema.get("description", ""),
+            if operation.get("operationId"):
+                tool = {
+                    "type": "function",
+                    "name": operation.get("operationId"),
+                    "description": operation.get(
+                        "description",
+                        operation.get("summary", "No description available."),
+                    ),
+                    "parameters": {"type": "object", "properties": {}, "required": []},
                 }
-                if param.get("required"):
-                    tool["parameters"]["required"].append(param_name)
-
-            # Extract and resolve requestBody if available
-            request_body = operation.get("requestBody")
-            if request_body:
-                content = request_body.get("content", {})
-                json_schema = content.get("application/json", {}).get("schema")
-                if json_schema:
-                    resolved_schema = resolve_schema(
-                        json_schema, openapi_spec.get("components", {})
-                    )
 
-                    if resolved_schema.get("properties"):
-                        tool["parameters"]["properties"].update(
-                            resolved_schema["properties"]
+                # Extract path and query parameters
+                for param in operation.get("parameters", []):
+                    param_name = param["name"]
+                    param_schema = param.get("schema", {})
+                    description = param_schema.get("description", "")
+                    if not description:
+                        description = param.get("description") or ""
+                    if param_schema.get("enum") and isinstance(
+                        param_schema.get("enum"), list
+                    ):
+                        description += (
+                            f". Possible values: {', '.join(param_schema.get('enum'))}"
+                        )
+                    tool["parameters"]["properties"][param_name] = {
+                        "type": param_schema.get("type"),
+                        "description": description,
+                    }
+                    if param.get("required"):
+                        tool["parameters"]["required"].append(param_name)
+
+                # Extract and resolve requestBody if available
+                request_body = operation.get("requestBody")
+                if request_body:
+                    content = request_body.get("content", {})
+                    json_schema = content.get("application/json", {}).get("schema")
+                    if json_schema:
+                        resolved_schema = resolve_schema(
+                            json_schema, openapi_spec.get("components", {})
                         )
-                        if "required" in resolved_schema:
-                            tool["parameters"]["required"] = list(
-                                set(
-                                    tool["parameters"]["required"]
-                                    + resolved_schema["required"]
+
+                        if resolved_schema.get("properties"):
+                            tool["parameters"]["properties"].update(
+                                resolved_schema["properties"]
+                            )
+                            if "required" in resolved_schema:
+                                tool["parameters"]["required"] = list(
+                                    set(
+                                        tool["parameters"]["required"]
+                                        + resolved_schema["required"]
+                                    )
                                 )
+                        elif resolved_schema.get("type") == "array":
+                            tool["parameters"] = (
+                                resolved_schema  # special case for array
                             )
-                    elif resolved_schema.get("type") == "array":
-                        tool["parameters"] = resolved_schema  # special case for array
 
-            tool_payload.append(tool)
+                tool_payload.append(tool)
 
     return tool_payload
 
@@ -431,8 +447,10 @@ async def get_tool_server_data(token: str, url: str) -> Dict[str, Any]:
     error = None
     try:
         timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA)
-        async with aiohttp.ClientSession(timeout=timeout) as session:
-            async with session.get(url, headers=headers) as response:
+        async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session:
+            async with session.get(
+                url, headers=headers, ssl=AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL
+            ) as response:
                 if response.status != 200:
                     error_body = await response.json()
                     raise Exception(error_body)
@@ -573,19 +591,26 @@ async def execute_tool_server(
         if token:
             headers["Authorization"] = f"Bearer {token}"
 
-        async with aiohttp.ClientSession() as session:
+        async with aiohttp.ClientSession(trust_env=True) as session:
             request_method = getattr(session, http_method.lower())
 
             if http_method in ["post", "put", "patch"]:
                 async with request_method(
-                    final_url, json=body_params, headers=headers
+                    final_url,
+                    json=body_params,
+                    headers=headers,
+                    ssl=AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL,
                 ) as response:
                     if response.status >= 400:
                         text = await response.text()
                         raise Exception(f"HTTP error {response.status}: {text}")
                     return await response.json()
             else:
-                async with request_method(final_url, headers=headers) as response:
+                async with request_method(
+                    final_url,
+                    headers=headers,
+                    ssl=AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL,
+                ) as response:
                     if response.status >= 400:
                         text = await response.text()
                         raise Exception(f"HTTP error {response.status}: {text}")

+ 65 - 2
src/lib/components/admin/Settings/WebSearch.svelte

@@ -30,9 +30,10 @@
 		'bing',
 		'exa',
 		'perplexity',
-		'sougou'
+		'sougou',
+		'external'
 	];
-	let webLoaderEngines = ['playwright', 'firecrawl', 'tavily'];
+	let webLoaderEngines = ['playwright', 'firecrawl', 'tavily', 'external'];
 
 	let webConfig = null;
 
@@ -431,6 +432,37 @@
 									/>
 								</div>
 							</div>
+						{:else if webConfig.WEB_SEARCH_ENGINE === 'external'}
+							<div class="mb-2.5 flex w-full flex-col">
+								<div>
+									<div class=" self-center text-xs font-medium mb-1">
+										{$i18n.t('External Web Search URL')}
+									</div>
+
+									<div class="flex w-full">
+										<div class="flex-1">
+											<input
+												class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
+												type="text"
+												placeholder={$i18n.t('Enter External Web Search URL')}
+												bind:value={webConfig.EXTERNAL_WEB_SEARCH_URL}
+												autocomplete="off"
+											/>
+										</div>
+									</div>
+								</div>
+
+								<div class="mt-2">
+									<div class=" self-center text-xs font-medium mb-1">
+										{$i18n.t('External Web Search API Key')}
+									</div>
+
+									<SensitiveInput
+										placeholder={$i18n.t('Enter External Web Search API Key')}
+										bind:value={webConfig.EXTERNAL_WEB_SEARCH_API_KEY}
+									/>
+								</div>
+							</div>
 						{/if}
 					{/if}
 
@@ -652,6 +684,37 @@
 								</div>
 							{/if}
 						</div>
+					{:else if webConfig.WEB_LOADER_ENGINE === 'external'}
+						<div class="mb-2.5 flex w-full flex-col">
+							<div>
+								<div class=" self-center text-xs font-medium mb-1">
+									{$i18n.t('External Web Loader URL')}
+								</div>
+
+								<div class="flex w-full">
+									<div class="flex-1">
+										<input
+											class="w-full rounded-lg py-2 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
+											type="text"
+											placeholder={$i18n.t('Enter External Web Loader URL')}
+											bind:value={webConfig.EXTERNAL_WEB_LOADER_URL}
+											autocomplete="off"
+										/>
+									</div>
+								</div>
+							</div>
+
+							<div class="mt-2">
+								<div class=" self-center text-xs font-medium mb-1">
+									{$i18n.t('External Web Loader API Key')}
+								</div>
+
+								<SensitiveInput
+									placeholder={$i18n.t('Enter External Web Loader API Key')}
+									bind:value={webConfig.EXTERNAL_WEB_LOADER_API_KEY}
+								/>
+							</div>
+						</div>
 					{/if}
 
 					<div class="  mb-2.5 flex w-full justify-between">

+ 1 - 1
src/lib/components/channel/Channel.svelte

@@ -262,7 +262,7 @@
 			{#if threadId !== null}
 				<Drawer
 					show={threadId !== null}
-					on:close={() => {
+					onClose={() => {
 						threadId = null;
 					}}
 				>

+ 5 - 3
src/lib/components/chat/Chat.svelte

@@ -236,9 +236,11 @@
 		await tick();
 		await tick();
 
-		const messageElement = document.getElementById(`message-${message.id}`);
-		if (messageElement) {
-			messageElement.scrollIntoView({ behavior: 'smooth' });
+		if ($settings?.scrollOnBranchChange ?? true) {
+			const messageElement = document.getElementById(`message-${message.id}`);
+			if (messageElement) {
+				messageElement.scrollIntoView({ behavior: 'smooth' });
+			}
 		}
 
 		await tick();

+ 1 - 1
src/lib/components/chat/ChatControls.svelte

@@ -140,7 +140,7 @@
 		{#if $showControls}
 			<Drawer
 				show={$showControls}
-				on:close={() => {
+				onClose={() => {
 					showControls.set(false);
 				}}
 			>

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

@@ -1063,9 +1063,9 @@
 													);
 												}
 											}}
-											uploadOneDriveHandler={async () => {
+											uploadOneDriveHandler={async (authorityType) => {
 												try {
-													const fileData = await pickAndDownloadFile();
+													const fileData = await pickAndDownloadFile(authorityType);
 													if (fileData) {
 														const file = new File([fileData.blob], fileData.name, {
 															type: fileData.blob.type || 'application/octet-stream'

+ 59 - 87
src/lib/components/chat/MessageInput/InputMenu.svelte

@@ -229,94 +229,66 @@
 			{/if}
 
 			{#if $config?.features?.enable_onedrive_integration}
-				<DropdownMenu.Item
-					class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
-					on:click={() => {
-						uploadOneDriveHandler();
-					}}
-				>
-					<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="w-5 h-5" fill="none">
-						<mask
-							id="mask0_87_7796"
-							style="mask-type:alpha"
-							maskUnits="userSpaceOnUse"
-							x="0"
-							y="6"
-							width="32"
-							height="20"
+				<DropdownMenu.Sub>
+					<DropdownMenu.SubTrigger class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl w-full">
+						<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" class="w-5 h-5" fill="none">
+							<mask id="mask0_87_7796" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="6" width="32" height="20">
+								<path d="M7.82979 26C3.50549 26 0 22.5675 0 18.3333C0 14.1921 3.35322 10.8179 7.54613 10.6716C9.27535 7.87166 12.4144 6 16 6C20.6308 6 24.5169 9.12183 25.5829 13.3335C29.1316 13.3603 32 16.1855 32 19.6667C32 23.0527 29 26 25.8723 25.9914L7.82979 26Z" fill="#C4C4C4"/>
+							</mask>
+							<g mask="url(#mask0_87_7796)">
+								<path d="M7.83017 26.0001C5.37824 26.0001 3.18957 24.8966 1.75391 23.1691L18.0429 16.3335L30.7089 23.4647C29.5926 24.9211 27.9066 26.0001 26.0004 25.9915C23.1254 26.0001 12.0629 26.0001 7.83017 26.0001Z" fill="url(#paint0_linear_87_7796)"/>
+								<path d="M25.5785 13.3149L18.043 16.3334L30.709 23.4647C31.5199 22.4065 32.0004 21.0916 32.0004 19.6669C32.0004 16.1857 29.1321 13.3605 25.5833 13.3337C25.5817 13.3274 25.5801 13.3212 25.5785 13.3149Z" fill="url(#paint1_linear_87_7796)"/>
+								<path d="M7.06445 10.7028L18.0423 16.3333L25.5779 13.3148C24.5051 9.11261 20.6237 6 15.9997 6C12.4141 6 9.27508 7.87166 7.54586 10.6716C7.3841 10.6773 7.22358 10.6877 7.06445 10.7028Z" fill="url(#paint2_linear_87_7796)"/>
+								<path d="M1.7535 23.1687L18.0425 16.3331L7.06471 10.7026C3.09947 11.0792 0 14.3517 0 18.3331C0 20.1665 0.657197 21.8495 1.7535 23.1687Z" fill="url(#paint3_linear_87_7796)"/>
+							</g>
+							<defs>
+								<linearGradient id="paint0_linear_87_7796" x1="4.42591" y1="24.6668" x2="27.2309" y2="23.2764" gradientUnits="userSpaceOnUse">
+									<stop stop-color="#2086B8"/>
+									<stop offset="1" stop-color="#46D3F6"/>
+								</linearGradient>
+								<linearGradient id="paint1_linear_87_7796" x1="23.8302" y1="19.6668" x2="30.2108" y2="15.2082" gradientUnits="userSpaceOnUse">
+									<stop stop-color="#1694DB"/>
+									<stop offset="1" stop-color="#62C3FE"/>
+								</linearGradient>
+								<linearGradient id="paint2_linear_87_7796" x1="8.51037" y1="7.33333" x2="23.3335" y2="15.9348" gradientUnits="userSpaceOnUse">
+									<stop stop-color="#0D3D78"/>
+									<stop offset="1" stop-color="#063B83"/>
+								</linearGradient>
+								<linearGradient id="paint3_linear_87_7796" x1="-0.340429" y1="19.9998" x2="14.5634" y2="14.4649" gradientUnits="userSpaceOnUse">
+									<stop stop-color="#16589B"/>
+									<stop offset="1" stop-color="#1464B7"/>
+								</linearGradient>
+							</defs>
+						</svg>
+						<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive')}</div>
+					</DropdownMenu.SubTrigger>
+					<DropdownMenu.SubContent 
+						class="w-[calc(100vw-2rem)] max-w-[280px] rounded-xl px-1 py-1 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-sm"
+						side={$mobile ? "bottom" : "right"}
+						sideOffset={$mobile ? 5 : 0}
+						alignOffset={$mobile ? 0 : -8}
+					>
+						<DropdownMenu.Item
+							class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
+							on:click={() => {
+								uploadOneDriveHandler('personal');
+							}}
 						>
-							<path
-								d="M7.82979 26C3.50549 26 0 22.5675 0 18.3333C0 14.1921 3.35322 10.8179 7.54613 10.6716C9.27535 7.87166 12.4144 6 16 6C20.6308 6 24.5169 9.12183 25.5829 13.3335C29.1316 13.3603 32 16.1855 32 19.6667C32 23.0527 29 26 25.8723 25.9914L7.82979 26Z"
-								fill="#C4C4C4"
-							/>
-						</mask>
-						<g mask="url(#mask0_87_7796)">
-							<path
-								d="M7.83017 26.0001C5.37824 26.0001 3.18957 24.8966 1.75391 23.1691L18.0429 16.3335L30.7089 23.4647C29.5926 24.9211 27.9066 26.0001 26.0004 25.9915C23.1254 26.0001 12.0629 26.0001 7.83017 26.0001Z"
-								fill="url(#paint0_linear_87_7796)"
-							/>
-							<path
-								d="M25.5785 13.3149L18.043 16.3334L30.709 23.4647C31.5199 22.4065 32.0004 21.0916 32.0004 19.6669C32.0004 16.1857 29.1321 13.3605 25.5833 13.3337C25.5817 13.3274 25.5801 13.3212 25.5785 13.3149Z"
-								fill="url(#paint1_linear_87_7796)"
-							/>
-							<path
-								d="M7.06445 10.7028L18.0423 16.3333L25.5779 13.3148C24.5051 9.11261 20.6237 6 15.9997 6C12.4141 6 9.27508 7.87166 7.54586 10.6716C7.3841 10.6773 7.22358 10.6877 7.06445 10.7028Z"
-								fill="url(#paint2_linear_87_7796)"
-							/>
-							<path
-								d="M1.7535 23.1687L18.0425 16.3331L7.06471 10.7026C3.09947 11.0792 0 14.3517 0 18.3331C0 20.1665 0.657197 21.8495 1.7535 23.1687Z"
-								fill="url(#paint3_linear_87_7796)"
-							/>
-						</g>
-						<defs>
-							<linearGradient
-								id="paint0_linear_87_7796"
-								x1="4.42591"
-								y1="24.6668"
-								x2="27.2309"
-								y2="23.2764"
-								gradientUnits="userSpaceOnUse"
-							>
-								<stop stop-color="#2086B8" />
-								<stop offset="1" stop-color="#46D3F6" />
-							</linearGradient>
-							<linearGradient
-								id="paint1_linear_87_7796"
-								x1="23.8302"
-								y1="19.6668"
-								x2="30.2108"
-								y2="15.2082"
-								gradientUnits="userSpaceOnUse"
-							>
-								<stop stop-color="#1694DB" />
-								<stop offset="1" stop-color="#62C3FE" />
-							</linearGradient>
-							<linearGradient
-								id="paint2_linear_87_7796"
-								x1="8.51037"
-								y1="7.33333"
-								x2="23.3335"
-								y2="15.9348"
-								gradientUnits="userSpaceOnUse"
-							>
-								<stop stop-color="#0D3D78" />
-								<stop offset="1" stop-color="#063B83" />
-							</linearGradient>
-							<linearGradient
-								id="paint3_linear_87_7796"
-								x1="-0.340429"
-								y1="19.9998"
-								x2="14.5634"
-								y2="14.4649"
-								gradientUnits="userSpaceOnUse"
-							>
-								<stop stop-color="#16589B" />
-								<stop offset="1" stop-color="#1464B7" />
-							</linearGradient>
-						</defs>
-					</svg>
-					<div class="line-clamp-1">{$i18n.t('OneDrive')}</div>
-				</DropdownMenu.Item>
+							<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive (personal)')}</div>
+						</DropdownMenu.Item>
+						<DropdownMenu.Item
+							class="flex gap-2 items-center px-3 py-2 text-sm font-medium cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl"
+							on:click={() => {
+								uploadOneDriveHandler('organizations');
+							}}
+						>
+							<div class="flex flex-col">
+								<div class="line-clamp-1">{$i18n.t('Microsoft OneDrive (work/school)')}</div>
+								<div class="text-xs text-gray-500">Includes SharePoint</div>
+							</div>
+						</DropdownMenu.Item>
+					</DropdownMenu.SubContent>
+				</DropdownMenu.Sub>
 			{/if}
 		</DropdownMenu.Content>
 	</div>

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

@@ -83,6 +83,7 @@
 			});
 			return acc;
 		}, []);
+		console.log('citations', citations);
 
 		showRelevance = calculateShowRelevance(citations);
 		showPercentage = shouldShowPercentage(citations);

+ 7 - 4
src/lib/components/chat/Messages/CitationsModal.svelte

@@ -139,13 +139,16 @@
 														{percentage.toFixed(2)}%
 													</span>
 												{/if}
+
+												{#if typeof document?.distance === 'number'}
+													<span class="text-gray-500 dark:text-gray-500">
+														({(document?.distance ?? 0).toFixed(4)})
+													</span>
+												{/if}
+											{:else if typeof document?.distance === 'number'}
 												<span class="text-gray-500 dark:text-gray-500">
 													({(document?.distance ?? 0).toFixed(4)})
 												</span>
-											{:else}
-												<span class="text-gray-500 dark:text-gray-500">
-													{(document?.distance ?? 0).toFixed(4)}
-												</span>
 											{/if}
 										</div>
 									</Tooltip>

+ 4 - 4
src/lib/components/chat/Messages/ContentRenderer.svelte

@@ -154,11 +154,11 @@
 		}, [])}
 		{onSourceClick}
 		{onTaskClick}
-		on:update={(e) => {
-			dispatch('update', e.detail);
+		onUpdate={(value) => {
+			dispatch('update', value);
 		}}
-		on:code={(e) => {
-			const { lang, code } = e.detail;
+		onCode={(value) => {
+			const { lang, code } = value;
 
 			if (
 				($settings?.detectArtifacts ?? true) &&

+ 4 - 16
src/lib/components/chat/Messages/Markdown.svelte

@@ -7,9 +7,6 @@
 	import markedKatexExtension from '$lib/utils/marked/katex-extension';
 
 	import MarkdownTokens from './Markdown/MarkdownTokens.svelte';
-	import { createEventDispatcher } from 'svelte';
-
-	const dispatch = createEventDispatcher();
 
 	export let id = '';
 	export let content;
@@ -18,6 +15,9 @@
 
 	export let sourceIds = [];
 
+	export let onUpdate = () => {};
+	export let onCode = () => {};
+
 	export let onSourceClick = () => {};
 	export let onTaskClick = () => {};
 
@@ -40,17 +40,5 @@
 </script>
 
 {#key id}
-	<MarkdownTokens
-		{tokens}
-		{id}
-		{save}
-		{onTaskClick}
-		{onSourceClick}
-		on:update={(e) => {
-			dispatch('update', e.detail);
-		}}
-		on:code={(e) => {
-			dispatch('code', e.detail);
-		}}
-	/>
+	<MarkdownTokens {tokens} {id} {save} {onTaskClick} {onSourceClick} {onUpdate} {onCode} />
 {/key}

+ 6 - 7
src/lib/components/chat/Messages/Markdown/MarkdownTokens.svelte

@@ -1,6 +1,6 @@
 <script lang="ts">
 	import DOMPurify from 'dompurify';
-	import { createEventDispatcher, onMount, getContext } from 'svelte';
+	import { onMount, getContext } from 'svelte';
 	const i18n = getContext('i18n');
 
 	import fileSaver from 'file-saver';
@@ -22,8 +22,6 @@
 	import Source from './Source.svelte';
 	import { settings } from '$lib/stores';
 
-	const dispatch = createEventDispatcher();
-
 	export let id: string;
 	export let tokens: Token[];
 	export let top = true;
@@ -31,6 +29,9 @@
 
 	export let save = false;
 
+	export let onUpdate: Function = () => {};
+	export let onCode: Function = () => {};
+
 	export let onTaskClick: Function = () => {};
 	export let onSourceClick: Function = () => {};
 
@@ -93,11 +94,9 @@
 				code={token?.text ?? ''}
 				{attributes}
 				{save}
-				onCode={(value) => {
-					dispatch('code', value);
-				}}
+				{onCode}
 				onSave={(value) => {
-					dispatch('update', {
+					onUpdate({
 						raw: token.raw,
 						oldContent: token.text,
 						newContent: value

+ 8 - 7
src/lib/components/chat/Messages/MultiResponseMessages.svelte

@@ -200,9 +200,11 @@
 		await initHandler();
 		await tick();
 
-		const messageElement = document.getElementById(`message-${messageId}`);
-		if (messageElement) {
-			messageElement.scrollIntoView({ block: 'start' });
+		if ($settings?.scrollOnBranchChange ?? true) {
+			const messageElement = document.getElementById(`message-${messageId}`);
+			if (messageElement) {
+				messageElement.scrollIntoView({ block: 'start' });
+			}
 		}
 	});
 </script>
@@ -238,10 +240,9 @@
 									messageChildrenIds = history.messages[currentMessageId].childrenIds;
 								}
 								history.currentId = currentMessageId;
-
-								await tick();
-								await updateChat();
-								triggerScroll();
+								// await tick();
+								// await updateChat();
+								// triggerScroll();
 							}
 						}}
 					>

+ 5 - 3
src/lib/components/chat/Messages/UserMessage.svelte

@@ -65,10 +65,12 @@
 
 		await tick();
 
-		messageEditTextAreaElement.style.height = '';
-		messageEditTextAreaElement.style.height = `${messageEditTextAreaElement.scrollHeight}px`;
+		if (messageEditTextAreaElement) {
+			messageEditTextAreaElement.style.height = '';
+			messageEditTextAreaElement.style.height = `${messageEditTextAreaElement.scrollHeight}px`;
 
-		messageEditTextAreaElement?.focus();
+			messageEditTextAreaElement?.focus();
+		}
 	};
 
 	const editMessageConfirmHandler = async (submit = true) => {

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

@@ -778,7 +778,7 @@
 						</div>
 					</button>
 				</div>
-			{:else if filteredItems.length === 0}
+			{:else}
 				<div class="mb-3"></div>
 			{/if}
 

+ 11 - 5
src/lib/components/chat/Settings/About.svelte

@@ -159,15 +159,21 @@ Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 
 1. Redistributions of source code must retain the above copyright notice, this
-   list of conditions and the following disclaimer.
+	list of conditions and the following disclaimer.
 
 2. Redistributions in binary form must reproduce the above copyright notice,
-   this list of conditions and the following disclaimer in the documentation
-   and/or other materials provided with the distribution.
+	this list of conditions and the following disclaimer in the documentation
+	and/or other materials provided with the distribution.
 
 3. Neither the name of the copyright holder nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
+	contributors may be used to endorse or promote products derived from
+	this software without specific prior written permission.
+
+4. Notwithstanding any other provision of this License, and as a material condition of the rights granted herein, licensees are strictly prohibited from altering, removing, obscuring, or replacing any "Open WebUI" branding, including but not limited to the name, logo, or any visual, textual, or symbolic identifiers that distinguish the software and its interfaces, in any deployment or distribution, regardless of the number of users, except as explicitly set forth in Clauses 5 and 6 below.
+
+5. The branding restriction enumerated in Clause 4 shall not apply in the following limited circumstances: (i) deployments or distributions where the total number of end users (defined as individual natural persons with direct access to the application) does not exceed fifty (50) within any rolling thirty (30) day period; (ii) cases in which the licensee is an official contributor to the codebase—with a substantive code change successfully merged into the main branch of the official codebase maintained by the copyright holder—who has obtained specific prior written permission for branding adjustment from the copyright holder; or (iii) where the licensee has obtained a duly executed enterprise license expressly permitting such modification. For all other cases, any removal or alteration of the "Open WebUI" branding shall constitute a material breach of license.
+
+6. All code, modifications, or derivative works incorporated into this project prior to the incorporation of this branding clause remain licensed under the BSD 3-Clause License, and prior contributors retain all BSD-3 rights therein; if any such contributor requests the removal of their BSD-3-licensed code, the copyright holder will do so, and any replacement code will be licensed under the project's primary license then in effect. By contributing after this clause's adoption, you agree to the project's Contributor License Agreement (CLA) and to these updated terms for all new contributions.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+ 1 - 1
src/lib/components/chat/Settings/Interface.svelte

@@ -855,7 +855,7 @@
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
 					<div class=" self-center text-xs">
-						{$i18n.t('Scroll to bottom when switching between branches')}
+						{$i18n.t('Scroll On Branch Change')}
 					</div>
 
 					<button

+ 3 - 4
src/lib/components/common/Drawer.svelte

@@ -1,13 +1,12 @@
 <script lang="ts">
-	import { onDestroy, onMount, createEventDispatcher } from 'svelte';
+	import { onDestroy, onMount } from 'svelte';
 	import { flyAndScale } from '$lib/utils/transitions';
 	import { fade, fly, slide } from 'svelte/transition';
 	import { isApp } from '$lib/stores';
 
-	const dispatch = createEventDispatcher();
-
 	export let show = false;
 	export let className = '';
+	export let onClose = () => {};
 
 	let modalElement = null;
 	let mounted = false;
@@ -33,7 +32,7 @@
 		window.addEventListener('keydown', handleKeyDown);
 		document.body.style.overflow = 'hidden';
 	} else if (modalElement) {
-		dispatch('close');
+		onClose();
 		window.removeEventListener('keydown', handleKeyDown);
 
 		if (document.body.contains(modalElement)) {

+ 4 - 1
src/lib/components/common/Textarea.svelte

@@ -4,6 +4,7 @@
 	export let value = '';
 	export let placeholder = '';
 	export let rows = 1;
+	export let minSize = null;
 	export let required = false;
 	export let className =
 		'w-full rounded-lg px-3 py-2 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden  h-full';
@@ -29,7 +30,9 @@
 	const resize = () => {
 		if (textareaElement) {
 			textareaElement.style.height = '';
-			textareaElement.style.height = `${textareaElement.scrollHeight}px`;
+			textareaElement.style.height = minSize
+				? `${Math.max(textareaElement.scrollHeight, minSize)}px`
+				: `${textareaElement.scrollHeight}px`;
 		}
 	};
 </script>

+ 36 - 7
src/lib/components/workspace/Knowledge/KnowledgeBase.svelte

@@ -11,7 +11,7 @@
 	import { page } from '$app/stores';
 	import { mobile, showSidebar, knowledge as _knowledge, config, user } from '$lib/stores';
 
-	import { updateFileDataContentById, uploadFile, deleteFileById } from '$lib/apis/files';
+	import { updateFileDataContentById, uploadFile, deleteFileById, getFileById } from '$lib/apis/files';
 	import {
 		addFileToKnowledgeById,
 		getKnowledgeById,
@@ -84,12 +84,15 @@
 
 	let selectedFile = null;
 	let selectedFileId = null;
+	let selectedFileContent = '';
+
+	// Add cache object
+	let fileContentCache = new Map();
 
 	$: if (selectedFileId) {
 		const file = (knowledge?.files ?? []).find((file) => file.id === selectedFileId);
 		if (file) {
-			file.data = file.data ?? { content: '' };
-			selectedFile = file;
+			fileSelectHandler(file);
 		} else {
 			selectedFile = null;
 		}
@@ -394,7 +397,10 @@
 
 	const updateFileContentHandler = async () => {
 		const fileId = selectedFile.id;
-		const content = selectedFile.data.content;
+		const content = selectedFileContent;
+
+		// Clear the cache for this file since we're updating it
+		fileContentCache.delete(fileId);
 
 		const res = updateFileDataContentById(localStorage.token, fileId, content).catch((e) => {
 			toast.error(`${e}`);
@@ -450,6 +456,29 @@
 		}
 	};
 
+	const fileSelectHandler = async (file) => {
+		try {
+			selectedFile = file;
+			
+			// Check cache first
+			if (fileContentCache.has(file.id)) {
+				selectedFileContent = fileContentCache.get(file.id);
+				return;
+			}
+
+			const response = await getFileById(localStorage.token, file.id);
+			if (response) {
+				selectedFileContent = response.data.content;
+				// Cache the content
+				fileContentCache.set(file.id, response.data.content);
+			} else {
+				toast.error($i18n.t('No content found in file.'));
+			}
+		} catch (e) {
+			toast.error($i18n.t('Failed to load file content.'));
+		}
+	};  
+
 	const onDragOver = (e) => {
 		e.preventDefault();
 
@@ -728,7 +757,7 @@
 								{#key selectedFile.id}
 									<RichTextInput
 										className="input-prose-sm"
-										bind:value={selectedFile.data.content}
+										bind:value={selectedFileContent}
 										placeholder={$i18n.t('Add content here')}
 										preserveBreaks={true}
 									/>
@@ -747,7 +776,7 @@
 				<Drawer
 					className="h-full"
 					show={selectedFileId !== null}
-					on:close={() => {
+					onClose={() => {
 						selectedFileId = null;
 					}}
 				>
@@ -786,7 +815,7 @@
 								{#key selectedFile.id}
 									<RichTextInput
 										className="input-prose-sm"
-										bind:value={selectedFile.data.content}
+										bind:value={selectedFileContent}
 										placeholder={$i18n.t('Add content here')}
 										preserveBreaks={true}
 									/>

+ 5 - 1
src/lib/components/workspace/Models/ModelEditor.svelte

@@ -56,6 +56,7 @@
 		}
 	}
 
+	let system = '';
 	let info = {
 		id: '',
 		base_model_id: null,
@@ -155,6 +156,7 @@
 			}
 		}
 
+		info.params.system = system.trim() === '' ? null : system;
 		info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
 		Object.keys(info.params).forEach((key) => {
 			if (info.params[key] === '' || info.params[key] === null) {
@@ -201,6 +203,8 @@
 				}
 			}
 
+			system = model?.params?.system ?? '';
+
 			params = { ...params, ...model?.params };
 			params.stop = params?.stop
 				? (typeof params.stop === 'string' ? params.stop.split(',') : (params?.stop ?? [])).join(
@@ -553,7 +557,7 @@
 										className=" text-sm w-full bg-transparent outline-hidden resize-none overflow-y-hidden "
 										placeholder={`Write your model system prompt content here\ne.g.) You are Mario from Super Mario Bros, acting as an assistant.`}
 										rows={4}
-										bind:value={info.params.system}
+										bind:value={system}
 									/>
 								</div>
 							</div>

+ 12 - 3
src/lib/components/workspace/Prompts/PromptEditor.svelte

@@ -8,6 +8,7 @@
 	import LockClosed from '$lib/components/icons/LockClosed.svelte';
 	import AccessControlModal from '../common/AccessControlModal.svelte';
 	import { user } from '$lib/stores';
+	import { slugify } from '$lib/utils';
 
 	export let onSubmit: Function;
 	export let edit = false;
@@ -25,8 +26,15 @@
 
 	let showAccessControlModal = false;
 
-	$: if (!edit) {
-		command = title !== '' ? `${title.replace(/\s+/g, '-').toLowerCase()}` : '';
+	let hasManualEdit = false;
+
+	$: if (!edit && !hasManualEdit) {
+		command = title !== '' ? slugify(title) : '';
+	}
+
+	// Track manual edits
+	function handleCommandInput(e: Event) {
+		hasManualEdit = true;
 	}
 
 	const submitHandler = async () => {
@@ -64,7 +72,7 @@
 			command = prompt.command.at(0) === '/' ? prompt.command.slice(1) : prompt.command;
 			content = prompt.content;
 
-			accessControl = prompt?.access_control ?? null;
+			accessControl = prompt?.access_control ?? {};
 		}
 	});
 </script>
@@ -125,6 +133,7 @@
 							class=" w-full bg-transparent outline-hidden"
 							placeholder={$i18n.t('Command')}
 							bind:value={command}
+							on:input={handleCommandInput}
 							required
 							disabled={edit}
 						/>

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

@@ -57,17 +57,17 @@
 	"All": "Tots",
 	"All Documents": "Tots els documents",
 	"All models deleted successfully": "Tots els models s'han eliminat correctament",
-	"Allow Call": "",
+	"Allow Call": "Permetre la trucada",
 	"Allow Chat Controls": "Permetre els controls de xat",
 	"Allow Chat Delete": "Permetre eliminar el xat",
 	"Allow Chat Deletion": "Permetre la supressió del xat",
 	"Allow Chat Edit": "Permetre editar el xat",
 	"Allow File Upload": "Permetre la pujada d'arxius",
-	"Allow Multiple Models in Chat": "",
+	"Allow Multiple Models in Chat": "Permetre múltiple models al xat",
 	"Allow non-local voices": "Permetre veus no locals",
-	"Allow Speech to Text": "",
+	"Allow Speech to Text": "Permetre Parla a Text",
 	"Allow Temporary Chat": "Permetre el xat temporal",
-	"Allow Text to Speech": "",
+	"Allow Text to Speech": "Permetre Text a Parla",
 	"Allow User Location": "Permetre la ubicació de l'usuari",
 	"Allow Voice Interruption in Call": "Permetre la interrupció de la veu en una trucada",
 	"Allowed Endpoints": "Punts d'accés permesos",
@@ -83,7 +83,7 @@
 	"and": "i",
 	"and {{COUNT}} more": "i {{COUNT}} més",
 	"and create a new shared link.": "i crear un nou enllaç compartit.",
-	"Android": "",
+	"Android": "Android",
 	"API Base URL": "URL Base de l'API",
 	"API Key": "clau API",
 	"API Key created.": "clau API creada.",
@@ -245,7 +245,7 @@
 	"Copied shared chat URL to clipboard!": "S'ha copiat l'URL compartida al porta-retalls!",
 	"Copied to clipboard": "Copiat al porta-retalls",
 	"Copy": "Copiar",
-	"Copy Formatted Text": "",
+	"Copy Formatted Text": "Copiar el text formatat",
 	"Copy last code block": "Copiar l'últim bloc de codi",
 	"Copy last response": "Copiar l'última resposta",
 	"Copy Link": "Copiar l'enllaç",
@@ -308,7 +308,7 @@
 	"Deleted User": "Usuari eliminat",
 	"Describe your knowledge base and objectives": "Descriu la teva base de coneixement i objectius",
 	"Description": "Descripció",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "Detectar automàticament els artefactes",
 	"Didn't fully follow instructions": "No s'han seguit les instruccions completament",
 	"Direct": "Directe",
 	"Direct Connections": "Connexions directes",
@@ -364,7 +364,7 @@
 	"e.g. my_filter": "p. ex. els_meus_filtres",
 	"e.g. my_tools": "p. ex. les_meves_eines",
 	"e.g. Tools for performing various operations": "p. ex. Eines per dur a terme operacions",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "p. ex. en-US, ja-JP, ca-ES (deixa-ho en blanc per detecció automàtica)",
 	"Edit": "Editar",
 	"Edit Arena Model": "Editar model de l'Arena",
 	"Edit Channel": "Editar el canal",
@@ -414,8 +414,8 @@
 	"Enter Document Intelligence Key": "Introdueix la clau de Document Intelligence",
 	"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 Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "Introdueix la URL base de Firecrawl API",
+	"Enter Firecrawl API Key": "Introdueix la clau API de Firecrawl",
 	"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 Engine Id": "Introdueix l'identificador del motor PSE de Google",
@@ -433,8 +433,8 @@
 	"Enter Mojeek Search API Key": "Introdueix la clau API de Mojeek Search",
 	"Enter Number of Steps (e.g. 50)": "Introdueix el nombre de passos (p. ex. 50)",
 	"Enter Perplexity API Key": "Introdueix la clau API de Perplexity",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Playwright Timeout": "Introdueix el timeout de Playwright",
+	"Enter Playwright WebSocket URL": "Introdueix la URL de Playwright WebSocket",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "Entra l'URL (p. ex. https://user:password@host:port)",
 	"Enter reasoning effort": "Introdueix l'esforç de raonament",
 	"Enter Sampler (e.g. Euler a)": "Introdueix el mostrejador (p.ex. Euler a)",
@@ -452,13 +452,13 @@
 	"Enter server host": "Introdueix el servidor",
 	"Enter server label": "Introdueix l'etiqueta del servidor",
 	"Enter server port": "Introdueix el port del servidor",
-	"Enter Sougou Search API sID": "",
-	"Enter Sougou Search API SK": "",
+	"Enter Sougou Search API sID": "Introdueix el sID de l'API de Sougou Search",
+	"Enter Sougou Search API SK": "Introdueix l'SK de l'API de Sougou Search",
 	"Enter stop sequence": "Introdueix la seqüència de parada",
 	"Enter system prompt": "Introdueix la indicació de sistema",
 	"Enter system prompt here": "Entra la indicació de sistema aquí",
 	"Enter Tavily API Key": "Introdueix la clau API de Tavily",
-	"Enter Tavily Extract Depth": "",
+	"Enter Tavily Extract Depth": "Introdueix la profunditat d'extracció de Tavily",
 	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Entra la URL pública de WebUI. Aquesta URL s'utilitzarà per generar els enllaços en les notificacions.",
 	"Enter Tika Server URL": "Introdueix l'URL del servidor Tika",
 	"Enter timeout in seconds": "Entra el temps màxim en segons",
@@ -539,8 +539,8 @@
 	"Filter is now globally enabled": "El filtre ha estat activat globalment",
 	"Filters": "Filtres",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "S'ha detectat la suplantació d'identitat de l'empremta digital: no es poden utilitzar les inicials com a avatar. S'estableix la imatge de perfil predeterminada.",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "URL de l'API de base de Firecrawl",
+	"Firecrawl API Key": "Clau API de Firecrawl",
 	"Fluidly stream large external response chunks": "Transmetre amb fluïdesa grans trossos de resposta externa",
 	"Focus chat input": "Estableix el focus a l'entrada del xat",
 	"Folder deleted successfully": "Carpeta eliminada correctament",
@@ -605,8 +605,8 @@
 	"Hybrid Search": "Cerca híbrida",
 	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Afirmo que he llegit i entenc les implicacions de la meva acció. Soc conscient dels riscos associats a l'execució de codi arbitrari i he verificat la fiabilitat de la font.",
 	"ID": "ID",
-	"iframe Sandbox Allow Forms": "",
-	"iframe Sandbox Allow Same Origin": "",
+	"iframe Sandbox Allow Forms": "Permetre formularis sandbox iframe",
+	"iframe Sandbox Allow Same Origin": "Permetre same-origin sandbox iframe",
 	"Ignite curiosity": "Despertar la curiositat",
 	"Image": "Imatge",
 	"Image Compression": "Compressió d'imatges",
@@ -667,7 +667,7 @@
 	"Label": "Etiqueta",
 	"Landing Page Mode": "Mode de la pàgina d'entrada",
 	"Language": "Idioma",
-	"Language Locales": "",
+	"Language Locales": "Localització d'idiomes",
 	"Last Active": "Activitat recent",
 	"Last Modified": "Modificació",
 	"Last reply": "Darrera resposta",
@@ -851,8 +851,8 @@
 	"Pipelines Valves": "Vàlvules de les Pipelines",
 	"Plain text (.txt)": "Text pla (.txt)",
 	"Playground": "Zona de jocs",
-	"Playwright Timeout (ms)": "",
-	"Playwright WebSocket URL": "",
+	"Playwright Timeout (ms)": "Temps d'espera (ms) de Playwright",
+	"Playwright WebSocket URL": "URL del WebSocket de Playwright",
 	"Please carefully review the following warnings:": "Si us plau, revisa els següents avisos amb cura:",
 	"Please do not close the settings page while loading the model.": "No tanquis la pàgina de configuració mentre carregues el model.",
 	"Please enter a prompt": "Si us plau, entra una indicació",
@@ -898,11 +898,11 @@
 	"References from": "Referències de",
 	"Refused when it shouldn't have": "Refusat quan no hauria d'haver estat",
 	"Regenerate": "Regenerar",
-	"Reindex": "",
-	"Reindex Knowledge Base Vectors": "",
+	"Reindex": "Reindexar",
+	"Reindex Knowledge Base Vectors": "Reindexar els vector base del Coneixement",
 	"Release Notes": "Notes de la versió",
 	"Relevance": "Rellevància",
-	"Relevance Threshold": "",
+	"Relevance Threshold": "Límit de rellevància",
 	"Remove": "Eliminar",
 	"Remove Model": "Eliminar el model",
 	"Rename": "Canviar el nom",
@@ -1032,8 +1032,8 @@
 	"Sign up to {{WEBUI_NAME}}": "Registrar-se a {{WEBUI_NAME}}",
 	"Signing in to {{WEBUI_NAME}}": "Iniciant sessió a {{WEBUI_NAME}}",
 	"sk-1234": "sk-1234",
-	"Sougou Search API sID": "",
-	"Sougou Search API SK": "",
+	"Sougou Search API sID": "sID de l'API de Sougou Search",
+	"Sougou Search API SK": "SK de l'API de Sougou Search",
 	"Source": "Font",
 	"Speech Playback Speed": "Velocitat de la parla",
 	"Speech recognition error: {{error}}": "Error de reconeixement de veu: {{error}}",
@@ -1061,7 +1061,7 @@
 	"Tap to interrupt": "Prem per interrompre",
 	"Tasks": "Tasques",
 	"Tavily API Key": "Clau API de Tavily",
-	"Tavily Extract Depth": "",
+	"Tavily Extract Depth": "Profunditat d'extracció de Tavily",
 	"Tell us more:": "Dona'ns més informació:",
 	"Temperature": "Temperatura",
 	"Template": "Plantilla",
@@ -1184,8 +1184,8 @@
 	"Use Gravatar": "Utilitzar Gravatar",
 	"Use groups to group your users and assign permissions.": "Utilitza grups per agrupar els usuaris i assignar permisos.",
 	"Use Initials": "Utilitzar inicials",
-	"Use no proxy to fetch page contents.": "",
-	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "",
+	"Use no proxy to fetch page contents.": "No utilitzis un proxy per obtenir contingut de la pàgina.",
+	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Utilitza el proxy designat per les variables d'entorn http_proxy i https_proxy per obtenir el contingut de la pàgina.",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "usuari",
@@ -1203,7 +1203,7 @@
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable per tenir-les reemplaçades amb el contingut del porta-retalls.",
 	"Verify Connection": "Verificar la connexió",
-	"Verify SSL Certificate": "",
+	"Verify SSL Certificate": "Verificar el certificat SSL",
 	"Version": "Versió",
 	"Version {{selectedVersion}} of {{totalVersions}}": "Versió {{selectedVersion}} de {{totalVersions}}",
 	"View Replies": "Veure les respostes",
@@ -1218,7 +1218,7 @@
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "Avís: l'execució de Jupyter permet l'execució de codi arbitrari, la qual cosa comporta greus riscos de seguretat; procediu amb extrema precaució.",
 	"Web": "Web",
 	"Web API": "Web API",
-	"Web Loader Engine": "",
+	"Web Loader Engine": "Motor de càrrega Web",
 	"Web Search": "Cerca la web",
 	"Web Search Engine": "Motor de cerca de la web",
 	"Web Search in Chat": "Cerca a internet al xat",

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

@@ -346,7 +346,7 @@
 	"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 tools from sources you don't trust.": "installieren Sie keine Werkzeuge aus Quellen, denen Sie nicht vertrauen.",
-	"Don't like the style": "schlechter Schreibstil",
+	"Don't like the style": "Schlechter Schreibstil",
 	"Done": "Erledigt",
 	"Download": "Exportieren",
 	"Download as SVG": "Exportieren als SVG",
@@ -781,7 +781,7 @@
 	"No valves to update": "Keine Valves zum Aktualisieren",
 	"None": "Nichts",
 	"Not factually correct": "Nicht sachlich korrekt",
-	"Not helpful": "Nich hilfreich",
+	"Not helpful": "Nicht hilfreich",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Hinweis: Wenn Sie eine Mindestpunktzahl festlegen, werden in der Suche nur Dokumente mit einer Punktzahl größer oder gleich der Mindestpunktzahl zurückgegeben.",
 	"Notes": "Notizen",
 	"Notification Sound": "Benachrichtigungston",

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

@@ -14,29 +14,29 @@
 	"*Prompt node ID(s) are required for image generation": "Los ID de nodo son requeridos para la generación de imágenes",
 	"A new version (v{{LATEST_VERSION}}) is now available.": "Nueva versión (v{{LATEST_VERSION}}) disponible.",
 	"A task model is used when performing tasks such as generating titles for chats and web search queries": "El modelo de tareas realiza tareas como la generación de títulos para chats y consultas de búsqueda web",
-	"a user": "un/a usuari@",
+	"a user": "un usuario",
 	"About": "Acerca de",
 	"Accept autocomplete generation / Jump to prompt variable": "Aceptar generación de autocompletado / Saltar a indicador variable",
 	"Access": "Acceso",
 	"Access Control": "Control de Acceso",
-	"Accessible to all users": "Accesible para todos l@s usuari@s",
+	"Accessible to all users": "Accesible para todos los usuarios",
 	"Account": "Cuenta",
 	"Account Activation Pending": "Activación de cuenta Pendiente",
 	"Accurate information": "Información precisa",
 	"Actions": "Acciones",
 	"Activate": "Activar",
 	"Activate this command by typing \"/{{COMMAND}}\" to chat input.": "Activar este comando escribiendo \"/{{COMMAND}}\" en el chat",
-	"Active Users": "Usuari@s activos",
+	"Active Users": "Usuarios activos",
 	"Add": "Añadir",
 	"Add a model ID": "Añadir un ID de modelo",
 	"Add a short description about what this model does": "Añadir una breve descripción sobre lo que hace este modelo",
 	"Add a tag": "Añadir una etiqueta",
-	"Add Arena Model": "Añadir un modelo a la Arena",
+	"Add Arena Model": "Añadir modelo a la Arena",
 	"Add Connection": "Añadir Conexión",
 	"Add Content": "Añadir Contenido",
 	"Add content here": "Añadir contenido aquí",
 	"Add custom prompt": "Añadir un indicador personalizado",
-	"Add Files": "Añadir Ficheros",
+	"Add Files": "Añadir Archivos",
 	"Add Group": "Añadir Grupo",
 	"Add Memory": "Añadir Memoria",
 	"Add Model": "Añadir Modelo",
@@ -44,31 +44,31 @@
 	"Add Tag": "Añadir etiqueta",
 	"Add Tags": "Añadir etiquetas",
 	"Add text content": "Añade contenido de texto",
-	"Add User": "Añadir Usuari@",
-	"Add User Group": "Añadir Grupo de Usuari@",
-	"Adjusting these settings will apply changes universally to all users.": "El ajuste de estas opciones se aplicará globalmente a todos l@s usuari@s.",
+	"Add User": "Añadir Usuario",
+	"Add User Group": "Añadir grupo de usuarios",
+	"Adjusting these settings will apply changes universally to all users.": "El ajuste de estas opciones se aplicará globalmente a todos los usuarios.",
 	"admin": "admin",
 	"Admin": "Admin",
 	"Admin Panel": "Administración",
 	"Admin Settings": "Ajustes de Admin",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Los Admins tienen acceso a todas las herramientas en todo momento; l@s usuari@s necesitan, en el área de trabajo, que los modelos tengan asignadas las herramentas.",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Los administradores tienen acceso a todas las herramientas en todo momento; los usuarios necesitan que los modelos tengan asignadas las herramientas en el area de trabajo.",
 	"Advanced Parameters": "Parámetros Avanzados",
-	"Advanced Params": "Param. Avanz.",
+	"Advanced Params": "Parámetros Avanzados",
 	"All": "Todos",
 	"All Documents": "Todos los Documentos",
 	"All models deleted successfully": "Todos los modelos borrados correctamnete",
-	"Allow Call": "",
+	"Allow Call": "Permitir Llamada",
 	"Allow Chat Controls": "Permitir Controles del Chat",
 	"Allow Chat Delete": "Permitir Borrar Chat",
 	"Allow Chat Deletion": "Permitir Borrado de Chat",
 	"Allow Chat Edit": "Pemritir Editar Chat",
-	"Allow File Upload": "Permitir Subida de Ficheros",
+	"Allow File Upload": "Permitir Subida de Archivos",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permitir voces no locales",
 	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Permitir Chat Temporal",
 	"Allow Text to Speech": "",
-	"Allow User Location": "Permitir Ubicación de Usuari@",
+	"Allow User Location": "Permitir Ubicación de Usuario",
 	"Allow Voice Interruption in Call": "Permitir Interrupción de Voz en Llamada",
 	"Allowed Endpoints": "Endpoints Permitidos",
 	"Already have an account?": "¿Ya tienes una cuenta?",
@@ -91,34 +91,34 @@
 	"API keys": "Claves API",
 	"Application DN": "Aplicacion DN",
 	"Application DN Password": "Contraseña Aplicacion DN",
-	"applies to all users with the \"user\" role": "se aplica a todos l@s usuari@s con el rol \"user\" ",
+	"applies to all users with the \"user\" role": "se aplica a todos los usuarios con el rol \"user\" ",
 	"April": "Abril",
 	"Archive": "Archivar",
 	"Archive All Chats": "Archivar Todos los Chats",
 	"Archived Chats": "Chats archivados",
 	"archived-chat-export": "exportar chats archivados",
-	"Are you sure you want to clear all memories? This action cannot be undone.": "¿estas segur@ que quieres borrar todas las memorias? (¡esta acción NO se puede deshacer!)",
-	"Are you sure you want to delete this channel?": "¿Estás segur@ de que quieres eliminar este canal?",
-	"Are you sure you want to delete this message?": "¿Estás segur@ de que quieres eliminar este mensaje? ",
-	"Are you sure you want to unarchive all archived chats?": "¿Estás segur@ de que quieres desarchivar todos los chats archivados?",
-	"Are you sure?": "¿Está segur@?",
+	"Are you sure you want to clear all memories? This action cannot be undone.": "¿Seguro que quieres borrar todas las memorias? (¡esta acción NO se puede deshacer!)",
+	"Are you sure you want to delete this channel?": "¿Seguro de que quieres eliminar este canal?",
+	"Are you sure you want to delete this message?": "¿Seguro de que quieres eliminar este mensaje? ",
+	"Are you sure you want to unarchive all archived chats?": "¿Seguro de que quieres desarchivar todos los chats archivados?",
+	"Are you sure?": "¿Estás seguro?",
 	"Arena Models": "Arena de Modelos",
 	"Artifacts": "Artefactos",
 	"Ask": "Preguntar",
 	"Ask a question": "Haz una pregunta",
 	"Assistant": "Asistente",
-	"Attach file from knowledge": "Adjuntar fichero desde el conocimiento",
+	"Attach file from knowledge": "Adjuntar archivo desde conocimiento",
 	"Attention to detail": "Atención al detalle",
 	"Attribute for Mail": "Atributo para Correo",
-	"Attribute for Username": "Atributo para Nombre de Usuari@",
+	"Attribute for Username": "Atributo para Nombre de Usuario",
 	"Audio": "Audio",
 	"August": "Agosto",
 	"Auth": "Autorización",
 	"Authenticate": "Autentificar",
-	"Authentication": "Autentificación",
+	"Authentication": "Autenticación",
 	"Auto": "Auto",
 	"Auto-Copy Response to Clipboard": "AutoCopiado de respuesta al Portapapeles",
-	"Auto-playback response": "AutoReproducir Respuesta",
+	"Auto-playback response": "Reproducir Respuesta automáticamente",
 	"Autocomplete Generation": "Generación de Autocompletado",
 	"Autocomplete Generation Input Max Length": "Max. Longitud de Entrada en Generación de Autocompletado",
 	"Automatic1111": "AUTOMATIC1111",
@@ -126,7 +126,7 @@
 	"AUTOMATIC1111 Base URL": "URL Base de AUTOMATIC1111",
 	"AUTOMATIC1111 Base URL is required.": "la URL Base de AUTOMATIC1111 es necesaria.",
 	"Available list": "Lista disponible",
-	"Available Tools": "",
+	"Available Tools": "Herramientas Disponibles",
 	"available!": "¡disponible!",
 	"Awful": "Horrible",
 	"Azure AI Speech": "Voz Azure AI",
@@ -148,23 +148,23 @@
 	"Bypass Embedding and Retrieval": "Evitar Incrustración y Recuperación",
 	"Calendar": "Calendario",
 	"Call": "Llamada",
-	"Call feature is not supported when using Web STT engine": "La característica Llamada no está soportada cuando se usa el motor Web STT",
+	"Call feature is not supported when using Web STT engine": "La funcionalidad de Llamada no está soportada cuando se usa el motor Web STT",
 	"Camera": "Cámara",
 	"Cancel": "Cancelar",
 	"Capabilities": "Capacidades",
 	"Capture": "Captura",
 	"Certificate Path": "Ruta a Certificado",
-	"Change Password": "Cambia la Contraseña",
-	"Channel Name": "Nombre de Canal",
+	"Change Password": "Cambiar Contraseña",
+	"Channel Name": "Nombre del Canal",
 	"Channels": "Canal",
 	"Character": "Carácter",
 	"Character limit for autocomplete generation input": "Límite de caracteres de entrada de la generación de autocompletado",
 	"Chart new frontiers": "Trazar nuevas fronteras",
 	"Chat": "Chat",
 	"Chat Background Image": "Imágen de Fondo del Chat",
-	"Chat Bubble UI": "Interface del Chat tipo Burbuja",
-	"Chat Controls": "Controles del chat",
-	"Chat direction": "Dirección del Chat",
+	"Chat Bubble UI": "Interface de Chat tipo Burbuja",
+	"Chat Controls": "Controles de chat",
+	"Chat direction": "Dirección de Chat",
 	"Chat Overview": "Vista General del Chat",
 	"Chat Permissions": "Permisos del Chat",
 	"Chat Tags Auto-Generation": "AutoGeneración de Etiquetas de Chat",
@@ -183,15 +183,15 @@
 	"Click here for filter guides.": "Pulsar aquí para guías de filtros",
 	"Click here for help.": "Pulsar aquí para Ayuda.",
 	"Click here to": "Pulsa aquí para",
-	"Click here to download user import template file.": "Pulsa aquí para descargar la plantilla de importación de usuari@.",
-	"Click here to learn more about faster-whisper and see the available models.": "Pulsa aquí para saber más sobre faster-whisper y ver modelos disponibles.",
+	"Click here to download user import template file.": "Pulsa aquí para descargar la plantilla para importar usuarios.",
+	"Click here to learn more about faster-whisper and see the available models.": "Pulsa aquí para saber más sobre faster-whisper y ver los modelos disponibles.",
 	"Click here to see available models.": "Pulsa aquí para ver modelos disponibles.",
 	"Click here to select": "Pulsa aquí para seleccionar",
 	"Click here to select a csv file.": "Pulsa aquí para seleccionar un fichero de Valores Separados por Comas (.csv)",
 	"Click here to select a py file.": "Pulsa aquí para seleccionar un fichero Python (.py)",
 	"Click here to upload a workflow.json file.": "Pulsa aquí para subir un fichero workflow.json",
 	"click here.": "Pulsa aquí.",
-	"Click on the user role button to change a user's role.": "Pulsa en el botón rol de usuari@ para cambiar su rol.",
+	"Click on the user role button to change a user's role.": "Pulsa en el botón rol de usuario para cambiar su rol.",
 	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permisos de escritura del portapapeles denegado. Por favor, comprueba la configuración de tu navegador para otorgar el permiso necesario.",
 	"Clone": "Clonar",
 	"Clone Chat": "Clonar Chat",
@@ -200,8 +200,8 @@
 	"Code execution": "Ejecución de Código",
 	"Code Execution": "Ejecución de Código",
 	"Code Execution Engine": "Motor de Ejecución de Código",
-	"Code Execution Timeout": "Tiempo",
-	"Code formatted successfully": "Se ha formateado correctamente el código.",
+	"Code Execution Timeout": "Tiempo límite de espera para Ejecución de Código",
+	"Code formatted successfully": "El codigo se ha formateado correctamente.",
 	"Code Interpreter": "Interprete de Código",
 	"Code Interpreter Engine": "Motor del Interprete de Código",
 	"Code Interpreter Prompt Template": "Plantilla del Indicador del Interprete de Código",
@@ -287,7 +287,7 @@
 	"Default to 389 or 636 if TLS is enabled": "Predeterminado a 389, o 636 si TLS está habilitado",
 	"Default to ALL": "Predeterminado a TODOS",
 	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Por defecto está predeterminada una segmentación de la recuperación para una extracción de contenido centrado y relevante, recomendado para la mayoría de los casos.",
-	"Default User Role": "Rol Predeterminado de l@s Usuari@s Nuev@s",
+	"Default User Role": "Rol predeterminado de los nuevos usuarios",
 	"Delete": "Borrar",
 	"Delete a model": "Borrar un modelo",
 	"Delete All Chats": "Borrar todos los chats",
@@ -302,17 +302,17 @@
 	"Delete prompt?": "¿Borrar el indicador?",
 	"delete this link": "Borrar este enlace",
 	"Delete tool?": "¿Borrar la herramienta?",
-	"Delete User": "Borrar Usuari@",
+	"Delete User": "Borrar Usuario",
 	"Deleted {{deleteModelTag}}": "{{deleteModelTag}} Borrado",
 	"Deleted {{name}}": "{{nombre}} Borrado",
-	"Deleted User": "Usuari@ Borrado",
+	"Deleted User": "Usuario Borrado",
 	"Describe your knowledge base and objectives": "Describe tu Base de Conocimientos y sus objetivos",
 	"Description": "Descripción",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "Detectar Artefactos Automáticamente",
 	"Didn't fully follow instructions": "No seguiste completamente las instrucciones",
 	"Direct": "Directo",
 	"Direct Connections": "Conexiones Directas",
-	"Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Las Conexiones Directas permiten a l@s usuari@s conectar a sus propios endpoints compatibles API OpenAI.",
+	"Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Las Conexiones Directas permiten a los usuarios conectar a sus propios endpoints compatibles API OpenAI.",
 	"Direct Connections settings updated": "Se actualizaron las configuraciones de las Conexiones Directas",
 	"Direct Tool Servers": "Servidores de Herramientas Directos",
 	"Disabled": "Deshabilitado",
@@ -328,8 +328,8 @@
 	"Discover, download, and explore model presets": "Descubre, descarga y explora modelos con preajustados",
 	"Dismissible": "Desestimable",
 	"Display": "Mostrar",
-	"Display Emoji in Call": "Muestra chirimbolitos(Emojis) en Llamada",
-	"Display the username instead of You in the Chat": "Mostrar en el chat el nombre de usuari@ en lugar del genérico Tu/Usted",
+	"Display Emoji in Call": "Muestra Emojis en Llamada",
+	"Display the username instead of You in the Chat": "Mostrar en el chat el nombre de usuario en lugar del genérico Tu",
 	"Displays citations in the response": "Mostrar citas en la respuesta",
 	"Dive into knowledge": "Sumérgete en el conocimiento",
 	"Do not install functions from sources you do not fully trust.": "¡No instalar funciones de fuentes en las que que no se confíe totalmente!",
@@ -344,8 +344,8 @@
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "no se realiza ninguna conexión externa y tus datos permanecen seguros alojados localmente en tu servidor.",
 	"Domain Filter List": "Lista de Filtrado de Dominio",
 	"Don't have an account?": "¿No tienes una cuenta?",
-	"don't install random functions from sources you don't trust.": "¡no instalar funciones aleatorias de fuentes en las que no se confíe!",
-	"don't install random tools from sources you don't trust.": "¡no instalar herramientas aleatorias de fuentes en las que no se confíe!",
+	"don't install random functions from sources you don't trust.": "¡no instalar funciones desconocidas de fuentes en las que no se confíe!",
+	"don't install random tools from sources you don't trust.": "¡no instalar herramientas desconocidas de fuentes en las que no se confíe!",
 	"Don't like the style": "¿No te gusta el estilo?",
 	"Done": "Hecho",
 	"Download": "Descargar",
@@ -358,21 +358,21 @@
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades de tiempo válidas son 's', 'm', 'h'.",
 	"e.g. \"json\" or a JSON schema": "p.ej. \"json\" o un esquema JSON",
 	"e.g. 60": "p.ej. 60",
-	"e.g. A filter to remove profanity from text": "p.ej. Un filtro para eliminar 'blasfemia' del texto",
+	"e.g. A filter to remove profanity from text": "p.ej. Un filtro para eliminar malas palabras del texto",
 	"e.g. My Filter": "p.ej. Mi Filtro",
 	"e.g. My Tools": "p.ej. Mis Herramientas",
 	"e.g. my_filter": "p.ej. mi_filtro",
 	"e.g. my_tools": "p.ej. mis_herramientas",
 	"e.g. Tools for performing various operations": "p.ej. Herramientas para realizar varias operaciones",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "p. ej., en-US,ja-JP (dejar en blanco para detectar automáticamente)",
 	"Edit": "Editar",
 	"Edit Arena Model": "Editar Modelo en Arena",
 	"Edit Channel": "Editar Canal",
 	"Edit Connection": "Editar Conexión",
 	"Edit Default Permissions": "Editar Permisos Predeterminados",
 	"Edit Memory": "Editar Memoria",
-	"Edit User": "Editar Usuari@",
-	"Edit User Group": "Editar Grupo de Usuari@",
+	"Edit User": "Editar Usuario",
+	"Edit User Group": "Editar Grupo de Usuarios",
 	"ElevenLabs": "ElevenLabs",
 	"Email": "Email",
 	"Embark on adventures": "Embarcate en aventuras",
@@ -390,13 +390,13 @@
 	"Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Habilitar Mapeado de Memoria (mmap) para cargar datos del modelo. Esta opción permite al sistema usar el almacenamiento del disco como una extensión de la RAM al tratar los archivos en disco como si estuvieran en la RAM. Esto puede mejorar el rendimiento del modelo al permitir un acceso más rápido a los datos. Sin embargo, puede no funcionar correctamente con todos los sistemas y puede consumir una cantidad significativa de espacio en disco.",
 	"Enable Message Rating": "Habilitar Calificación de los Mensajes",
 	"Enable Mirostat sampling for controlling perplexity.": "Algoritmo de decodificación de texto neuronal que controla activamente el proceso generativo para mantener la perplejidad del texto generado en un valor deseado. Previene las trampas de aburrimiento (por excesivas repeticiones) y de incoherencia (por generación de excesivo texto).",
-	"Enable New Sign Ups": "Habilitar Registros de Nuev@s Usuari@s",
+	"Enable New Sign Ups": "Habilitar Registros de Nuevos Usuarios",
 	"Enabled": "Habilitado",
-	"Enforce Temporary Chat": "",
+	"Enforce Temporary Chat": "Forzar el uso de Chat Temporal",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Asegúrese de que su archivo CSV incluya 4 columnas en este orden: Nombre, Correo Electrónico, Contraseña, Rol.",
 	"Enter {{role}} message here": "Ingresar mensaje {{role}} aquí",
 	"Enter a detail about yourself for your LLMs to recall": "Ingresar detalles sobre ti para que los recuerden sus LLMs",
-	"Enter api auth string (e.g. username:password)": "Ingresar cadena de autorización de la api (p.ej. nombre:contraseña)",
+	"Enter api auth string (e.g. username:password)": "Ingresar campo de autorización de la api (p.ej. nombre:contraseña)",
 	"Enter Application DN": "Ingresar el DN de la Aplicación",
 	"Enter Application DN Password": "Ingresar la Contraseña del DN de la Aplicación",
 	"Enter Bing Search V7 Endpoint": "Ingresar el Endpoint de Bing Search V7",
@@ -414,8 +414,8 @@
 	"Enter Document Intelligence Key": "Ingresar Clave de Azure Document Intelligence",
 	"Enter domains separated by commas (e.g., example.com,site.org)": "Ingresar dominios separados por comas (p.ej., ejemplo.com,sitio.org)",
 	"Enter Exa API Key": "Ingresar Clave API de Exa",
-	"Enter Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "Ingresar URL Base del API de Firecrawl",
+	"Enter Firecrawl API Key": "Ingresar Clave del API de Firecrawl",
 	"Enter Github Raw URL": "Ingresar URL Github en Bruto(raw)",
 	"Enter Google PSE API Key": "Ingresar Clave API de Google PSE",
 	"Enter Google PSE Engine Id": "Ingresa ID del Motor PSE de Google",
@@ -433,8 +433,8 @@
 	"Enter Mojeek Search API Key": "Ingresar Clave API de Mojeek Search",
 	"Enter Number of Steps (e.g. 50)": "Ingresar Número de Pasos (p.ej., 50)",
 	"Enter Perplexity API Key": "Ingresar Clave API de Perplexity",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Playwright Timeout": "Ingresar límite de tiempo de espera de Playwright",
+	"Enter Playwright WebSocket URL": "Ingresar URL de WebSocket de Playwright",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "Ingresar URL del proxy (p.ej. https://user:password@host:port)",
 	"Enter reasoning effort": "Ingresar esfuerzo de razonamiento",
 	"Enter Sampler (e.g. Euler a)": "Ingresar Muestreador (p.ej., Euler a)",
@@ -452,16 +452,16 @@
 	"Enter server host": "Ingresar host del servidor",
 	"Enter server label": "Ingresar etiqueta del servidor",
 	"Enter server port": "Ingresar puerto del servidor",
-	"Enter Sougou Search API sID": "",
-	"Enter Sougou Search API SK": "",
+	"Enter Sougou Search API sID": "Ingresar Sougou Search API sID",
+	"Enter Sougou Search API SK": "Ingresar Sougou Search API SK",
 	"Enter stop sequence": "Ingresar secuencia de parada",
 	"Enter system prompt": "Ingresar Indicador del sistema",
 	"Enter system prompt here": "Ingresa aquí el indicador del sistema",
 	"Enter Tavily API Key": "Ingresar Clave API de Tavily",
-	"Enter Tavily Extract Depth": "",
-	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Ingresar URL pública de su WebUI. Esta URL se usará para generar enlaces en las notificaciones.",
+	"Enter Tavily Extract Depth": "Ingresar parámetro de Extract Depth de Taviliy",
+	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Ingresar URL pública de WebUI. Esta URL se usará para generar enlaces en las notificaciones.",
 	"Enter Tika Server URL": "Ingresar URL del servidor Tika",
-	"Enter timeout in seconds": "Ingresar timeout en segundos",
+	"Enter timeout in seconds": "Ingresar tiempo límite de espera en segundos",
 	"Enter to Send": "'Enter' para Enviar",
 	"Enter Top K": "Ingresar Top K",
 	"Enter Top K Reranker": "Ingresar Top K Reclasificador",
@@ -475,8 +475,8 @@
 	"Enter your new password": "Ingresa tu contraseña nueva",
 	"Enter Your Password": "Ingresa tu contraseña",
 	"Enter Your Role": "Ingresa tu rol",
-	"Enter Your Username": "Ingresa tu nombre de usuari@",
-	"Enter your webhook URL": "Ingresa tu URL de enganchesWeb(webhook)",
+	"Enter Your Username": "Ingresa tu nombre de usuario",
+	"Enter your webhook URL": "Ingresa tu URL de webhook",
 	"Error": "Error",
 	"ERROR": "ERROR",
 	"Error accessing Google Drive: {{error}}": "Error accediendo a Google Drive: {{error}}",
@@ -488,18 +488,18 @@
 	"Example: mail": "Ejemplo: correo",
 	"Example: ou=users,dc=foo,dc=example": "Ejemplo: ou=usuarios,dc=foo,dc=ejemplo",
 	"Example: sAMAccountName or uid or userPrincipalName": "Ejemplo: sAMNombreCuenta o uid o userNombrePrincipal",
-	"Exceeded the number of seats in your license. Please contact support to increase the number of seats.": "Excedido el número de accesos en su licencia. Por favor, contacte con soporte para aumentar el número de accesos.",
+	"Exceeded the number of seats in your license. Please contact support to increase the number of seats.": "Excedido el número de accesos de usuarios en tu licencia. Por favor, contacta con soporte para aumentar el número de accesos.",
 	"Exclude": "Excluir",
 	"Execute code for analysis": "Ejecutar código para análisis",
-	"Executing **{{NAME}}**...": "",
+	"Executing **{{NAME}}**...": "Ejecutando **{{NAME}}**...",
 	"Expand": "Expandir",
 	"Experimental": "Experimental",
 	"Explain": "Explicar",
-	"Explain this section to me in more detail": "Explicame esta sección con más detalle",
+	"Explain this section to me in more detail": "Explícame esta sección con más detalle",
 	"Explore the cosmos": "Explora el cosmos",
 	"Export": "Exportar",
 	"Export All Archived Chats": "Exportar Todos los Chats Archivados",
-	"Export All Chats (All Users)": "Exportar Todos los Chats (Todos l@s Usuari@s)",
+	"Export All Chats (All Users)": "Exportar Todos los Chats (Todos los Usuarios)",
 	"Export chat (.json)": "Exportar chat (.json)",
 	"Export Chats": "Exportar Chats",
 	"Export Config to JSON File": "Exportar Configuración a archivo JSON",
@@ -523,8 +523,8 @@
 	"Features": "Características",
 	"Features Permissions": "Permisos de las Características",
 	"February": "Febrero",
-	"Feedback History": "Historial de realimentación",
-	"Feedbacks": "Realimentaciones",
+	"Feedback History": "Historial de Opiniones",
+	"Feedbacks": "Opiniones",
 	"Feel free to add specific details": "Añade libremente detalles específicos",
 	"File": "Archivo",
 	"File added successfully.": "Archivo añadido correctamente.",
@@ -539,11 +539,11 @@
 	"Filter is now globally enabled": "El filtro ahora está habilitado globalmente",
 	"Filters": "Filtros",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Se detectó suplantación de huellas: No se pueden usar las iniciales como avatar. Se establece la imagen de perfil predeterminada.",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "URL Base de API de Firecrawl",
+	"Firecrawl API Key": "Clave de API de Firecrawl",
 	"Fluidly stream large external response chunks": "Transmisión fluida de fragmentos de grandes respuestas externas",
-	"Focus chat input": "Enfoque entrada del chat",
-	"Folder deleted successfully": "Carpeta bollada correctamente",
+	"Focus chat input": "Enfocar campo de chat",
+	"Folder deleted successfully": "Carpeta eliminada correctamente",
 	"Folder name cannot be empty": "El nombre de la carpeta no puede estar vacío",
 	"Folder name cannot be empty.": "El nombre de la carpeta no puede estar vacío",
 	"Folder name updated successfully": "Nombre de la carpeta actualizado correctamente",
@@ -719,7 +719,7 @@
 	"Memory updated successfully": "Memoria actualizada correctamente",
 	"Merge Responses": "Fusionar Respuestas",
 	"Message rating should be enabled to use this feature": "Para usar esta función debe estar habilitada la calificación de mensajes",
-	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de la creación del enlace no se compartirán. L@s usuari@s con la URL del enlace podrán ver el chat compartido.",
+	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de la creación del enlace no se compartirán. Los usuarios con la URL del enlace podrán ver el chat compartido.",
 	"Min P": "Min P",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
@@ -777,7 +777,7 @@
 	"No results found": "No se encontraron resultados",
 	"No search query generated": "No se generó ninguna consulta de búsqueda",
 	"No source available": "No hay fuente disponible",
-	"No users were found.": "No se encontraron usuari@s.",
+	"No users were found.": "No se encontraron usuarios.",
 	"No valves to update": "No hay válvulas para actualizar",
 	"None": "Ninguno",
 	"Not factually correct": "No es correcto en todos los aspectos",
@@ -804,7 +804,7 @@
 	"Only alphanumeric characters and hyphens are allowed": "Sólo están permitidos caracteres alfanuméricos y guiones",
 	"Only alphanumeric characters and hyphens are allowed in the command string.": "Sólo están permitidos en la cadena de comandos caracteres alfanuméricos y guiones.",
 	"Only collections can be edited, create a new knowledge base to edit/add documents.": "Solo se pueden editar las colecciones, para añadir/editar documentos hay que crear una nueva base de conocimientos",
-	"Only select users and groups with permission can access": "Solo pueden acceder l@s usuari@s y grupos con permiso",
+	"Only select users and groups with permission can access": "Solo pueden acceder los usuarios y grupos con permiso",
 	"Oops! Looks like the URL is invalid. Please double-check and try again.": "¡vaya! Parece que la URL es inválida. Por favor, revisala y reintenta de nuevo.",
 	"Oops! There are files still uploading. Please wait for the upload to complete.": "¡vaya! Todavía hay archivos subiendose. Por favor, espera a que se complete la subida.",
 	"Oops! There was an error in the previous response.": "¡vaya! Hubo un error en la respuesta previa.",
@@ -824,7 +824,7 @@
 	"OpenAI URL/Key required.": "URL/Clave de OpenAI requerida.",
 	"openapi.json Path": "Ruta a openapi.json",
 	"or": "o",
-	"Organize your users": "Organiza tus usuari@s",
+	"Organize your users": "Organiza tus usuarios",
 	"Other": "Otro",
 	"OUTPUT": "SALIDA",
 	"Output format": "Formato de salida",
@@ -851,8 +851,8 @@
 	"Pipelines Valves": "Válvulas de Tuberías",
 	"Plain text (.txt)": "Texto plano (.txt)",
 	"Playground": "Zona de Pruebas",
-	"Playwright Timeout (ms)": "",
-	"Playwright WebSocket URL": "",
+	"Playwright Timeout (ms)": "Tiempo Límite de Espera (ms) de Playwright",
+	"Playwright WebSocket URL": "URL de WebSocket de Playwright",
 	"Please carefully review the following warnings:": "Por favor revisar cuidadosamente los siguientes avisos:",
 	"Please do not close the settings page while loading the model.": "Por favor no cerrar la página de ajustes mientras se está descargando el modelo.",
 	"Please enter a prompt": "Por favor ingresar un indicador",
@@ -894,7 +894,7 @@
 	"Record voice": "Grabar voz",
 	"Redirecting you to Open WebUI Community": "Redireccionando a la Comunidad Open-WebUI",
 	"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.": "Reduce la probabilidad de generación sin sentido. Un valor más alto (p.ej. 100) dará respuestas más diversas, mientras que un valor más bajo (p.ej. 10) será más conservador.",
-	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referir a ti mismo como \"Usuari@\" (p.ej. \"Usuari@ está aprendiendo Español\")",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referir a ti mismo como \"Usuario\" (p.ej. \"Usuario está aprendiendo Español\")",
 	"References from": "Referencias desde",
 	"Refused when it shouldn't have": "Rechazado cuando no debería haberlo hecho",
 	"Regenerate": "Regenerar",
@@ -902,7 +902,7 @@
 	"Reindex Knowledge Base Vectors": "Reindexar Base Vectorial de Conocimiento",
 	"Release Notes": "Notas de la Versión",
 	"Relevance": "Relevancia",
-	"Relevance Threshold": "",
+	"Relevance Threshold": "Umbral de Relevancia",
 	"Remove": "Eliminar",
 	"Remove Model": "Eliminar Modelo",
 	"Rename": "Renombrar",
@@ -1020,7 +1020,7 @@
 	"Show": "Mostrar",
 	"Show \"What's New\" modal on login": "Mostrar modal \"Qué hay de Nuevo\" al iniciar sesión",
 	"Show Admin Details in Account Pending Overlay": "Mostrar Detalles Admin en la sobrecapa de 'Cuenta Pendiente'",
-	"Show Model": "",
+	"Show Model": "Mostrar Modelo",
 	"Show shortcuts": "Mostrar Atajos",
 	"Show your support!": "¡Muestra tu apoyo!",
 	"Showcased creativity": "Creatividad exhibida",
@@ -1061,7 +1061,7 @@
 	"Tap to interrupt": "Toca para interrumpir",
 	"Tasks": "Tareas",
 	"Tavily API Key": "Clave API de Tavily",
-	"Tavily Extract Depth": "",
+	"Tavily Extract Depth": "Parámetro Extract Depth de Taviliy",
 	"Tell us more:": "Dinos algo más:",
 	"Temperature": "Temperatura",
 	"Template": "Plantilla",
@@ -1069,14 +1069,14 @@
 	"Text Splitter": "Divisor de Texto",
 	"Text-to-Speech Engine": "Motor Texto a Voz(TTS)",
 	"Tfs Z": "TFS Z",
-	"Thanks for your feedback!": "¡Gracias por tu realimentación!",
+	"Thanks for your feedback!": "¡Gracias por tu comentario!",
 	"The Application Account DN you bind with for search": "Cuenta DN de la aplicación vinculada para búsqueda",
-	"The base to search for users": "La base para buscar usuari@s",
+	"The base to search for users": "Base para buscar usuarios",
 	"The batch size determines how many text requests are processed together at once. A higher batch size can increase the performance and speed of the model, but it also requires more memory.": "El tamaño de lote determina cuántas solicitudes de texto se procesan juntas de una vez. Un tamaño de lote más alto puede aumentar el rendimiento y la velocidad del modelo, pero también requiere más memoria.",
-	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "L@s desarrolladores de este complemento son apasionad@s voluntari@s de la comunidad. Si este complemento te es útil, por favor considera contribuir a su desarrollo.",
+	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Quienes desarollaron este complemento son apasionados voluntarios/as de la comunidad. Si este complemento te es útil, por favor considera contribuir a su desarrollo.",
 	"The evaluation leaderboard is based on the Elo rating system and is updated in real-time.": "La tabla clasificatoria de evaluación se basa en el sistema de clasificación Elo y se actualiza en tiempo real.",
-	"The LDAP attribute that maps to the mail that users use to sign in.": "El atributo LDAP que mapea el correo que l@s usuari@s utilizan para iniciar sesión.",
-	"The LDAP attribute that maps to the username that users use to sign in.": "El atributo LDAP que mapea el nombre de usuari@ que l@s usuari@s utilizan para iniciar sesión.",
+	"The LDAP attribute that maps to the mail that users use to sign in.": "El atributo LDAP que mapea el correo que los usuarios utilizan para iniciar sesión.",
+	"The LDAP attribute that maps to the username that users use to sign in.": "El atributo LDAP que mapea el nombre de usuario que los usuarios utilizan para iniciar sesión.",
 	"The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "La tabla clasificatoria está actualmente en beta, por lo que los cálculos de clasificación pueden reajustarse a medida que se refina el algoritmo.",
 	"The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "El tamaño máximo del archivo en MB. Si el tamaño del archivo supera este límite, el archivo no se subirá.",
 	"The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "El número máximo de archivos que se pueden utilizar a la vez en el chat. Si se supera este límite, los archivos no se subirán.",
@@ -1114,7 +1114,7 @@
 	"TLS": "TLS",
 	"To access the available model names for downloading,": "Para acceder a los nombres de modelos disponibles para descargar,",
 	"To access the GGUF models available for downloading,": "Para acceder a los modelos GGUF disponibles para descargar,",
-	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Para acceder a WebUI, por favor contacte con Admins. L@s administradores pueden gestionar los estados de l@s usuari@s esde el panel de administración.",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Para acceder a WebUI, por favor contacte con Admins. Los administradores pueden gestionar los estados de los usuarios esde el panel de administración.",
 	"To attach knowledge base here, add them to the \"Knowledge\" workspace first.": "Para adjuntar la base de conocimientos aquí, primero añadirla a \"Conocimiento\" en el área de trabajo.",
 	"To learn more about available endpoints, visit our documentation.": "Para aprender más sobre los endpoints disponibles, visite nuestra documentación.",
 	"To protect your privacy, only ratings, model IDs, tags, and metadata are shared from your feedback—your chat logs remain private and are not included.": "Para proteger tu privacidad, de tu realimentación solo se comparten las calificaciones, IDs de modelo, etiquetas y metadatos; tus chat registrados permanecen privados y no se incluyen.",
@@ -1182,18 +1182,18 @@
 	"URL Mode": "Modo URL",
 	"Use '#' in the prompt input to load and include your knowledge.": "Utilizar '#' en el indicador para cargar e incluir tu conocimiento.",
 	"Use Gravatar": "Usar Gravatar",
-	"Use groups to group your users and assign permissions.": "Usar grupos para agrupar a usuari@s y asignar permisos.",
+	"Use groups to group your users and assign permissions.": "Usar grupos para agrupar a usuarios y asignar permisos.",
 	"Use Initials": "Usar Iniciales",
 	"Use no proxy to fetch page contents.": "No usar proxy para extraer contenidos",
 	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Usar el proxy asignado en las variables del entorno http_proxy y/o https_proxy para extraer contenido",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
-	"user": "usuari@",
-	"User": "Usuari@",
-	"User location successfully retrieved.": "Ubicación de usuari@ obtenida correctamente.",
-	"User Webhooks": "Usuari@ EnganchesWeb(webhooks)",
-	"Username": "Nombre de Usuari@",
-	"Users": "Usuari@s",
+	"user": "usuario",
+	"User": "Usuario",
+	"User location successfully retrieved.": "Ubicación de usuario obtenida correctamente.",
+	"User Webhooks": "Usuario Webhooks",
+	"Username": "Nombre de Usuario",
+	"Users": "Usuarios",
 	"Using the default arena model with all models. Click the plus button to add custom models.": "Usando el modelo de arena predeterminado con todos los modelos. Pulsar en el botón + para agregar modelos personalizados.",
 	"Utilize": "Utilizar",
 	"Valid time units:": "Unidades de tiempo válidas:",
@@ -1213,7 +1213,7 @@
 	"Voice Input": "Entrada de Voz",
 	"Warning": "Aviso",
 	"Warning:": "Aviso:",
-	"Warning: Enabling this will allow users to upload arbitrary code on the server.": "Aviso: Habilitar esto permitirá a l@s usuari@s subir código arbitrario al servidor.",
+	"Warning: Enabling this will allow users to upload arbitrary code on the server.": "Aviso: Habilitar esto permitirá a los usuarios subir código arbitrario al servidor.",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Aviso: Si actualizas o cambias el modelo de incrustacción, necesitarás re-importar todos los documentos.",
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "Aviso: La ejecución Jupyter habilita la ejecución de código arbitrario, planteando graves riesgos de seguridad; Proceder con extrema precaución.",
 	"Web": "Web",

Разлика између датотеке није приказан због своје велике величине
+ 565 - 565
src/lib/i18n/locales/fa-IR/translation.json


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

@@ -57,17 +57,17 @@
 	"All": "Kaikki",
 	"All Documents": "Kaikki asiakirjat",
 	"All models deleted successfully": "Kaikki mallit poistettu onnistuneesti",
-	"Allow Call": "",
+	"Allow Call": "Salli puhelut",
 	"Allow Chat Controls": "Salli keskustelujen hallinta",
 	"Allow Chat Delete": "Salli keskustelujen poisto",
 	"Allow Chat Deletion": "Salli keskustelujen poisto",
 	"Allow Chat Edit": "Salli keskustelujen muokkaus",
 	"Allow File Upload": "Salli tiedostojen lataus",
-	"Allow Multiple Models in Chat": "",
+	"Allow Multiple Models in Chat": "Salli useampi malli keskustelussa",
 	"Allow non-local voices": "Salli ei-paikalliset äänet",
-	"Allow Speech to Text": "",
+	"Allow Speech to Text": "Salli puhe tekstiksi",
 	"Allow Temporary Chat": "Salli väliaikaiset keskustelut",
-	"Allow Text to Speech": "",
+	"Allow Text to Speech": "Salli teksti puheeksi",
 	"Allow User Location": "Salli käyttäjän sijainti",
 	"Allow Voice Interruption in Call": "Salli äänen keskeytys puhelussa",
 	"Allowed Endpoints": "Hyväksytyt päätepisteet",
@@ -83,7 +83,7 @@
 	"and": "ja",
 	"and {{COUNT}} more": "ja {{COUNT}} muuta",
 	"and create a new shared link.": "ja luo uusi jaettu linkki.",
-	"Android": "",
+	"Android": "Android",
 	"API Base URL": "API:n verkko-osoite",
 	"API Key": "API-avain",
 	"API Key created.": "API-avain luotu.",
@@ -116,7 +116,7 @@
 	"Auth": "Todennus",
 	"Authenticate": "Todentaa",
 	"Authentication": "Todennus",
-	"Auto": "",
+	"Auto": "Automaattinen",
 	"Auto-Copy Response to Clipboard": "Kopioi vastaus automaattisesti leikepöydälle",
 	"Auto-playback response": "Soita vastaus automaattisesti",
 	"Autocomplete Generation": "Automaattisen täydennyksen luonti",
@@ -157,7 +157,7 @@
 	"Change Password": "Vaihda salasana",
 	"Channel Name": "Kanavan nimi",
 	"Channels": "Kanavat",
-	"Character": "Hahmo",
+	"Character": "Kirjain",
 	"Character limit for autocomplete generation input": "Automaattisen täydennyksen syötteen merkkiraja",
 	"Chart new frontiers": "Kartoita uusia rajapintoja",
 	"Chat": "Keskustelu",
@@ -224,10 +224,10 @@
 	"Confirm your new password": "Vahvista uusi salasanasi",
 	"Connect to your own OpenAI compatible API endpoints.": "Yhdistä omat OpenAI yhteensopivat API päätepisteet.",
 	"Connect to your own OpenAPI compatible external tool servers.": "Yhdistä omat ulkopuoliset OpenAPI yhteensopivat työkalu palvelimet.",
-	"Connection failed": "",
-	"Connection successful": "",
+	"Connection failed": "Yhteys epäonnistui",
+	"Connection successful": "Yhteys onnistui",
 	"Connections": "Yhteydet",
-	"Connections saved successfully": "",
+	"Connections saved successfully": "Yhteyksien tallentaminen onnistui",
 	"Constrains effort on reasoning for reasoning models. Only applicable to reasoning models from specific providers that support reasoning effort.": "",
 	"Contact Admin for WebUI Access": "Ota yhteyttä ylläpitäjään WebUI-käyttöä varten",
 	"Content": "Sisältö",
@@ -245,7 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Jaettu keskustelulinkki kopioitu leikepöydälle!",
 	"Copied to clipboard": "Kopioitu leikepöydälle",
 	"Copy": "Kopioi",
-	"Copy Formatted Text": "",
+	"Copy Formatted Text": "Kopioi muotoiltu teksti",
 	"Copy last code block": "Kopioi viimeisin koodilohko",
 	"Copy last response": "Kopioi viimeisin vastaus",
 	"Copy Link": "Kopioi linkki",
@@ -308,7 +308,7 @@
 	"Deleted User": "Käyttäjä poistettu",
 	"Describe your knowledge base and objectives": "Kuvaa tietokantasi ja tavoitteesi",
 	"Description": "Kuvaus",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "Tunnista artefaktit automaattisesti",
 	"Didn't fully follow instructions": "Ei noudattanut ohjeita täysin",
 	"Direct": "Suora",
 	"Direct Connections": "Suorat yhteydet",
@@ -364,7 +364,7 @@
 	"e.g. my_filter": "esim. oma_suodatin",
 	"e.g. my_tools": "esim. omat_työkalut",
 	"e.g. Tools for performing various operations": "esim. työkaluja erilaisten toimenpiteiden suorittamiseen",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "esim. en-US,ja-JP (Tyhjäksi jättämällä, automaattinen tunnistus)",
 	"Edit": "Muokkaa",
 	"Edit Arena Model": "Muokkaa Arena-mallia",
 	"Edit Channel": "Muokkaa kanavaa",
@@ -407,15 +407,15 @@
 	"Enter CFG Scale (e.g. 7.0)": "Kirjoita CFG-mitta (esim. 7.0)",
 	"Enter Chunk Overlap": "Syötä osien päällekkäisyys",
 	"Enter Chunk Size": "Syötä osien koko",
-	"Enter comma-seperated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "",
+	"Enter comma-seperated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Syötä pilkulla erottaen \"token:bias_value\" parit (esim. 5432:100, 413:-100)",
 	"Enter description": "Kirjoita kuvaus",
 	"Enter Docling Server URL": "Kirjoita Docling palvelimen verkko-osoite",
 	"Enter Document Intelligence Endpoint": "Kirjoita asiakirja tiedustelun päätepiste",
 	"Enter Document Intelligence Key": "Kirjoiuta asiakirja tiedustelun avain",
 	"Enter domains separated by commas (e.g., example.com,site.org)": "Verkko-osoitteet erotetaan pilkulla (esim. esimerkki.com,sivu.org)",
 	"Enter Exa API Key": "Kirjoita Exa API -avain",
-	"Enter Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "Kirjoita Firecrawl API -verkko-osoite",
+	"Enter Firecrawl API Key": "Kirjoita Firecrawl API-avain",
 	"Enter Github Raw URL": "Kirjoita Github Raw -verkko-osoite",
 	"Enter Google PSE API Key": "Kirjoita Google PSE API -avain",
 	"Enter Google PSE Engine Id": "Kirjoita Google PSE -moottorin tunnus",
@@ -433,8 +433,8 @@
 	"Enter Mojeek Search API Key": "Kirjoita Mojeek Search API -avain",
 	"Enter Number of Steps (e.g. 50)": "Kirjoita askelten määrä (esim. 50)",
 	"Enter Perplexity API Key": "Aseta Perplexity API-avain",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Playwright Timeout": "Aseta Playwright aikakatkaisu",
+	"Enter Playwright WebSocket URL": "Aseta Playwright WebSocket-aikakatkaisu",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "Kirjoita välityspalvelimen verkko-osoite (esim. https://käyttäjä:salasana@host:portti)",
 	"Enter reasoning effort": "",
 	"Enter Sampler (e.g. Euler a)": "Kirjoita näytteistäjä (esim. Euler a)",
@@ -516,7 +516,7 @@
 	"Failed to create API Key.": "API-avaimen luonti epäonnistui.",
 	"Failed to fetch models": "Mallien hakeminen epäonnistui",
 	"Failed to read clipboard contents": "Leikepöydän sisällön lukeminen epäonnistui",
-	"Failed to save connections": "",
+	"Failed to save connections": "Yhteyksien tallentaminen epäonnistui",
 	"Failed to save models configuration": "Mallien määrityksen tallentaminen epäonnistui",
 	"Failed to update settings": "Asetusten päivittäminen epäonnistui",
 	"Failed to upload file.": "Tiedoston lataaminen epäonnistui.",
@@ -539,8 +539,8 @@
 	"Filter is now globally enabled": "Suodatin on nyt otettu käyttöön globaalisti",
 	"Filters": "Suodattimet",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Sormenjäljen väärentäminen havaittu: Alkukirjaimia ei voi käyttää avatarina. Käytetään oletusprofiilikuvaa.",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "Firecrawl API -verkko-osoite",
+	"Firecrawl API Key": "Firecrawl API-avain",
 	"Fluidly stream large external response chunks": "Virtaa suuria ulkoisia vastausosia joustavasti",
 	"Focus chat input": "Fokusoi syöttökenttään",
 	"Folder deleted successfully": "Kansio poistettu onnistuneesti",
@@ -605,8 +605,8 @@
 	"Hybrid Search": "Hybridihaku",
 	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Vahvistan, että olen lukenut ja ymmärrän toimintani seuraukset. Olen tietoinen mielivaltaisen koodin suorittamiseen liittyvistä riskeistä ja olen varmistanut lähteen luotettavuuden.",
 	"ID": "Tunnus",
-	"iframe Sandbox Allow Forms": "",
-	"iframe Sandbox Allow Same Origin": "",
+	"iframe Sandbox Allow Forms": "Salli lomakkeet iframe hiekkalaatikossa",
+	"iframe Sandbox Allow Same Origin": "Salli iframe hiekkalaatikko samasta alkuperästä",
 	"Ignite curiosity": "Sytytä uteliaisuus",
 	"Image": "Kuva",
 	"Image Compression": "Kuvan pakkaus",
@@ -667,14 +667,14 @@
 	"Label": "Tunniste",
 	"Landing Page Mode": "Etusivun tila",
 	"Language": "Kieli",
-	"Language Locales": "",
+	"Language Locales": "Kielialueet",
 	"Last Active": "Viimeksi aktiivinen",
 	"Last Modified": "Viimeksi muokattu",
 	"Last reply": "Viimeksi vastattu",
 	"LDAP": "LDAP",
 	"LDAP server updated": "LDAP-palvelin päivitetty",
 	"Leaderboard": "Tulosluettelo",
-	"Learn more about OpenAPI tool servers.": "",
+	"Learn more about OpenAPI tool servers.": "Lue lisää OpenAPI työkalu palvelimista.",
 	"Leave empty for unlimited": "Rajaton tyhjäksi jättämällä",
 	"Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "Jätä tyhjäksi sisällyttääksesi \"{{url}}/api/tags\" päätepisteen mallit",
 	"Leave empty to include all models from \"{{url}}/models\" endpoint": "Jätä tyhjäksi sisällyttääksesi \"{{url}}/models\" päätepisteen mallit",
@@ -812,7 +812,7 @@
 	"Open file": "Avaa tiedosto",
 	"Open in full screen": "Avaa koko näytön tilaan",
 	"Open new chat": "Avaa uusi keskustelu",
-	"Open WebUI can use tools provided by any OpenAPI server.": "",
+	"Open WebUI can use tools provided by any OpenAPI server.": "Open WebUI voi käyttää minkä tahansa OpenAPI-palvelimen tarjoamia työkaluja.",
 	"Open WebUI uses faster-whisper internally.": "Open WebUI käyttää faster-whisperia sisäisesti.",
 	"Open WebUI uses SpeechT5 and CMU Arctic speaker embeddings.": "Open WebUI käyttää SpeechT5:tä ja CMU Arctic -kaiuttimen upotuksia.",
 	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "Open WebUI -versio (v{{OPEN_WEBUI_VERSION}}) on alempi kuin vaadittu versio (v{{REQUIRED_VERSION}})",
@@ -851,13 +851,13 @@
 	"Pipelines Valves": "Putkistojen venttiilit",
 	"Plain text (.txt)": "Pelkkä teksti (.txt)",
 	"Playground": "Leikkipaikka",
-	"Playwright Timeout (ms)": "",
-	"Playwright WebSocket URL": "",
+	"Playwright Timeout (ms)": "Playwright aikakatkaisu (ms)",
+	"Playwright WebSocket URL": "Playwright WebSocket verkko-osoite",
 	"Please carefully review the following warnings:": "Tarkista huolellisesti seuraavat varoitukset:",
 	"Please do not close the settings page while loading the model.": "Älä sulje asetussivua mallin latautuessa.",
 	"Please enter a prompt": "Kirjoita kehote",
-	"Please enter a valid path": "",
-	"Please enter a valid URL": "",
+	"Please enter a valid path": "Kirjoita kelvollinen polku",
+	"Please enter a valid URL": "Kirjoita kelvollinen verkko-osoite",
 	"Please fill in all fields.": "Täytä kaikki kentät.",
 	"Please select a model first.": "Valitse ensin malli.",
 	"Please select a model.": "Valitse malli.",
@@ -885,7 +885,7 @@
 	"Pull \"{{searchValue}}\" from Ollama.com": "Lataa \"{{searchValue}}\" Ollama.comista",
 	"Pull a model from Ollama.com": "Lataa malli Ollama.comista",
 	"Query Generation Prompt": "Kyselytulosten luontikehote",
-	"RAG Template": "RAG-malline",
+	"RAG Template": "RAG-kehote",
 	"Rating": "Arviointi",
 	"Re-rank models by topic similarity": "Uudelleenjärjestä mallit aiheyhteyden mukaan",
 	"Read": "Lue",
@@ -898,11 +898,11 @@
 	"References from": "Viitteet lähteistä",
 	"Refused when it shouldn't have": "Kieltäytyi, vaikka ei olisi pitänyt",
 	"Regenerate": "Uudelleentuota",
-	"Reindex": "",
-	"Reindex Knowledge Base Vectors": "",
+	"Reindex": "Indeksoi uudelleen",
+	"Reindex Knowledge Base Vectors": "Indeksoi tietämyksen vektorit uudelleen",
 	"Release Notes": "Julkaisutiedot",
 	"Relevance": "Relevanssi",
-	"Relevance Threshold": "",
+	"Relevance Threshold": "Relevanssikynnys",
 	"Remove": "Poista",
 	"Remove Model": "Poista malli",
 	"Rename": "Nimeä uudelleen",
@@ -1085,7 +1085,7 @@
 	"Theme": "Teema",
 	"Thinking...": "Ajattelee...",
 	"This action cannot be undone. Do you wish to continue?": "Tätä toimintoa ei voi peruuttaa. Haluatko jatkaa?",
-	"This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "",
+	"This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "Tämä kanava on luotiin {{createdAt}}. Tämä on {{channelName}} kanavan alku.",
 	"This chat won’t appear in history and your messages will not be saved.": "Tämä keskustelu ei näy historiassa, eikä viestejäsi tallenneta.",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Tämä varmistaa, että arvokkaat keskustelusi tallennetaan turvallisesti backend-tietokantaasi. Kiitos!",
 	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Tämä on kokeellinen ominaisuus, se ei välttämättä toimi odotetulla tavalla ja se voi muuttua milloin tahansa.",
@@ -1144,7 +1144,7 @@
 	"Tools have a function calling system that allows arbitrary code execution.": "Työkalut sallivat mielivaltaisen koodin suorittamisen toimintokutsuilla.",
 	"Tools Public Sharing": "Työkalujen julkinen jakaminen",
 	"Top K": "Top K",
-	"Top K Reranker": "",
+	"Top K Reranker": "Top K uudelleen sijoittaja",
 	"Top P": "Top P",
 	"Transformers": "Muunnokset",
 	"Trouble accessing Ollama?": "Ongelmia Ollama-yhteydessä?",
@@ -1170,7 +1170,7 @@
 	"Updated": "Päivitetty",
 	"Updated at": "Päivitetty",
 	"Updated At": "Päivitetty",
-	"Upgrade to a licensed plan for enhanced capabilities, including custom theming and branding, and dedicated support.": "",
+	"Upgrade to a licensed plan for enhanced capabilities, including custom theming and branding, and dedicated support.": "Päivitä lisenssi saadaksesi parempia ominaisuuksia, mukaan lukien mukautetun teeman ja brändäyksen sekä yksilöllistä tukea.",
 	"Upload": "Lataa",
 	"Upload a GGUF model": "Lataa GGUF-malli",
 	"Upload directory": "Latauksen hakemisto",
@@ -1184,8 +1184,8 @@
 	"Use Gravatar": "Käytä Gravataria",
 	"Use groups to group your users and assign permissions.": "Käytä ryhmiä jäsentääksesi käyttäjiä ja antaaksesi käyttöoikeuksia.",
 	"Use Initials": "Käytä alkukirjaimia",
-	"Use no proxy to fetch page contents.": "",
-	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "",
+	"Use no proxy to fetch page contents.": "Älä käytä välityspalvelinta sivun tietoja haettaessa.",
+	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Käytä http_proxy- ja https_proxy-ympäristömuuttujien määrittämää välityspalvelinta sivun sisällön hakemiseen.",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "käyttäjä",
@@ -1203,7 +1203,7 @@
 	"variable": "muuttuja",
 	"variable to have them replaced with clipboard content.": "muuttuja korvataan leikepöydän sisällöllä.",
 	"Verify Connection": "Tarkista yhteys",
-	"Verify SSL Certificate": "",
+	"Verify SSL Certificate": "Tarkista SSL-varmenne",
 	"Version": "Versio",
 	"Version {{selectedVersion}} of {{totalVersions}}": "Versio {{selectedVersion}} / {{totalVersions}}",
 	"View Replies": "Näytä vastaukset",
@@ -1218,7 +1218,7 @@
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "Varoitus: Jupyter käyttö voi mahdollistaa mielivaltaiseen koodin suorittamiseen, mikä voi aiheuttaa tietoturvariskejä - käytä äärimmäisen varoen.",
 	"Web": "Web",
 	"Web API": "Web-API",
-	"Web Loader Engine": "",
+	"Web Loader Engine": "Verkko lataaja moottori",
 	"Web Search": "Verkkohaku",
 	"Web Search Engine": "Hakukoneet",
 	"Web Search in Chat": "Verkkohaku keskustelussa",
@@ -1248,7 +1248,7 @@
 	"Write your model template content here": "Kirjoita mallisi mallinnesisältö tähän",
 	"Yesterday": "Eilen",
 	"You": "Sinä",
-	"You are currently using a trial license. Please contact support to upgrade your license.": "",
+	"You are currently using a trial license. Please contact support to upgrade your license.": "Käytät tällä hetkellä kokeiluversiota. Ota yhteyttä tukeen lisenssin päivittämiseksi.",
 	"You can only chat with a maximum of {{maxCount}} file(s) at a time.": "Voit keskustella enintään {{maxCount}} tiedoston kanssa kerralla.",
 	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Voit personoida vuorovaikutustasi LLM-ohjelmien kanssa lisäämällä muistoja 'Hallitse'-painikkeen kautta, jolloin ne ovat hyödyllisempiä ja räätälöityjä sinua varten.",
 	"You cannot upload an empty file.": "Et voi ladata tyhjää tiedostoa.",

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

@@ -4,10 +4,10 @@
 	"(e.g. `sh webui.sh --api --api-auth username_password`)": "(m.sh. `sh webui.sh --api --api-auth username_password `)",
 	"(e.g. `sh webui.sh --api`)": "(m.sh. `sh webui.sh --api`)",
 	"(latest)": "(is déanaí)",
-	"(Ollama)": "",
+	"(Ollama)": "(Ollama)",
 	"{{ models }}": "{{ models }}",
-	"{{COUNT}} Available Tools": "",
-	"{{COUNT}} hidden lines": "",
+	"{{COUNT}} Available Tools": "{{COUNT}} Uirlisí ar Fáil",
+	"{{COUNT}} hidden lines": "{{COUNT}} línte folaithe",
 	"{{COUNT}} Replies": "{{COUNT}} Freagra",
 	"{{user}}'s Chats": "Comhráite {{user}}",
 	"{{webUIName}} Backend Required": "{{webUIName}} Ceoldeireadh Riachtanach",
@@ -54,28 +54,28 @@
 	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Tá rochtain ag riarthóirí ar gach uirlis i gcónaí; teastaíonn ó úsáideoirí uirlisí a shanntar in aghaidh an mhúnla sa spás oibre.",
 	"Advanced Parameters": "Paraiméadair Casta",
 	"Advanced Params": "Paraiméid Casta",
-	"All": "",
+	"All": "Gach",
 	"All Documents": "Gach Doiciméad",
 	"All models deleted successfully": "Scriosadh na múnlaí go léir go rathúil",
-	"Allow Call": "",
+	"Allow Call": "Ceadaigh Glao",
 	"Allow Chat Controls": "Ceadaigh Rialuithe Comhrá",
 	"Allow Chat Delete": "Ceadaigh Comhrá a Scriosadh",
 	"Allow Chat Deletion": "Cead Scriosadh Comhrá",
 	"Allow Chat Edit": "Ceadaigh Eagarthóireacht Comhrá",
 	"Allow File Upload": "Ceadaigh Uaslódáil Comhad",
-	"Allow Multiple Models in Chat": "",
+	"Allow Multiple Models in Chat": "Ceadaigh Múnlaí Il sa Chomhrá",
 	"Allow non-local voices": "Lig guthanna neamh-áitiúla",
-	"Allow Speech to Text": "",
+	"Allow Speech to Text": "Ceadaigh Óráid go Téacs",
 	"Allow Temporary Chat": "Cead Comhrá Sealadach",
-	"Allow Text to Speech": "",
+	"Allow Text to Speech": "Ceadaigh Téacs a Chaint",
 	"Allow User Location": "Ceadaigh Suíomh Úsáideora",
 	"Allow Voice Interruption in Call": "Ceadaigh Briseadh Guth i nGlao",
 	"Allowed Endpoints": "Críochphointí Ceadaithe",
 	"Already have an account?": "Tá cuntas agat cheana féin?",
-	"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.": "",
+	"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.": "Rogha eile seachas an top_p, agus tá sé mar aidhm aige cothromaíocht cáilíochta agus éagsúlachta a chinntiú. Léiríonn an paraiméadar p an dóchúlacht íosta go mbreithneofar comhartha, i gcoibhneas le dóchúlacht an chomhartha is dóichí. Mar shampla, le p=0.05 agus dóchúlacht 0.9 ag an comhartha is dóichí, déantar logits le luach níos lú ná 0.045 a scagadh amach.",
 	"Always": "I gcónaí",
-	"Always Collapse Code Blocks": "",
-	"Always Expand Details": "",
+	"Always Collapse Code Blocks": "Laghdaigh Bloic Chóid i gcónaí",
+	"Always Expand Details": "Leathnaigh Sonraí i gcónaí",
 	"Amazing": "Iontach",
 	"an assistant": "cúntóir",
 	"Analyzed": "Anailísithe",
@@ -83,7 +83,7 @@
 	"and": "agus",
 	"and {{COUNT}} more": "agus {{COUNT}} eile",
 	"and create a new shared link.": "agus cruthaigh nasc nua roinnte.",
-	"Android": "",
+	"Android": "Android",
 	"API Base URL": "URL Bonn API",
 	"API Key": "Eochair API",
 	"API Key created.": "Cruthaíodh Eochair API.",
@@ -104,7 +104,7 @@
 	"Are you sure?": "An bhfuil tú cinnte?",
 	"Arena Models": "Múnlaí Airéine",
 	"Artifacts": "Déantáin",
-	"Ask": "",
+	"Ask": "Fiafraigh",
 	"Ask a question": "Cuir ceist",
 	"Assistant": "Cúntóir",
 	"Attach file from knowledge": "Ceangail comhad ó eolas",
@@ -113,10 +113,10 @@
 	"Attribute for Username": "Tréith don Ainm Úsáideora",
 	"Audio": "Fuaim",
 	"August": "Lúnasa",
-	"Auth": "",
+	"Auth": "Údarú",
 	"Authenticate": "Fíordheimhnigh",
 	"Authentication": "Fíordheimhniú",
-	"Auto": "",
+	"Auto": "Uath",
 	"Auto-Copy Response to Clipboard": "Freagra AutoCopy go Gearrthaisce",
 	"Auto-playback response": "Freagra uathsheinm",
 	"Autocomplete Generation": "Giniúint Uathchríochnaithe",
@@ -126,7 +126,7 @@
 	"AUTOMATIC1111 Base URL": "UATHOIBRÍOCH1111 Bun URL",
 	"AUTOMATIC1111 Base URL is required.": "Tá URL bonn UATHOIBRÍOCH1111 ag teastáil.",
 	"Available list": "Liosta atá ar fáil",
-	"Available Tools": "",
+	"Available Tools": "Uirlisí ar Fáil",
 	"available!": "ar fáil!",
 	"Awful": "Uafásach",
 	"Azure AI Speech": "Óráid Azure AI",
@@ -142,7 +142,7 @@
 	"Bing Search V7 Endpoint": "Cuardach Bing V7 Críochphointe",
 	"Bing Search V7 Subscription Key": "Eochair Síntiúis Bing Cuardach V7",
 	"Bocha Search API Key": "Eochair API Cuardach Bocha",
-	"Boosting or penalizing specific tokens for constrained responses. Bias values will be clamped between -100 and 100 (inclusive). (Default: none)": "",
+	"Boosting or penalizing specific tokens for constrained responses. Bias values will be clamped between -100 and 100 (inclusive). (Default: none)": "Treisiú nó pionós a ghearradh ar chomharthaí sonracha as freagraí srianta. Déanfar luachanna laofachta a chlampáil idir -100 agus 100 (san áireamh). (Réamhshocrú: ceann ar bith)",
 	"Brave Search API Key": "Eochair API Cuardaigh Brave",
 	"By {{name}}": "Le {{name}}",
 	"Bypass Embedding and Retrieval": "Seachbhóthar Leabú agus Aisghabháil",
@@ -205,7 +205,7 @@
 	"Code Interpreter": "Ateangaire Cód",
 	"Code Interpreter Engine": "Inneall Ateangaire Cóid",
 	"Code Interpreter Prompt Template": "Teimpléad Pras Ateangaire Cód",
-	"Collapse": "",
+	"Collapse": "Laghdaigh",
 	"Collection": "Bailiúchán",
 	"Color": "Dath",
 	"ComfyUI": "ComfyUI",
@@ -223,12 +223,12 @@
 	"Confirm your action": "Deimhnigh do ghníomh",
 	"Confirm your new password": "Deimhnigh do phasfhocal nua",
 	"Connect to your own OpenAI compatible API endpoints.": "Ceangail le do chríochphointí API atá comhoiriúnach le OpenAI.",
-	"Connect to your own OpenAPI compatible external tool servers.": "",
-	"Connection failed": "",
-	"Connection successful": "",
+	"Connect to your own OpenAPI compatible external tool servers.": "Ceangail le do fhreastalaithe uirlisí seachtracha atá comhoiriúnach le OpenAPI.",
+	"Connection failed": "Theip ar an gceangal",
+	"Connection successful": "Ceangal rathúil",
 	"Connections": "Naisc",
-	"Connections saved successfully": "",
-	"Constrains effort on reasoning for reasoning models. Only applicable to reasoning models from specific providers that support reasoning effort.": "",
+	"Connections saved successfully": "D'éirigh le naisc a shábháil",
+	"Constrains effort on reasoning for reasoning models. Only applicable to reasoning models from specific providers that support reasoning effort.": "Srianann iarracht ar réasúnaíocht a dhéanamh ar shamhlacha réasúnaíochta. Ní bhaineann ach le samhlacha réasúnaíochta ó sholáthraithe sonracha a thacaíonn le hiarracht réasúnaíochta.",
 	"Contact Admin for WebUI Access": "Déan teagmháil le Riarachán le haghaidh Rochtana WebUI",
 	"Content": "Ábhar",
 	"Content Extraction Engine": "Inneall Eastóscadh Ábhar",
@@ -240,12 +240,12 @@
 	"Control how message text is split for TTS requests. 'Punctuation' splits into sentences, 'paragraphs' splits into paragraphs, and 'none' keeps the message as a single string.": "Rialú conas a roinntear téacs teachtaireachta d'iarratais TTS. Roinneann 'poncaíocht' ina abairtí, scoilteann 'míreanna' i míreanna, agus coinníonn 'aon' an teachtaireacht mar shreang amháin.",
 	"Control the repetition of token sequences in the generated text. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 1.1) will be more lenient. At 1, it is disabled.": "Rialú a dhéanamh ar athrá seichimh chomharthaí sa téacs ginte. Cuirfidh luach níos airde (m.sh., 1.5) pionós níos láidre ar athrá, agus beidh luach níos ísle (m.sh., 1.1) níos boige. Ag 1, tá sé díchumasaithe. (Réamhshocrú: 1.1)",
 	"Controls": "Rialuithe",
-	"Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text.": "",
+	"Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text.": "Rialaíonn sé an chothromaíocht idir comhleanúnachas agus éagsúlacht an aschuir. Beidh téacs níos dírithe agus níos soiléire mar thoradh ar luach níos ísle.",
 	"Copied": "Cóipeáladh",
 	"Copied shared chat URL to clipboard!": "Cóipeáladh URL an chomhrá roinnte chuig an ngearrthaisce!",
 	"Copied to clipboard": "Cóipeáilte go gear",
 	"Copy": "Cóipeáil",
-	"Copy Formatted Text": "",
+	"Copy Formatted Text": "Cóipeáil Téacs Formáidithe",
 	"Copy last code block": "Cóipeáil bloc cód deireanach",
 	"Copy last response": "Cóipeáil an fhreagairt",
 	"Copy Link": "Cóipeáil Nasc",
@@ -266,7 +266,7 @@
 	"Created At": "Cruthaithe Ag",
 	"Created by": "Cruthaithe ag",
 	"CSV Import": "Iompórtáil CSV",
-	"Ctrl+Enter to Send": "",
+	"Ctrl+Enter to Send": "Ctrl+Iontráil chun Seol",
 	"Current Model": "Múnla Reatha",
 	"Current Password": "Pasfhocal Reatha",
 	"Custom": "Saincheaptha",
@@ -286,7 +286,7 @@
 	"Default Prompt Suggestions": "Moltaí Leid Réamhshocraithe",
 	"Default to 389 or 636 if TLS is enabled": "Réamhshocrú go 389 nó 636 má tá TLS cumasaithe",
 	"Default to ALL": "Réamhshocrú do GACH",
-	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "",
+	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Réamhshocrú maidir le haisghabháil deighilte d’eastóscadh ábhar dírithe agus ábhartha, moltar é seo i bhformhór na gcásanna.",
 	"Default User Role": "Ról Úsáideora Réamhshocraithe",
 	"Delete": "Scrios",
 	"Delete a model": "Scrios múnla",
@@ -308,13 +308,13 @@
 	"Deleted User": "Úsáideoir Scriosta",
 	"Describe your knowledge base and objectives": "Déan cur síos ar do bhunachar eolais agus do chuspóirí",
 	"Description": "Cur síos",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "Déan Déantáin a bhrath go huathoibríoch",
 	"Didn't fully follow instructions": "Níor lean sé treoracha go hiomlán",
-	"Direct": "",
+	"Direct": "Díreach",
 	"Direct Connections": "Naisc Dhíreacha",
 	"Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Ligeann Connections Direct d’úsáideoirí ceangal lena gcríochphointí API féin atá comhoiriúnach le OpenAI.",
 	"Direct Connections settings updated": "Nuashonraíodh socruithe Connections Direct",
-	"Direct Tool Servers": "",
+	"Direct Tool Servers": "Freastalaithe Uirlisí Díreacha",
 	"Disabled": "Díchumasaithe",
 	"Discover a function": "Faigh amach feidhm",
 	"Discover a model": "Faigh amach múnla",
@@ -334,8 +334,8 @@
 	"Dive into knowledge": "Léim isteach eolas",
 	"Do not install functions from sources you do not fully trust.": "Ná suiteáil feidhmeanna ó fhoinsí nach bhfuil muinín iomlán agat.",
 	"Do not install tools from sources you do not fully trust.": "Ná suiteáil uirlisí ó fhoinsí nach bhfuil muinín iomlán agat.",
-	"Docling": "",
-	"Docling Server URL required.": "",
+	"Docling": "Docling",
+	"Docling Server URL required.": "URL Freastalaí Doling ag teastáil.",
 	"Document": "Doiciméad",
 	"Document Intelligence": "Faisnéise Doiciméad",
 	"Document Intelligence endpoint and key required.": "Críochphointe Faisnéise Doiciméad agus eochair ag teastáil.",
@@ -356,15 +356,15 @@
 	"Draw": "Tarraing",
 	"Drop any files here to add to the conversation": "Scaoil aon chomhaid anseo le cur leis an gcomhrá",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "m.sh. '30s', '10m'. Is iad aonaid ama bailí ná 's', 'm', 'h'.",
-	"e.g. \"json\" or a JSON schema": "",
+	"e.g. \"json\" or a JSON schema": "m.sh. \"json\" nó scéimre JSON",
 	"e.g. 60": "m.sh. 60",
 	"e.g. A filter to remove profanity from text": "m.h. Scagaire chun profanity a bhaint as téacs",
 	"e.g. My Filter": "m.sh. Mo Scagaire",
-	"e.g. My Tools": "e.g. Mo Uirlisí",
+	"e.g. My Tools": "m.sh. Mo Uirlisí",
 	"e.g. my_filter": "m.sh. mo_scagaire",
 	"e.g. my_tools": "m.sh. mo_uirlisí",
 	"e.g. Tools for performing various operations": "m.sh. Uirlisí chun oibríochtaí éagsúla a dhéanamh",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "m.sh., en-US, ja-JP (fág bán le haghaidh uathbhraite)",
 	"Edit": "Cuir in eagar",
 	"Edit Arena Model": "Cuir Samhail Airéine in Eagar",
 	"Edit Channel": "Cuir Cainéal in Eagar",
@@ -383,16 +383,16 @@
 	"Embedding model set to \"{{embedding_model}}\"": "Múnla leabaithe socraithe go \"{{embedding_model}}\"",
 	"Enable API Key": "Cumasaigh Eochair API",
 	"Enable autocomplete generation for chat messages": "Cumasaigh giniúint uathchríochnaithe le haghaidh teachtaireachtaí comhrá",
-	"Enable Code Execution": "",
+	"Enable Code Execution": "Cumasaigh Forghníomhú Cód",
 	"Enable Code Interpreter": "Cumasaigh Ateangaire Cóid",
 	"Enable Community Sharing": "Cumasaigh Comhroinnt Pobail",
 	"Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Cumasaigh Glasáil Cuimhne (mlock) chun sonraí samhaltaithe a chosc ó RAM. Glasálann an rogha seo sraith oibre leathanaigh an mhúnla isteach i RAM, ag cinntiú nach ndéanfar iad a mhalartú go diosca. Is féidir leis seo cabhrú le feidhmíocht a choinneáil trí lochtanna leathanaigh a sheachaint agus rochtain tapa ar shonraí a chinntiú.",
 	"Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Cumasaigh Mapáil Cuimhne (mmap) chun sonraí samhla a lódáil. Ligeann an rogha seo don chóras stóráil diosca a úsáid mar leathnú ar RAM trí chomhaid diosca a chóireáil amhail is dá mba i RAM iad. Is féidir leis seo feidhmíocht na samhla a fheabhsú trí rochtain níos tapúla ar shonraí a cheadú. Mar sin féin, d'fhéadfadh sé nach n-oibreoidh sé i gceart le gach córas agus féadfaidh sé méid suntasach spáis diosca a ithe.",
 	"Enable Message Rating": "Cumasaigh Rátáil Teachtai",
-	"Enable Mirostat sampling for controlling perplexity.": "",
+	"Enable Mirostat sampling for controlling perplexity.": "Cumasaigh sampláil Mirostat chun seachrán a rialú.",
 	"Enable New Sign Ups": "Cumasaigh Clárúcháin Nua",
 	"Enabled": "Cumasaithe",
-	"Enforce Temporary Chat": "",
+	"Enforce Temporary Chat": "Cuir Comhrá Sealadach i bhfeidhm",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Déan cinnte go bhfuil 4 cholún san ord seo i do chomhad CSV: Ainm, Ríomhphost, Pasfhocal, Ról.",
 	"Enter {{role}} message here": "Cuir isteach teachtaireacht {{role}} anseo",
 	"Enter a detail about yourself for your LLMs to recall": "Cuir isteach mionsonraí fút féin chun do LLManna a mheabhrú",
@@ -407,15 +407,15 @@
 	"Enter CFG Scale (e.g. 7.0)": "Cuir isteach Scála CFG (m.sh. 7.0)",
 	"Enter Chunk Overlap": "Cuir isteach Chunk Forluí",
 	"Enter Chunk Size": "Cuir isteach Méid an Smután",
-	"Enter comma-seperated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "",
+	"Enter comma-seperated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Cuir isteach péirí camóg-scartha \"comhartha:luach laofachta\" (mar shampla: 5432:100, 413:-100)",
 	"Enter description": "Iontráil cur síos",
-	"Enter Docling Server URL": "",
+	"Enter Docling Server URL": "Cuir isteach URL Freastalaí Doling",
 	"Enter Document Intelligence Endpoint": "Iontráil Críochphointe Faisnéise Doiciméid",
 	"Enter Document Intelligence Key": "Iontráil Eochair Faisnéise Doiciméad",
 	"Enter domains separated by commas (e.g., example.com,site.org)": "Cuir isteach fearainn atá scartha le camóga (m.sh., example.com,site.org)",
 	"Enter Exa API Key": "Cuir isteach Eochair Exa API",
-	"Enter Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "Cuir isteach URL Bonn API Firecrawl",
+	"Enter Firecrawl API Key": "Cuir isteach Eochair API Firecrawl",
 	"Enter Github Raw URL": "Cuir isteach URL Github Raw",
 	"Enter Google PSE API Key": "Cuir isteach Eochair API Google PSE",
 	"Enter Google PSE Engine Id": "Cuir isteach ID Inneall Google PSE",
@@ -425,16 +425,16 @@
 	"Enter Jupyter Token": "Cuir isteach Jupyter Chomhartha",
 	"Enter Jupyter URL": "Cuir isteach URL Jupyter",
 	"Enter Kagi Search API Key": "Cuir isteach Eochair Kagi Cuardach API",
-	"Enter Key Behavior": "",
+	"Enter Key Behavior": "Iontráil Iompar Eochair",
 	"Enter language codes": "Cuir isteach cóid teanga",
-	"Enter Mistral API Key": "",
+	"Enter Mistral API Key": "Cuir isteach Eochair API Mistral",
 	"Enter Model ID": "Iontráil ID Mhúnla",
 	"Enter model tag (e.g. {{modelTag}})": "Cuir isteach chlib samhail (m.sh. {{modelTag}})",
 	"Enter Mojeek Search API Key": "Cuir isteach Eochair API Cuardach Mojeek",
 	"Enter Number of Steps (e.g. 50)": "Iontráil Líon na gCéimeanna (m.sh. 50)",
-	"Enter Perplexity API Key": "",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Perplexity API Key": "Cuir isteach Eochair API Perplexity",
+	"Enter Playwright Timeout": "Iontráil Teorainn Ama na nDrámadóir",
+	"Enter Playwright WebSocket URL": "Cuir isteach URL WebSocket Seinmeora",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "Cuir isteach URL seachfhreastalaí (m.sh. https://user:password@host:port)",
 	"Enter reasoning effort": "Cuir isteach iarracht réasúnaíochta",
 	"Enter Sampler (e.g. Euler a)": "Cuir isteach Sampler (m.sh. Euler a)",
@@ -452,26 +452,26 @@
 	"Enter server host": "Cuir isteach óstach freastalaí",
 	"Enter server label": "Cuir isteach lipéad freastalaí",
 	"Enter server port": "Cuir isteach port freastalaí",
-	"Enter Sougou Search API sID": "",
-	"Enter Sougou Search API SK": "",
+	"Enter Sougou Search API sID": "Cuir isteach sID Sougou Search API",
+	"Enter Sougou Search API SK": "Cuir isteach Sougou Search API SK",
 	"Enter stop sequence": "Cuir isteach seicheamh stad",
 	"Enter system prompt": "Cuir isteach an chóras leid",
-	"Enter system prompt here": "",
+	"Enter system prompt here": "Cuir leid córais isteach anseo",
 	"Enter Tavily API Key": "Cuir isteach eochair API Tavily",
-	"Enter Tavily Extract Depth": "",
+	"Enter Tavily Extract Depth": "Cuir isteach Doimhneacht Sliocht Tavily",
 	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Cuir isteach URL poiblí do WebUI. Bainfear úsáid as an URL seo chun naisc a ghiniúint sna fógraí.",
 	"Enter Tika Server URL": "Cuir isteach URL freastalaí Tika",
 	"Enter timeout in seconds": "Cuir isteach an t-am istigh i soicindí",
-	"Enter to Send": "",
+	"Enter to Send": "Iontráil chun Seol",
 	"Enter Top K": "Cuir isteach Barr K",
-	"Enter Top K Reranker": "",
+	"Enter Top K Reranker": "Cuir isteach Barr K Reranker",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Iontráil URL (m.sh. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Iontráil URL (m.sh. http://localhost:11434)",
 	"Enter your current password": "Cuir isteach do phasfhocal reatha",
 	"Enter Your Email": "Cuir isteach do Ríomhphost",
 	"Enter Your Full Name": "Cuir isteach d'Ainm Iomlán",
 	"Enter your message": "Cuir isteach do theachtaireacht",
-	"Enter your name": "",
+	"Enter your name": "Cuir isteach d'ainm",
 	"Enter your new password": "Cuir isteach do phasfhocal nua",
 	"Enter Your Password": "Cuir isteach do phasfhocal",
 	"Enter Your Role": "Cuir isteach do Ról",
@@ -488,14 +488,14 @@
 	"Example: mail": "Sampla: ríomhphost",
 	"Example: ou=users,dc=foo,dc=example": "Sampla: ou=úsáideoirí,dc=foo,dc=sampla",
 	"Example: sAMAccountName or uid or userPrincipalName": "Sampla: sAMAaccountName nó uid nó userPrincipalName",
-	"Exceeded the number of seats in your license. Please contact support to increase the number of seats.": "",
+	"Exceeded the number of seats in your license. Please contact support to increase the number of seats.": "Níos mó ná líon na suíochán i do cheadúnas. Déan teagmháil le do thoil le tacaíocht chun líon na suíochán a mhéadú.",
 	"Exclude": "Eisigh",
 	"Execute code for analysis": "Íosluchtaigh cód le haghaidh anailíse",
-	"Executing **{{NAME}}**...": "",
-	"Expand": "",
+	"Executing **{{NAME}}**...": "**{{NAME}}** á rith...",
+	"Expand": "Leathnaigh",
 	"Experimental": "Turgnamhach",
-	"Explain": "",
-	"Explain this section to me in more detail": "",
+	"Explain": "Mínigh",
+	"Explain this section to me in more detail": "Mínigh an chuid seo dom níos mine",
 	"Explore the cosmos": "Déan iniúchadh ar an cosmos",
 	"Export": "Easpórtáil",
 	"Export All Archived Chats": "Easpórtáil Gach Comhrá Cartlainne",
@@ -509,14 +509,14 @@
 	"Export Prompts": "Leideanna Easpórtála",
 	"Export to CSV": "Easpórtáil go CSV",
 	"Export Tools": "Uirlisí Easpór",
-	"External": "",
+	"External": "Seachtrach",
 	"External Models": "Múnlaí Seachtracha",
 	"Failed to add file.": "Theip ar an gcomhad a chur leis.",
-	"Failed to connect to {{URL}} OpenAPI tool server": "",
+	"Failed to connect to {{URL}} OpenAPI tool server": "Theip ar nascadh le {{URL}} freastalaí uirlisí OpenAPI",
 	"Failed to create API Key.": "Theip ar an eochair API a chruthú.",
 	"Failed to fetch models": "Theip ar shamhlacha a fháil",
 	"Failed to read clipboard contents": "Theip ar ábhar gearrthaisce a lé",
-	"Failed to save connections": "",
+	"Failed to save connections": "Theip ar na naisc a shábháil",
 	"Failed to save models configuration": "Theip ar chumraíocht na múnlaí a shábháil",
 	"Failed to update settings": "Theip ar shocruithe a nuashonrú",
 	"Failed to upload file.": "Theip ar uaslódáil an chomhaid.",
@@ -539,8 +539,8 @@
 	"Filter is now globally enabled": "Tá an scagaire cumasaithe go domhanda anois",
 	"Filters": "Scagairí",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Braithíodh spoofing méarloirg: Ní féidir teachlitreacha a úsáid mar avatar. Réamhshocrú ar íomhá próifíle réamhshocraithe.",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "URL Bunús API Firecrawl",
+	"Firecrawl API Key": "Eochair API Firecrawl",
 	"Fluidly stream large external response chunks": "Sruthaigh codanna móra freagartha seachtracha go sreabhach",
 	"Focus chat input": "Ionchur comhrá fócas",
 	"Folder deleted successfully": "Scriosadh an fillteán go rathúil",
@@ -551,7 +551,7 @@
 	"Forge new paths": "Déan cosáin nua a chruthú",
 	"Form": "Foirm",
 	"Format your variables using brackets like this:": "Formáidigh na hathróga ag baint úsáide as lúibíní mar seo:",
-	"Forwards system user session credentials to authenticate": "",
+	"Forwards system user session credentials to authenticate": "Cuir dintiúir seisiúin úsáideora córais ar aghaidh lena bhfíordheimhniú",
 	"Frequency Penalty": "Pionós Minicíochta",
 	"Full Context Mode": "Mód Comhthéacs Iomlán",
 	"Function": "Feidhm",
@@ -573,7 +573,7 @@
 	"Gemini API Key is required.": "Tá Eochair Gemini API ag teastáil.",
 	"General": "Ginearálta",
 	"Generate an image": "Gin íomhá",
-	"Generate Image": "Ginigh Íomhá",
+	"Generate Image": "Gin Íomhá",
 	"Generate prompt pair": "Gin péire pras",
 	"Generating search query": "Giniúint ceist cuardaigh",
 	"Get started": "Cuir tús leis",
@@ -597,7 +597,7 @@
 	"Hex Color": "Dath Heics",
 	"Hex Color - Leave empty for default color": "Dath Heics - Fág folamh don dath réamhshocraithe",
 	"Hide": "Folaigh",
-	"Hide Model": "",
+	"Hide Model": "Folaigh Múnla",
 	"Home": "Baile",
 	"Host": "Óstach",
 	"How can I help you today?": "Conas is féidir liom cabhrú leat inniu?",
@@ -605,8 +605,8 @@
 	"Hybrid Search": "Cuardach Hibrideach",
 	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Admhaím gur léigh mé agus tuigim impleachtaí mo ghníomhaíochta. Táim ar an eolas faoi na rioscaí a bhaineann le cód treallach a fhorghníomhú agus tá iontaofacht na foinse fíoraithe agam.",
 	"ID": "ID",
-	"iframe Sandbox Allow Forms": "",
-	"iframe Sandbox Allow Same Origin": "",
+	"iframe Sandbox Allow Forms": "iframe Bosca Gainimh Foirmeacha Ceadaithe",
+	"iframe Sandbox Allow Same Origin": "Bosca Gainimh iframe Ceadaigh an Bunús Céanna",
 	"Ignite curiosity": "Las fiosracht",
 	"Image": "Íomhá",
 	"Image Compression": "Comhbhrú Íomhá",
@@ -628,16 +628,16 @@
 	"Include": "Cuir san áireamh",
 	"Include `--api-auth` flag when running stable-diffusion-webui": "Cuir bratach `--api-auth` san áireamh agus webui stable-diffusion-reatha á rith",
 	"Include `--api` flag when running stable-diffusion-webui": "Cuir bratach `--api` san áireamh agus webui cobhsaí-scaipthe á rith",
-	"Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "",
+	"Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "Bíonn tionchar aige ar chomh tapa agus a fhreagraíonn an t-algartam d’aiseolas ón téacs ginte. Beidh coigeartuithe níos moille mar thoradh ar ráta foghlama níos ísle, agus déanfaidh ráta foghlama níos airde an t-algartam níos freagraí.",
 	"Info": "Eolas",
-	"Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "",
+	"Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "Instealladh an t-ábhar ar fad mar chomhthéacs do phróiseáil chuimsitheach, moltar é seo le haghaidh ceisteanna casta.",
 	"Input commands": "Orduithe ionchuir",
 	"Install from Github URL": "Suiteáil ó Github URL",
 	"Instant Auto-Send After Voice Transcription": "Seoladh Uathoibríoch Láithreach Tar éis",
 	"Integration": "Comhtháthú",
 	"Interface": "Comhéadan",
 	"Invalid file format.": "Formáid comhaid neamhbhailí.",
-	"Invalid JSON schema": "",
+	"Invalid JSON schema": "Scéimre JSON neamhbhailí",
 	"Invalid Tag": "Clib neamhbhailí",
 	"is typing...": "ag clóscríobh...",
 	"January": "Eanáir",
@@ -645,7 +645,7 @@
 	"join our Discord for help.": "bí inár Discord chun cabhair a fháil.",
 	"JSON": "JSON",
 	"JSON Preview": "Réamhamharc JSON",
-	"July": "Lúil",
+	"July": "Iúil",
 	"June": "Meitheamh",
 	"Jupyter Auth": "Fíordheimhniú Jupyter",
 	"Jupyter URL": "URL Jupyter",
@@ -659,7 +659,7 @@
 	"Knowledge Access": "Rochtain Eolais",
 	"Knowledge created successfully.": "Eolas cruthaithe go rathúil.",
 	"Knowledge deleted successfully.": "D'éirigh leis an eolas a scriosadh.",
-	"Knowledge Public Sharing": "",
+	"Knowledge Public Sharing": "Roinnt Faisnéise Poiblí",
 	"Knowledge reset successfully.": "D'éirigh le hathshocrú eolais.",
 	"Knowledge updated successfully": "D'éirigh leis an eolas a nuashonrú",
 	"Kokoro.js (Browser)": "Kokoro.js (Brabhsálaí)",
@@ -667,17 +667,17 @@
 	"Label": "Lipéad",
 	"Landing Page Mode": "Mód Leathanach Tuirlingthe",
 	"Language": "Teanga",
-	"Language Locales": "",
+	"Language Locales": "Logánta Teanga",
 	"Last Active": "Gníomhach Deiridh",
 	"Last Modified": "Athraithe Deiridh",
 	"Last reply": "Freagra deiridh",
 	"LDAP": "LDAP",
 	"LDAP server updated": "Nuashonraíodh freastalaí LDAP",
 	"Leaderboard": "An Clár Ceannairí",
-	"Learn more about OpenAPI tool servers.": "",
+	"Learn more about OpenAPI tool servers.": "Foghlaim tuilleadh faoi fhreastalaithe uirlisí OpenAPI.",
 	"Leave empty for unlimited": "Fág folamh le haghaidh neamhtheoranta",
-	"Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "",
-	"Leave empty to include all models from \"{{url}}/models\" endpoint": "",
+	"Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "Fág folamh chun gach múnla ó chríochphointe \"{{url}}/api/tags\" 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 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.": "Fág réimse an mhúnla folamh chun an tsamhail réamhshocraithe a úsáid.",
@@ -691,7 +691,7 @@
 	"Local": "Áitiúil",
 	"Local Models": "Múnlaí Áitiúla",
 	"Location access not allowed": "Ní cheadaítear rochtain suímh",
-	"Logit Bias": "",
+	"Logit Bias": "Bias Logit",
 	"Lost": "Cailleadh",
 	"LTR": "LTR",
 	"Made by Open WebUI Community": "Déanta ag OpenWebUI Community",
@@ -704,7 +704,7 @@
 	"Manage Ollama API Connections": "Bainistigh Naisc API Ollama",
 	"Manage OpenAI API Connections": "Bainistigh Naisc API OpenAI",
 	"Manage Pipelines": "Bainistigh píblín",
-	"Manage Tool Servers": "",
+	"Manage Tool Servers": "Bainistigh Freastalaithe Uirlisí",
 	"March": "Márta",
 	"Max Tokens (num_predict)": "Comharthaí Uasta (num_predicate)",
 	"Max Upload Count": "Líon Uaslódála Max",
@@ -724,16 +724,16 @@
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Tau": "Mirostat Tau",
-	"Mistral OCR": "",
-	"Mistral OCR API Key required.": "",
+	"Mistral OCR": "OCR Mistral",
+	"Mistral OCR API Key required.": "Mistral OCR API Eochair ag teastáil.",
 	"Model": "Múnla",
 	"Model '{{modelName}}' has been successfully downloaded.": "Rinneadh an tsamhail '{{modelName}}' a íoslódáil go rathúil.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Tá múnla ‘{{modelTag}}’ sa scuaine cheana féin le híoslódáil.",
 	"Model {{modelId}} not found": "Múnla {{modelId}} gan aimsiú",
 	"Model {{modelName}} is not vision capable": "Níl samhail {{modelName}} in ann amharc",
 	"Model {{name}} is now {{status}}": "Tá samhail {{name}} {{status}} anois",
-	"Model {{name}} is now hidden": "",
-	"Model {{name}} is now visible": "",
+	"Model {{name}} is now hidden": "Tá múnla {{name}} i bhfolach anois",
+	"Model {{name}} is now visible": "Tá múnla {{name}} le feiceáil anois",
 	"Model accepts image inputs": "Glacann múnla le hionchuir",
 	"Model created successfully!": "Cruthaíodh múnla go rathúil!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Fuarthas cosán an múnla. Teastaíonn ainm gearr an mhúnla le haghaidh nuashonraithe, ní féidir leanúint ar aghaidh.",
@@ -749,7 +749,7 @@
 	"Models": "Múnlaí",
 	"Models Access": "Rochtain Múnlaí",
 	"Models configuration saved successfully": "Sábháladh cumraíocht na múnlaí go rathúil",
-	"Models Public Sharing": "",
+	"Models Public Sharing": "Múnlaí Comhroinnte Poiblí",
 	"Mojeek Search API Key": "Eochair API Cuardach Mojeek",
 	"more": "níos mó",
 	"More": "Tuilleadh",
@@ -812,7 +812,7 @@
 	"Open file": "Oscail comhad",
 	"Open in full screen": "Oscail i scáileán iomlán",
 	"Open new chat": "Oscail comhrá nua",
-	"Open WebUI can use tools provided by any OpenAPI server.": "",
+	"Open WebUI can use tools provided by any OpenAPI server.": "Is féidir le WebUI Oscailte uirlisí a úsáid a sholáthraíonn aon fhreastalaí OpenAPI.",
 	"Open WebUI uses faster-whisper internally.": "Úsáideann Open WebUI cogar níos tapúla go hinmheánach.",
 	"Open WebUI uses SpeechT5 and CMU Arctic speaker embeddings.": "Úsáideann Open WebUI úsáidí SpeechT5 agus CMU leabaithe cainteoir Artach.",
 	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "Tá leagan WebUI oscailte (v{{OPEN_WEBUI_VERSION}}) níos ísle ná an leagan riachtanach (v{{REQUIRED_VERSION}})",
@@ -822,7 +822,7 @@
 	"OpenAI API Key is required.": "Tá Eochair API OpenAI ag teastáil.",
 	"OpenAI API settings updated": "Nuashonraíodh socruithe OpenAI API",
 	"OpenAI URL/Key required.": "Teastaíonn URL/eochair OpenAI.",
-	"openapi.json Path": "",
+	"openapi.json Path": "Conair openapi.json",
 	"or": "nó",
 	"Organize your users": "Eagraigh do chuid úsáideoirí",
 	"Other": "Eile",
@@ -839,7 +839,7 @@
 	"Permission denied when accessing microphone": "Cead diúltaithe agus tú ag rochtain ar",
 	"Permission denied when accessing microphone: {{error}}": "Cead diúltaithe agus tú ag teacht ar mhicreafón: {{error}}",
 	"Permissions": "Ceadanna",
-	"Perplexity API Key": "",
+	"Perplexity API Key": "Eochair API Perplexity",
 	"Personalization": "Pearsantú",
 	"Pin": "Bioráin",
 	"Pinned": "Pinneáilte",
@@ -851,13 +851,13 @@
 	"Pipelines Valves": "Comhlaí Píblíne",
 	"Plain text (.txt)": "Téacs simplí (.txt)",
 	"Playground": "Clós súgartha",
-	"Playwright Timeout (ms)": "",
-	"Playwright WebSocket URL": "",
+	"Playwright Timeout (ms)": "Teorainn Ama drámadóra (ms)",
+	"Playwright WebSocket URL": "URL drámadóir WebSocket",
 	"Please carefully review the following warnings:": "Déan athbhreithniú cúramach ar na rabhaidh seo a leanas le do thoil:",
 	"Please do not close the settings page while loading the model.": "Ná dún leathanach na socruithe agus an tsamhail á luchtú.",
 	"Please enter a prompt": "Cuir isteach leid",
-	"Please enter a valid path": "",
-	"Please enter a valid URL": "",
+	"Please enter a valid path": "Cuir isteach cosán bailí",
+	"Please enter a valid URL": "Cuir isteach URL bailí",
 	"Please fill in all fields.": "Líon isteach gach réimse le do thoil.",
 	"Please select a model first.": "Roghnaigh munla ar dtús le do thoil.",
 	"Please select a model.": "Roghnaigh múnla le do thoil.",
@@ -869,19 +869,19 @@
 	"Presence Penalty": "Pionós Láithreacht",
 	"Previous 30 days": "30 lá roimhe seo",
 	"Previous 7 days": "7 lá roimhe seo",
-	"Private": "",
+	"Private": "Príobháideach",
 	"Profile Image": "Íomhá Próifíl",
 	"Prompt": "Leid",
 	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Leid (m.sh. inis dom fíric spraíúil faoin Impireacht Rómhánach)",
-	"Prompt Autocompletion": "",
+	"Prompt Autocompletion": "Uathchríochnú Pras",
 	"Prompt Content": "Ábhar Leid",
 	"Prompt created successfully": "Leid cruthaithe go rathúil",
 	"Prompt suggestions": "Moltaí leid",
 	"Prompt updated successfully": "D'éirigh leis an leid a nuashonrú",
 	"Prompts": "Leabhair",
 	"Prompts Access": "Rochtain ar Chuirí",
-	"Prompts Public Sharing": "",
-	"Public": "",
+	"Prompts Public Sharing": "Spreagann Roinnt Phoiblí",
+	"Public": "Poiblí",
 	"Pull \"{{searchValue}}\" from Ollama.com": "Tarraing \"{{searchValue}}\" ó Ollama.com",
 	"Pull a model from Ollama.com": "Tarraing múnla ó Ollama.com",
 	"Query Generation Prompt": "Cuirí Ginearáil Ceisteanna",
@@ -893,16 +893,16 @@
 	"Reasoning Effort": "Iarracht Réasúnúcháin",
 	"Record voice": "Taifead guth",
 	"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.": "",
+	"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.": "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í.",
 	"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í ó",
 	"Refused when it shouldn't have": "Diúltaíodh nuair nár chóir dó",
 	"Regenerate": "Athghiniúint",
-	"Reindex": "",
-	"Reindex Knowledge Base Vectors": "",
+	"Reindex": "Reindex",
+	"Reindex Knowledge Base Vectors": "Veicteoirí Bonn Eolais a ath-innéacsú",
 	"Release Notes": "Nótaí Scaoilte",
 	"Relevance": "Ábharthacht",
-	"Relevance Threshold": "",
+	"Relevance Threshold": "Tairseach Ábharthaíochta",
 	"Remove": "Bain",
 	"Remove Model": "Bain Múnla",
 	"Rename": "Athainmnigh",
@@ -1005,22 +1005,22 @@
 	"Set the number of worker threads used for computation. This option controls how many threads are used to process incoming requests concurrently. Increasing this value can improve performance under high concurrency workloads but may also consume more CPU resources.": "Socraigh líon na snáitheanna oibrithe a úsáidtear le haghaidh ríomh. Rialaíonn an rogha seo cé mhéad snáithe a úsáidtear chun iarratais a thagann isteach a phróiseáil i gcomhthráth. D'fhéadfadh méadú ar an luach seo feidhmíocht a fheabhsú faoi ualaí oibre comhairgeadra ard ach féadfaidh sé níos mó acmhainní LAP a úsáid freisin.",
 	"Set Voice": "Socraigh Guth",
 	"Set whisper model": "Socraigh múnla cogar",
-	"Sets a flat bias against tokens that have appeared at least once. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "",
-	"Sets a scaling bias against tokens to penalize repetitions, based on how many times they have appeared. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "",
-	"Sets how far back for the model to look back to prevent repetition.": "",
-	"Sets the random number seed to use for generation. Setting this to a specific number will make the model generate the same text for the same prompt.": "",
-	"Sets the size of the context window used to generate the next token.": "",
+	"Sets a flat bias against tokens that have appeared at least once. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Socraíonn sé claonadh cothrom i gcoinne comharthaí a tháinig chun solais uair amháin ar a laghad. Cuirfidh luach níos airde (m.sh., 1.5) pionós níos láidre ar athrá, agus beidh luach níos ísle (m.sh., 0.9) níos boige. Ag 0, tá sé díchumasaithe.",
+	"Sets a scaling bias against tokens to penalize repetitions, based on how many times they have appeared. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Socraíonn sé laofacht scálaithe i gcoinne comharthaí chun pionós a ghearradh ar athrá, bunaithe ar cé mhéad uair a tháinig siad chun solais. Cuirfidh luach níos airde (m.sh., 1.5) pionós níos láidre ar athrá, agus beidh luach níos ísle (m.sh., 0.9) níos boige. Ag 0, tá sé díchumasaithe.",
+	"Sets how far back for the model to look back to prevent repetition.": "Socraíonn sé cé chomh fada siar is atá an tsamhail le breathnú siar chun athrá a chosc.",
+	"Sets the random number seed to use for generation. Setting this to a specific number will make the model generate the same text for the same prompt.": "Socraíonn sé an síol uimhir randamach a úsáid le haghaidh giniúna. Má shocraítear é seo ar uimhir shainiúil, ginfidh an tsamhail an téacs céanna don leid céanna.",
+	"Sets the size of the context window used to generate the next token.": "Socraíonn sé méid na fuinneoige comhthéacs a úsáidtear chun an chéad chomhartha eile a ghiniúint.",
 	"Sets the stop sequences to use. When this pattern is encountered, the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.": "Socraíonn sé na stadanna le húsáid. Nuair a thagtar ar an bpatrún seo, stopfaidh an LLM ag giniúint téacs agus ag filleadh. Is féidir patrúin stad iolracha a shocrú trí pharaiméadair stadanna iolracha a shonrú i gcomhad samhail.",
 	"Settings": "Socruithe",
 	"Settings saved successfully!": "Socruithe sábhálta go rathúil!",
 	"Share": "Comhroinn",
 	"Share Chat": "Comhroinn Comhrá",
 	"Share to Open WebUI Community": "Comhroinn le Pobal OpenWebUI",
-	"Sharing Permissions": "",
+	"Sharing Permissions": "Ceadanna a Roinnt",
 	"Show": "Taispeáin",
 	"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 Model": "",
+	"Show Model": "Taispeáin Múnla",
 	"Show shortcuts": "Taispeáin aicearraí",
 	"Show your support!": "Taispeáin do thacaíocht!",
 	"Showcased creativity": "Cruthaitheacht léirithe",
@@ -1032,8 +1032,8 @@
 	"Sign up to {{WEBUI_NAME}}": "Cláraigh le {{WEBUI_NAME}}",
 	"Signing in to {{WEBUI_NAME}}": "Ag síniú isteach ar {{WEBUI_NAME}}",
 	"sk-1234": "sk-1234",
-	"Sougou Search API sID": "",
-	"Sougou Search API SK": "",
+	"Sougou Search API sID": "Sougou Search API sID",
+	"Sougou Search API SK": "Sougou Search API SK",
 	"Source": "Foinse",
 	"Speech Playback Speed": "Luas Athsheinm Urlabhra",
 	"Speech recognition error: {{error}}": "Earráid aitheantais cainte: {{error}}",
@@ -1053,7 +1053,7 @@
 	"System": "Córas",
 	"System Instructions": "Treoracha Córas",
 	"System Prompt": "Córas Leid",
-	"Tags": "",
+	"Tags": "Clibeanna",
 	"Tags Generation": "Giniúint Clibeanna",
 	"Tags Generation Prompt": "Clibeanna Giniúint Leid",
 	"Tail free sampling is used to reduce the impact of less probable tokens from the output. A higher value (e.g., 2.0) will reduce the impact more, while a value of 1.0 disables this setting.": "Úsáidtear sampláil saor ó eireabaill chun tionchar na n-chomharthaí ón aschur nach bhfuil chomh dóchúil céanna a laghdú. Laghdóidh luach níos airde (m.sh., 2.0) an tionchar níos mó, agus díchumasaíonn luach 1.0 an socrú seo. (réamhshocraithe: 1)",
@@ -1061,7 +1061,7 @@
 	"Tap to interrupt": "Tapáil chun cur isteach",
 	"Tasks": "Tascanna",
 	"Tavily API Key": "Eochair API Tavily",
-	"Tavily Extract Depth": "",
+	"Tavily Extract Depth": "Doimhneacht Sliocht Tavily",
 	"Tell us more:": "Inis dúinn níos mó:",
 	"Temperature": "Teocht",
 	"Template": "Teimpléad",
@@ -1072,7 +1072,7 @@
 	"Thanks for your feedback!": "Go raibh maith agat as do chuid aiseolas!",
 	"The Application Account DN you bind with for search": "An Cuntas Feidhmchláir DN a nascann tú leis le haghaidh cuardaigh",
 	"The base to search for users": "An bonn chun cuardach a dhéanamh ar úsáideoirí",
-	"The batch size determines how many text requests are processed together at once. A higher batch size can increase the performance and speed of the model, but it also requires more memory.": "",
+	"The batch size determines how many text requests are processed together at once. A higher batch size can increase the performance and speed of the model, but it also requires more memory.": "Cinneann méid an bhaisc cé mhéad iarratas téacs a phróiseáiltear le chéile ag an am céanna. Is féidir le méid baisc níos airde feidhmíocht agus luas an mhúnla a mhéadú, ach éilíonn sé níos mó cuimhne freisin.",
 	"The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Is deonacha paiseanta ón bpobal iad na forbróirí taobh thiar den bhreiseán seo. Má aimsíonn an breiseán seo cabhrach leat, smaoinigh ar rannchuidiú lena fhorbairt.",
 	"The evaluation leaderboard is based on the Elo rating system and is updated in real-time.": "Tá an clár ceannairí meastóireachta bunaithe ar chóras rátála Elo agus déantar é a nuashonrú i bhfíor-am.",
 	"The LDAP attribute that maps to the mail that users use to sign in.": "An tréith LDAP a mhapálann don ríomhphost a úsáideann úsáideoirí chun síniú isteach.",
@@ -1081,16 +1081,16 @@
 	"The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Uasmhéid an chomhaid i MB. Má sháraíonn méid an chomhaid an teorainn seo, ní uaslódófar an comhad.",
 	"The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "An líon uasta na gcomhaid is féidir a úsáid ag an am céanna i gcomhrá. Má sháraíonn líon na gcomhaid an teorainn seo, ní uaslódófar na comhaid.",
 	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Ba chóir go mbeadh an scór ina luach idir 0.0 (0%) agus 1.0 (100%).",
-	"The temperature of the model. Increasing the temperature will make the model answer more creatively.": "",
+	"The temperature of the model. Increasing the temperature will make the model answer more creatively.": "Teocht an mhúnla. Déanfaidh méadú ar an teocht an freagra múnla níos cruthaithí.",
 	"Theme": "Téama",
 	"Thinking...": "Ag smaoineamh...",
 	"This action cannot be undone. Do you wish to continue?": "Ní féidir an gníomh seo a chur ar ais. Ar mhaith leat leanúint ar aghaidh?",
-	"This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "",
-	"This chat won’t appear in history and your messages will not be saved.": "",
+	"This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "Cruthaíodh an cainéal seo ar {{createdAt}}. Seo tús an chainéil {{channelName}}.",
+	"This chat won’t appear in history and your messages will not be saved.": "Ní bheidh an comhrá seo le feiceáil sa stair agus ní shábhálfar do theachtaireachtaí.",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cinntíonn sé seo go sábhálfar do chomhráite luachmhara go daingean i do bhunachar sonraí cúltaca Go raibh maith agat!",
 	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Is gné turgnamhach í seo, b'fhéidir nach bhfeidhmeoidh sé mar a bhíothas ag súil leis agus tá sé faoi réir athraithe ag am ar bith.",
-	"This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "",
-	"This option sets the maximum number of tokens the model can generate in its response. Increasing this limit allows the model to provide longer answers, but it may also increase the likelihood of unhelpful or irrelevant content being generated.": "",
+	"This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Rialaíonn an rogha seo cé mhéad comhartha a chaomhnaítear agus an comhthéacs á athnuachan. Mar shampla, má shocraítear go 2 é, coinneofar an 2 chomhartha dheireanacha de chomhthéacs an chomhrá. Is féidir le comhthéacs a chaomhnú cabhrú le leanúnachas comhrá a choinneáil, ach d’fhéadfadh sé laghdú a dhéanamh ar an gcumas freagairt do thopaicí nua.",
+	"This option sets the maximum number of tokens the model can generate in its response. Increasing this limit allows the model to provide longer answers, but it may also increase the likelihood of unhelpful or irrelevant content being generated.": "Socraíonn an rogha seo an t-uaslíon comharthaí is féidir leis an tsamhail a ghiniúint ina fhreagra. Tríd an teorainn seo a mhéadú is féidir leis an tsamhail freagraí níos faide a sholáthar, ach d’fhéadfadh go méadódh sé an dóchúlacht go nginfear ábhar neamhchabhrach nó nach mbaineann le hábhar.",
 	"This option will delete all existing files in the collection and replace them with newly uploaded files.": "Scriosfaidh an rogha seo gach comhad atá sa bhailiúchán agus cuirfear comhaid nua-uaslódála ina n-ionad.",
 	"This response was generated by \"{{model}}\"": "Gin an freagra seo ag \"{{model}}\"",
 	"This will delete": "Scriosfaidh sé seo",
@@ -1103,7 +1103,7 @@
 	"Thought for {{DURATION}} seconds": "Smaoineamh ar feadh {{DURATION}} soicind",
 	"Tika": "Tika",
 	"Tika Server URL required.": "Teastaíonn URL Freastalaí Tika.",
-	"Tiktoken": "Tictoken",
+	"Tiktoken": "Tiktoken",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Leid: Nuashonraigh sliotáin iolracha athróg as a chéile trí bhrú ar an eochair cluaisín san ionchur comhrá tar éis gach athsholáthair.",
 	"Title": "Teideal",
 	"Title (e.g. Tell me a fun fact)": "Teideal (m.sh. inis dom fíric spraíúil)",
@@ -1134,7 +1134,7 @@
 	"Tool ID": "ID Uirlis",
 	"Tool imported successfully": "Uirlis iompórtáilte",
 	"Tool Name": "Ainm Uirlis",
-	"Tool Servers": "",
+	"Tool Servers": "Freastalaithe Uirlisí",
 	"Tool updated successfully": "An uirlis nuashonraithe",
 	"Tools": "Uirlisí",
 	"Tools Access": "Rochtain Uirlisí",
@@ -1142,9 +1142,9 @@
 	"Tools Function Calling Prompt": "Leid Glaonna Feidhm Uirlisí",
 	"Tools have a function calling system that allows arbitrary code execution": "Tá córas glaonna feidhme ag uirlisí a cheadaíonn forghníomhú cód treallach",
 	"Tools have a function calling system that allows arbitrary code execution.": "Tá córas glaonna feidhme ag uirlisí a cheadaíonn forghníomhú cód treallach.",
-	"Tools Public Sharing": "",
+	"Tools Public Sharing": "Uirlisí Roinnte Poiblí",
 	"Top K": "Barr K",
-	"Top K Reranker": "",
+	"Top K Reranker": "Barr K Reranker",
 	"Top P": "Barr P",
 	"Transformers": "Claochladáin",
 	"Trouble accessing Ollama?": "Deacracht teacht ar Ollama?",
@@ -1184,14 +1184,14 @@
 	"Use Gravatar": "Úsáid Gravatar",
 	"Use groups to group your users and assign permissions.": "Úsáid grúpaí chun d'úsáideoirí a ghrúpáil agus ceadanna a shannadh",
 	"Use Initials": "Úsáid ceannlitreacha",
-	"Use no proxy to fetch page contents.": "",
-	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "",
+	"Use no proxy to fetch page contents.": "Ná húsáid seachfhreastalaí chun inneachar an leathanaigh a fháil.",
+	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Úsáid seachfhreastalaí ainmnithe ag athróga timpeallachta http_proxy agus https_proxy chun inneachar an leathanaigh a fháil.",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "úsáideoir",
 	"User": "Úsáideoir",
 	"User location successfully retrieved.": "Fuarthas suíomh an úsáideora go rathúil.",
-	"User Webhooks": "",
+	"User Webhooks": "Crúcaí Gréasáin Úsáideoir",
 	"Username": "Ainm Úsáideora",
 	"Users": "Úsáideoirí",
 	"Using the default arena model with all models. Click the plus button to add custom models.": "Ag baint úsáide as an múnla réimse réamhshocraithe le gach múnlaí. Cliceáil ar an gcnaipe móide chun múnlaí saincheaptha a chur leis.",
@@ -1202,12 +1202,12 @@
 	"Valves updated successfully": "Comhlaí nuashonraíodh",
 	"variable": "athraitheach",
 	"variable to have them replaced with clipboard content.": "athróg chun ábhar gearrthaisce a chur in ionad iad.",
-	"Verify Connection": "",
-	"Verify SSL Certificate": "",
+	"Verify Connection": "Fíoraigh Ceangal",
+	"Verify SSL Certificate": "Fíoraigh Deimhniú SSL",
 	"Version": "Leagan",
 	"Version {{selectedVersion}} of {{totalVersions}}": "Leagan {{selectedVersion}} de {{totalVersions}}",
 	"View Replies": "Féach ar Fhreagraí",
-	"View Result from **{{NAME}}**": "",
+	"View Result from **{{NAME}}**": "Féach ar Thoradh ó **{{NAME}}**",
 	"Visibility": "Infheictheacht",
 	"Voice": "Guth",
 	"Voice Input": "Ionchur Gutha",
@@ -1218,7 +1218,7 @@
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "Rabhadh: Trí fhorghníomhú Jupyter is féidir cód a fhorghníomhú go treallach, rud a chruthaíonn mór-rioscaí slándála - bí fíorchúramach.",
 	"Web": "Gréasán",
 	"Web API": "API Gréasáin",
-	"Web Loader Engine": "",
+	"Web Loader Engine": "Inneall Luchtaithe Gréasáin",
 	"Web Search": "Cuardach Gréasáin",
 	"Web Search Engine": "Inneall Cuardaigh Gréasáin",
 	"Web Search in Chat": "Cuardach Gréasáin i gComhrá",
@@ -1226,7 +1226,7 @@
 	"Webhook URL": "URL Webhook",
 	"WebUI Settings": "Socruithe WebUI",
 	"WebUI URL": "URL WebUI",
-	"WebUI will make requests to \"{{url}}\"": "",
+	"WebUI will make requests to \"{{url}}\"": "Déanfaidh WebUI iarratais ar \"{{url}}\"",
 	"WebUI will make requests to \"{{url}}/api/chat\"": "Déanfaidh WebUI iarratais ar \"{{url}}/api/chat\"",
 	"WebUI will make requests to \"{{url}}/chat/completions\"": "Déanfaidh WebUI iarratais ar \"{{url}}/chat/completions\"",
 	"What are you trying to achieve?": "Cad atá tú ag iarraidh a bhaint amach?",
@@ -1238,7 +1238,7 @@
 	"Why?": "Cén fáth?",
 	"Widescreen Mode": "Mód Leathanscáileán",
 	"Won": "Bhuaigh",
-	"Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text.": "",
+	"Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text.": "Oibríonn sé le barr-k. Beidh téacs níos éagsúla mar thoradh ar luach níos airde (m.sh., 0.95), agus ginfidh luach níos ísle (m.sh., 0.5) téacs níos dírithe agus níos coimeádaí.",
 	"Workspace": "Spás oibre",
 	"Workspace Permissions": "Ceadanna Spás Oibre",
 	"Write": "Scríobh",
@@ -1248,7 +1248,7 @@
 	"Write your model template content here": "Scríobh do mhúnla ábhar teimpléad anseo",
 	"Yesterday": "Inné",
 	"You": "Tú",
-	"You are currently using a trial license. Please contact support to upgrade your license.": "",
+	"You are currently using a trial license. Please contact support to upgrade your license.": "Tá ceadúnas trialach á úsáid agat faoi láthair. Déan teagmháil leis an bhfoireann tacaíochta chun do cheadúnas a uasghrádú.",
 	"You can only chat with a maximum of {{maxCount}} file(s) at a time.": "Ní féidir leat comhrá a dhéanamh ach le comhad {{maxCount}} ar a mhéad ag an am.",
 	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Is féidir leat do chuid idirghníomhaíochtaí le LLManna a phearsantú ach cuimhní cinn a chur leis tríd an gcnaipe 'Bainistigh' thíos, rud a fhágann go mbeidh siad níos cabhrach agus níos oiriúnaí duit.",
 	"You cannot upload an empty file.": "Ní féidir leat comhad folamh a uaslódáil.",

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

@@ -128,7 +128,7 @@
 	"Available list": "가능한 목록",
 	"Available Tools": "",
 	"available!": "사용 가능!",
-	"Awful": "끔찍함",
+	"Awful": "형편없음",
 	"Azure AI Speech": "Azure AI 음성",
 	"Azure Region": "Azure 지역",
 	"Back": "뒤로가기",

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

@@ -234,7 +234,7 @@
 	"Content Extraction Engine": "",
 	"Context Length": "Konteksto ilgis",
 	"Continue Response": "Tęsti atsakymą",
-	"Continue with {{provider}}": "Tęstti su {{tiekėju}}",
+	"Continue with {{provider}}": "Tęsti su {{tiekėju}}",
 	"Continue with Email": "",
 	"Continue with LDAP": "",
 	"Control how message text is split for TTS requests. 'Punctuation' splits into sentences, 'paragraphs' splits into paragraphs, and 'none' keeps the message as a single string.": "",

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

@@ -43,7 +43,7 @@
 	"Add Reaction": "Dodaj reakcję",
 	"Add Tag": "Dodaj tag",
 	"Add Tags": "Dodaj tagi",
-	"Add text content": "Dodaj tekstową zawartość",
+	"Add text content": "Dodaj zawartość tekstową",
 	"Add User": "Dodaj użytkownika",
 	"Add User Group": "Dodaj grupę użytkowników",
 	"Adjusting these settings will apply changes universally to all users.": "Dostosowanie tych ustawień spowoduje wprowadzenie zmian dla wszystkich użytkowników.",
@@ -54,7 +54,7 @@
 	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorzy mają dostęp do wszystkich narzędzi przez cały czas; użytkownicy muszą mieć przydzielone narzędzia dla każdego modelu w przestrzeni roboczej.",
 	"Advanced Parameters": "Zaawansowane ustawienia",
 	"Advanced Params": "Zaawansowane ustawienia",
-	"All": "",
+	"All": "Wszystkie",
 	"All Documents": "Wszystkie dokumenty",
 	"All models deleted successfully": "Wszystkie modele zostały usunięte pomyślnie.",
 	"Allow Call": "",
@@ -74,8 +74,8 @@
 	"Already have an account?": "Czy masz już konto?",
 	"Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "",
 	"Always": "Zawsze",
-	"Always Collapse Code Blocks": "",
-	"Always Expand Details": "",
+	"Always Collapse Code Blocks": "Zawsze zwijaj bloki kodu",
+	"Always Expand Details": "Zawsze rozwiń szczegóły",
 	"Amazing": "Niesamowite",
 	"an assistant": "asystent",
 	"Analyzed": "Przeanalizowane",
@@ -147,8 +147,8 @@
 	"By {{name}}": "Przez {{name}}",
 	"Bypass Embedding and Retrieval": "",
 	"Calendar": "Kalendarz",
-	"Call": "Wywołanie",
-	"Call feature is not supported when using Web STT engine": "Funkcja wywołania nie jest obsługiwana podczas korzystania z silnika Web STT",
+	"Call": "Rozmowa",
+	"Call feature is not supported when using Web STT engine": "Funkcja rozmowy nie jest obsługiwana podczas korzystania z silnika Web STT",
 	"Camera": "Kamera",
 	"Cancel": "Anuluj",
 	"Capabilities": "Możliwości",
@@ -193,14 +193,14 @@
 	"click here.": "kliknij tutaj.",
 	"Click on the user role button to change a user's role.": "Kliknij przycisk roli użytkownika, aby zmienić jego uprawnienia.",
 	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Nie można było skopiować do schowka. Sprawdź ustawienia przeglądarki, aby przyznać wymagany dostęp.",
-	"Clone": "Sklonuj",
+	"Clone": "Duplikuj",
 	"Clone Chat": "Sklonuj czat",
 	"Clone of {{TITLE}}": "Klon {{TITLE}}",
 	"Close": "Zamknij",
 	"Code execution": "Wykonanie kodu",
 	"Code Execution": "Wykonanie kodu",
 	"Code Execution Engine": "Silnik wykonawczy kodu",
-	"Code Execution Timeout": "Limit czasu wykonania kodu",
+	"Code Execution Timeout": "Limit czasu wykonywania kodu",
 	"Code formatted successfully": "Kod został sformatowany pomyślnie.",
 	"Code Interpreter": "Interpreter kodu",
 	"Code Interpreter Engine": "Silnik interpretatora kodu",
@@ -245,7 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Skopiowano udostępniony URL czatu do schowka!",
 	"Copied to clipboard": "Skopiowane do schowka",
 	"Copy": "Skopiuj",
-	"Copy Formatted Text": "",
+	"Copy Formatted Text": "Skopiuj sformatowany tekst",
 	"Copy last code block": "Skopiuj ostatni fragment kodu",
 	"Copy last response": "Skopiuj ostatnią wypowiedź",
 	"Copy Link": "Skopiuj link",
@@ -283,7 +283,7 @@
 	"Default Models": "Domyślne modele",
 	"Default permissions": "Domyślne uprawnienia",
 	"Default permissions updated successfully": "Domyślne uprawnienia zaktualizowane pomyślnie",
-	"Default Prompt Suggestions": "Domyślne propozycje wpisów",
+	"Default Prompt Suggestions": "Domyślne propozycje promptów",
 	"Default to 389 or 636 if TLS is enabled": "Domyślnie użyj 389 lub 636, jeśli TLS jest włączony",
 	"Default to ALL": "Domyślne dla wszystkich",
 	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "",
@@ -316,12 +316,12 @@
 	"Direct Connections settings updated": "Ustawienia połączeń bezpośrednich zaktualizowane",
 	"Direct Tool Servers": "",
 	"Disabled": "Wyłączony",
-	"Discover a function": "Odkryj funkcję",
-	"Discover a model": "Odkryj model",
-	"Discover a prompt": "Odkryj prompty",
-	"Discover a tool": "Odkryj narzędzie",
+	"Discover a function": "Odkrywaj funkcję",
+	"Discover a model": "Odkrywaj model",
+	"Discover a prompt": "Odkrywaj prompty",
+	"Discover a tool": "Odkrywaj narzędzia",
 	"Discover how to use Open WebUI and seek support from the community.": "Odkryj, jak korzystać z Open WebUI i szukaj wsparcia w społeczności.",
-	"Discover wonders": "Odkryj cuda",
+	"Discover wonders": "Odkrywaj cuda",
 	"Discover, download, and explore custom functions": "Odkryj, pobierz i eksploruj niestandardowe funkcje",
 	"Discover, download, and explore custom prompts": "Odkryj, pobierz i eksploruj niestandardowe prompty",
 	"Discover, download, and explore custom tools": "Odkryj, pobierz i eksploruj niestandardowe narzędzia",
@@ -425,7 +425,7 @@
 	"Enter Jupyter Token": "Wprowadź token Jupyter",
 	"Enter Jupyter URL": "Podaj adres URL Jupytera",
 	"Enter Kagi Search API Key": "Wprowadź klucz wyszukiwania Kagi",
-	"Enter Key Behavior": "",
+	"Enter Key Behavior": "Zachowanie klawisza Enter",
 	"Enter language codes": "Wprowadź kody języków",
 	"Enter Mistral API Key": "",
 	"Enter Model ID": "Wprowadź ID modelu",
@@ -455,7 +455,7 @@
 	"Enter Sougou Search API sID": "",
 	"Enter Sougou Search API SK": "",
 	"Enter stop sequence": "Wprowadź sekwencję stop",
-	"Enter system prompt": "Wprowadź polecenie systemowe",
+	"Enter system prompt": "Wprowadź prompt systemowy",
 	"Enter system prompt here": "",
 	"Enter Tavily API Key": "Wprowadź klucz API Tavily",
 	"Enter Tavily Extract Depth": "",
@@ -624,7 +624,7 @@
 	"Import Models": "Importowanie modeli",
 	"Import Presets": "Importuj ustawienia",
 	"Import Prompts": "Importuj prompty",
-	"Import Tools": "Import narzędzi",
+	"Import Tools": "Importuj narzędzia",
 	"Include": "Włączyć",
 	"Include `--api-auth` flag when running stable-diffusion-webui": "Użyj flagi `--api-auth` podczas uruchamiania stable-diffusion-webui",
 	"Include `--api` flag when running stable-diffusion-webui": "Użyj flagi `--api` podczas uruchamiania stable-diffusion-webui.",
@@ -792,14 +792,14 @@
 	"num_thread (Ollama)": "num_thread (Ollama)",
 	"OAuth ID": "Identyfikator OAuth",
 	"October": "Październik",
-	"Off": "Wyłączony",
+	"Off": "Wyłączone",
 	"Okay, Let's Go!": "Okej, do dzieła!",
 	"OLED Dark": "Ciemny OLED",
 	"Ollama": "Ollama",
 	"Ollama API": "Interfejs API Ollama",
 	"Ollama API settings updated": "Ustawienia API Ollama zostały zaktualizowane",
 	"Ollama Version": "Wersja Ollama",
-	"On": "Włączony",
+	"On": "Włączone",
 	"OneDrive": "",
 	"Only alphanumeric characters and hyphens are allowed": "Dozwolone są tylko znaki alfanumeryczne i myślniki",
 	"Only alphanumeric characters and hyphens are allowed in the command string.": "W komendzie dozwolone są wyłącznie znaki alfanumeryczne i myślniki.",
@@ -855,7 +855,7 @@
 	"Playwright WebSocket URL": "",
 	"Please carefully review the following warnings:": "Proszę uważnie przejrzeć poniższe ostrzeżenia:",
 	"Please do not close the settings page while loading the model.": "Proszę nie zamykać strony ustawień podczas ładowania modelu.",
-	"Please enter a prompt": "Proszę podać promp",
+	"Please enter a prompt": "Proszę podać prompt",
 	"Please enter a valid path": "",
 	"Please enter a valid URL": "",
 	"Please fill in all fields.": "Proszę wypełnić wszystkie pola.",
@@ -874,7 +874,7 @@
 	"Prompt": "Wprowadź prompt: ",
 	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (np. podaj ciekawostkę o Imperium Rzymskim)",
 	"Prompt Autocompletion": "",
-	"Prompt Content": "Treść podpowiedzi",
+	"Prompt Content": "Treść promptu",
 	"Prompt created successfully": "Prompt został utworzony pomyślnie",
 	"Prompt suggestions": "Sugestie promptów",
 	"Prompt updated successfully": "Prompt został zaktualizowany pomyślnie.",
@@ -894,7 +894,7 @@
 	"Record voice": "Nagraj swój głos",
 	"Redirecting you to Open WebUI Community": "Przekierowujemy Cię do społeczności Open WebUI",
 	"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.": "",
-	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odnosić się do siebie jako \"Użytkownik\" (np. \"Użytkownik uczy się hiszpańskiego\")",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odnoś się do mnie jako \"Użytkownik\" (np. \"Użytkownik uczy się hiszpańskiego\")",
 	"References from": "Odniesienia do",
 	"Refused when it shouldn't have": "Odmówił, gdy nie powinien",
 	"Regenerate": "Wygeneruj ponownie",
@@ -948,18 +948,18 @@
 	"Search Filters": "Filtry wyszukiwania",
 	"search for tags": "wyszukiwanie tagów",
 	"Search Functions": "Funkcje wyszukiwania",
-	"Search Knowledge": "Wyszukaj wiedzę",
+	"Search Knowledge": "Przeszukaj wiedzę",
 	"Search Models": "Wyszukiwanie modeli",
 	"Search options": "Opcje wyszukiwania",
-	"Search Prompts": "Prompty wyszukiwania",
+	"Search Prompts": "Szukaj promptów",
 	"Search Result Count": "Liczba wyników wyszukiwania",
 	"Search the internet": "Przeszukaj internet",
-	"Search Tools": "Narzędzia wyszukiwania",
+	"Search Tools": "Szukaj narzędzi",
 	"SearchApi API Key": "Klucz API SearchApi",
 	"SearchApi Engine": "Search API Engine",
 	"Searched {{count}} sites": "Przeszukano {{count}} stron",
 	"Searching \"{{searchQuery}}\"": "Wyszukiwanie \"{{searchQuery}}\"",
-	"Searching Knowledge for \"{{searchQuery}}\"": "Wyszukiwanie wiedzy dla \"{{searchQuery}}\"",
+	"Searching Knowledge for \"{{searchQuery}}\"": "Przeszukiwanie wiedzy dla \"{{searchQuery}}\"",
 	"Searxng Query URL": "Adres URL zapytania Searxng",
 	"See readme.md for instructions": "Sprawdź readme.md dla instrukcji",
 	"See what's new": "Sprawdź nowości",
@@ -998,7 +998,7 @@
 	"Set Image Size": "Ustaw rozmiar obrazu",
 	"Set reranking model (e.g. {{model}})": "Skonfiguruj model ponownego rankingu (np. {{model}})",
 	"Set Sampler": "Próbnik samplera",
-	"Set Scheduler": "Ustawiacz harmonogramu",
+	"Set Scheduler": "Ustaw harmonogram",
 	"Set Steps": "Ustaw kroki",
 	"Set Task Model": "Konfiguracja modelu zadań",
 	"Set the number of layers, which will be off-loaded to GPU. Increasing this value can significantly improve performance for models that are optimized for GPU acceleration but may also consume more power and GPU resources.": "Ustaw liczbę warstw, które zostaną przeniesione na GPU. Zwiększenie tej wartości może znacząco poprawić wydajność dla modeli optymalizowanych pod kątem akceleracji GPU, ale także może zużywać więcej energii i zasobów GPU.",
@@ -1038,7 +1038,7 @@
 	"Speech Playback Speed": "Prędkość odtwarzania mowy",
 	"Speech recognition error: {{error}}": "Błąd rozpoznawania mowy: {{error}}",
 	"Speech-to-Text Engine": "Silnik konwersji mowy na tekst",
-	"Stop": "Zatrzymaj się",
+	"Stop": "Zatrzymaj",
 	"Stop Sequence": "Zatrzymaj sekwencję",
 	"Stream Chat Response": "Strumieniowanie odpowiedzi z czatu",
 	"STT Model": "Model STT",
@@ -1108,7 +1108,7 @@
 	"Title": "Tytuł",
 	"Title (e.g. Tell me a fun fact)": "Tytuł (na przykład {e.g.} Powiedz mi jakiś zabawny fakt)",
 	"Title Auto-Generation": "Automatyczne tworzenie tytułu",
-	"Title cannot be an empty string.": "Tytuł nie może być pustą stringiem.",
+	"Title cannot be an empty string.": "Tytuł nie może być pustym stringiem.",
 	"Title Generation": "Generowanie tytułów",
 	"Title Generation Prompt": "Prompt do generowania tytułu",
 	"TLS": "TLS",
@@ -1202,8 +1202,8 @@
 	"Valves updated successfully": "Zawory zaktualizowane pomyślnie",
 	"variable": "zmienna",
 	"variable to have them replaced with clipboard content.": "Zmienna, która ma zostać zastąpiona zawartością schowka.",
-	"Verify Connection": "",
-	"Verify SSL Certificate": "",
+	"Verify Connection": "Sprawdź połączenie",
+	"Verify SSL Certificate": "Sprawdź certyfikat SSL",
 	"Version": "Wersja",
 	"Version {{selectedVersion}} of {{totalVersions}}": "Wersja {{selectedVersion}} z {{totalVersions}}",
 	"View Replies": "Wyświetl odpowiedzi",

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

@@ -57,20 +57,20 @@
 	"All": "全部",
 	"All Documents": "所有文档",
 	"All models deleted successfully": "所有模型删除成功",
-	"Allow Call": "",
-	"Allow Chat Controls": "允许对话高级设置",
+	"Allow Call": "允许通话",
+	"Allow Chat Controls": "允许使用对话高级设置",
 	"Allow Chat Delete": "允许删除对话记录",
 	"Allow Chat Deletion": "允许删除对话记录",
 	"Allow Chat Edit": "允许编辑对话记录",
 	"Allow File Upload": "允许上传文件",
-	"Allow Multiple Models in Chat": "",
+	"Allow Multiple Models in Chat": "允许同时与多个模型聊天",
 	"Allow non-local voices": "允许调用非本地音色",
-	"Allow Speech to Text": "",
+	"Allow Speech to Text": "允许语音转文本",
 	"Allow Temporary Chat": "允许临时对话",
-	"Allow Text to Speech": "",
+	"Allow Text to Speech": "允许文本转语音",
 	"Allow User Location": "允许获取您的位置",
 	"Allow Voice Interruption in Call": "允许通话中的打断语音",
-	"Allowed Endpoints": "允许的端点",
+	"Allowed Endpoints": "允许的 API 端点",
 	"Already have an account?": "已经拥有账号了?",
 	"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.": "top_p 的替代方法,旨在确保质量和多样性之间的平衡。参数 p 表示相对于最可能令牌的概率,一个令牌被考虑的最小概率。例如,当 p=0.05 且最可能的令牌概率为 0.9 时,概率值小于 0.045 的词元将被过滤掉。",
 	"Always": "保持",
@@ -83,7 +83,7 @@
 	"and": "和",
 	"and {{COUNT}} more": "还有 {{COUNT}} 个",
 	"and create a new shared link.": "并创建一个新的分享链接。",
-	"Android": "",
+	"Android": "Android",
 	"API Base URL": "API 请求地址",
 	"API Key": "API 密钥",
 	"API Key created.": "API 密钥已创建。",
@@ -245,7 +245,7 @@
 	"Copied shared chat URL to clipboard!": "已复制此对话分享链接至剪贴板!",
 	"Copied to clipboard": "已复制到剪贴板",
 	"Copy": "复制",
-	"Copy Formatted Text": "",
+	"Copy Formatted Text": "复制格式化文本",
 	"Copy last code block": "复制最后一个代码块中的代码",
 	"Copy last response": "复制最后一次回复内容",
 	"Copy Link": "复制链接",
@@ -308,7 +308,7 @@
 	"Deleted User": "已删除用户",
 	"Describe your knowledge base and objectives": "描述您的知识库和目标",
 	"Description": "描述",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "自动检测 Artifacts",
 	"Didn't fully follow instructions": "没有完全遵照指示",
 	"Direct": "直接",
 	"Direct Connections": "直接连接",
@@ -364,7 +364,7 @@
 	"e.g. my_filter": "例如:my_filter",
 	"e.g. my_tools": "例如:my_tools",
 	"e.g. Tools for performing various operations": "例如:用于执行各种操作的工具",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "例如,'en-US,ja-JP'(留空以便自动检测)",
 	"Edit": "编辑",
 	"Edit Arena Model": "编辑竞技场模型",
 	"Edit Channel": "编辑频道",
@@ -605,8 +605,8 @@
 	"Hybrid Search": "混合搜索",
 	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "我已阅读并理解我的行为所带来的影响,明白执行任意代码所涉及的风险。且我已验证代码来源可信度。",
 	"ID": "ID",
-	"iframe Sandbox Allow Forms": "",
-	"iframe Sandbox Allow Same Origin": "",
+	"iframe Sandbox Allow Forms": "iframe 沙盒允许表单提交",
+	"iframe Sandbox Allow Same Origin": "iframe 沙盒允许同源访问",
 	"Ignite curiosity": "点燃好奇心",
 	"Image": "图像生成",
 	"Image Compression": "图像压缩",
@@ -667,7 +667,7 @@
 	"Label": "标签",
 	"Landing Page Mode": "默认主页样式",
 	"Language": "语言",
-	"Language Locales": "",
+	"Language Locales": "语言环境",
 	"Last Active": "最后在线时间",
 	"Last Modified": "最后修改时间",
 	"Last reply": "最后回复",
@@ -902,7 +902,7 @@
 	"Reindex Knowledge Base Vectors": "重建知识库向量",
 	"Release Notes": "更新日志",
 	"Relevance": "相关性",
-	"Relevance Threshold": "",
+	"Relevance Threshold": "相关性阈值",
 	"Remove": "移除",
 	"Remove Model": "移除模型",
 	"Rename": "重命名",
@@ -1203,7 +1203,7 @@
 	"variable": "变量",
 	"variable to have them replaced with clipboard content.": "变量将被剪贴板内容替换。",
 	"Verify Connection": "验证连接",
-	"Verify SSL Certificate": "",
+	"Verify SSL Certificate": "验证 SSL 证书",
 	"Version": "版本",
 	"Version {{selectedVersion}} of {{totalVersions}}": "版本 {{selectedVersion}}/{{totalVersions}}",
 	"View Replies": "查看回复",

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

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

+ 64 - 42
src/lib/utils/index.ts

@@ -1243,58 +1243,80 @@ export const convertOpenApiToToolPayload = (openApiSpec) => {
 
 	for (const [path, methods] of Object.entries(openApiSpec.paths)) {
 		for (const [method, operation] of Object.entries(methods)) {
-			const tool = {
-				type: 'function',
-				name: operation.operationId,
-				description: operation.description || operation.summary || 'No description available.',
-				parameters: {
-					type: 'object',
-					properties: {},
-					required: []
-				}
-			};
-
-			// Extract path and query parameters
-			if (operation.parameters) {
-				operation.parameters.forEach((param) => {
-					tool.parameters.properties[param.name] = {
-						type: param.schema.type,
-						description: param.schema.description || ''
-					};
-
-					if (param.required) {
-						tool.parameters.required.push(param.name);
+			if (operation?.operationId) {
+				const tool = {
+					type: 'function',
+					name: operation.operationId,
+					description: operation.description || operation.summary || 'No description available.',
+					parameters: {
+						type: 'object',
+						properties: {},
+						required: []
 					}
-				});
-			}
+				};
 
-			// Extract and recursively resolve requestBody if available
-			if (operation.requestBody) {
-				const content = operation.requestBody.content;
-				if (content && content['application/json']) {
-					const requestSchema = content['application/json'].schema;
-					const resolvedRequestSchema = resolveSchema(requestSchema, openApiSpec.components);
-
-					if (resolvedRequestSchema.properties) {
-						tool.parameters.properties = {
-							...tool.parameters.properties,
-							...resolvedRequestSchema.properties
+				// Extract path and query parameters
+				if (operation.parameters) {
+					operation.parameters.forEach((param) => {
+						let description = param.schema.description || param.description || '';
+						if (param.schema.enum && Array.isArray(param.schema.enum)) {
+							description += `. Possible values: ${param.schema.enum.join(', ')}`;
+						}
+						tool.parameters.properties[param.name] = {
+							type: param.schema.type,
+							description: description
 						};
 
-						if (resolvedRequestSchema.required) {
-							tool.parameters.required = [
-								...new Set([...tool.parameters.required, ...resolvedRequestSchema.required])
-							];
+						if (param.required) {
+							tool.parameters.required.push(param.name);
+						}
+					});
+				}
+
+				// Extract and recursively resolve requestBody if available
+				if (operation.requestBody) {
+					const content = operation.requestBody.content;
+					if (content && content['application/json']) {
+						const requestSchema = content['application/json'].schema;
+						const resolvedRequestSchema = resolveSchema(requestSchema, openApiSpec.components);
+
+						if (resolvedRequestSchema.properties) {
+							tool.parameters.properties = {
+								...tool.parameters.properties,
+								...resolvedRequestSchema.properties
+							};
+
+							if (resolvedRequestSchema.required) {
+								tool.parameters.required = [
+									...new Set([...tool.parameters.required, ...resolvedRequestSchema.required])
+								];
+							}
+						} else if (resolvedRequestSchema.type === 'array') {
+							tool.parameters = resolvedRequestSchema; // special case when root schema is an array
 						}
-					} else if (resolvedRequestSchema.type === 'array') {
-						tool.parameters = resolvedRequestSchema; // special case when root schema is an array
 					}
 				}
-			}
 
-			toolPayload.push(tool);
+				toolPayload.push(tool);
+			}
 		}
 	}
 
 	return toolPayload;
 };
+
+export const slugify = (str: string): string => {
+	return (
+		str
+			// 1. Normalize: separate accented letters into base + combining marks
+			.normalize('NFD')
+			// 2. Remove all combining marks (the accents)
+			.replace(/[\u0300-\u036f]/g, '')
+			// 3. Replace any sequence of whitespace with a single hyphen
+			.replace(/\s+/g, '-')
+			// 4. Remove all characters except alphanumeric characters and hyphens
+			.replace(/[^a-zA-Z0-9-]/g, '')
+			// 5. Convert to lowercase
+			.toLowerCase()
+	);
+};

+ 204 - 74
src/lib/utils/onedrive-file-picker.ts

@@ -2,70 +2,128 @@ import { PublicClientApplication } from '@azure/msal-browser';
 import type { PopupRequest } from '@azure/msal-browser';
 import { v4 as uuidv4 } from 'uuid';
 
-let CLIENT_ID = '';
+class OneDriveConfig {
+	private static instance: OneDriveConfig;
+	private clientId: string = '';
+	private sharepointUrl: string = '';
+	private msalInstance: PublicClientApplication | null = null;
+	private currentAuthorityType: 'personal' | 'organizations' = 'personal';
 
-async function getCredentials() {
-	if (CLIENT_ID) return;
+	private constructor() {}
 
-	const response = await fetch('/api/config');
-	if (!response.ok) {
-		throw new Error('Failed to fetch OneDrive credentials');
+	public static getInstance(): OneDriveConfig {
+		if (!OneDriveConfig.instance) {
+			OneDriveConfig.instance = new OneDriveConfig();
+		}
+		return OneDriveConfig.instance;
 	}
-	const config = await response.json();
-	CLIENT_ID = config.onedrive?.client_id;
-	if (!CLIENT_ID) {
-		throw new Error('OneDrive client ID not configured');
+
+	public async initialize(authorityType?: 'personal' | 'organizations'): Promise<void> {
+		if (authorityType && this.currentAuthorityType !== authorityType) {
+			this.currentAuthorityType = authorityType;
+			this.msalInstance = null;
+		}
+		await this.getCredentials();
 	}
-}
 
-let msalInstance: PublicClientApplication | null = null;
+	public async ensureInitialized(authorityType?: 'personal' | 'organizations'): Promise<void> {
+		await this.initialize(authorityType);
+	}
 
-// Initialize MSAL authentication
-async function initializeMsal() {
-	try {
-		if (!CLIENT_ID) {
-			await getCredentials();
+	private async getCredentials(): Promise<void> {
+		
+		const headers: HeadersInit = {
+			'Content-Type': 'application/json'
+		};
+
+		const response = await fetch('/api/config', { 
+			headers,
+			credentials: 'include'
+		});
+		
+		if (!response.ok) {
+			throw new Error('Failed to fetch OneDrive credentials');
+		}
+		
+		const config = await response.json();
+		
+		const newClientId = config.onedrive?.client_id;
+		const newSharepointUrl = config.onedrive?.sharepoint_url;
+		
+		if (!newClientId) {
+			throw new Error('OneDrive configuration is incomplete');
 		}
 
-		const msalParams = {
-			auth: {
-				authority: 'https://login.microsoftonline.com/consumers',
-				clientId: CLIENT_ID
-			}
-		};
+		this.clientId = newClientId;
+		this.sharepointUrl = newSharepointUrl;
+	}
+
+	public async getMsalInstance(authorityType?: 'personal' | 'organizations'): Promise<PublicClientApplication> {
+		await this.ensureInitialized(authorityType);
+		
+		if (!this.msalInstance) {
+			const authorityEndpoint = this.currentAuthorityType === 'organizations' ? 'common' : 'consumers';
+			const msalParams = {
+				auth: {
+					authority: `https://login.microsoftonline.com/${authorityEndpoint}`,
+					clientId: this.clientId
+				}
+			};
 
-		if (!msalInstance) {
-			msalInstance = new PublicClientApplication(msalParams);
-			if (msalInstance.initialize) {
-				await msalInstance.initialize();
+			this.msalInstance = new PublicClientApplication(msalParams);
+			if (this.msalInstance.initialize) {
+				await this.msalInstance.initialize();
 			}
 		}
 
-		return msalInstance;
-	} catch (error) {
-		throw new Error(
-			'MSAL initialization failed: ' + (error instanceof Error ? error.message : String(error))
-		);
+		return this.msalInstance;
+	}
+
+	public getAuthorityType(): 'personal' | 'organizations' {
+		return this.currentAuthorityType;
+	}
+
+	public getSharepointUrl(): string {
+		return this.sharepointUrl;
+	}
+
+	public getBaseUrl(): string {
+		if (this.currentAuthorityType === 'organizations') {
+			if (!this.sharepointUrl || this.sharepointUrl === '') {
+				throw new Error('Sharepoint URL not configured');
+			}
+
+			let sharePointBaseUrl = this.sharepointUrl.replace(/^https?:\/\//, '');
+			sharePointBaseUrl = sharePointBaseUrl.replace(/\/$/, '');
+
+			return `https://${sharePointBaseUrl}`;
+		} else {
+			return 'https://onedrive.live.com/picker';
+		}
 	}
 }
 
+
 // Retrieve OneDrive access token
-async function getToken(): Promise<string> {
-	const authParams: PopupRequest = { scopes: ['OneDrive.ReadWrite'] };
+async function getToken(resource?: string, authorityType?: 'personal' | 'organizations'): Promise<string> {
+	const config = OneDriveConfig.getInstance();
+	await config.ensureInitialized(authorityType);
+	
+	const currentAuthorityType = config.getAuthorityType();
+
+	const scopes = currentAuthorityType === 'organizations'
+		? [`${resource || config.getBaseUrl()}/.default`]
+		: ['OneDrive.ReadWrite'];
+	
+	const authParams: PopupRequest = { scopes };
 	let accessToken = '';
-	try {
-		msalInstance = await initializeMsal();
-		if (!msalInstance) {
-			throw new Error('MSAL not initialized');
-		}
 
+	try {
+		const msalInstance = await config.getMsalInstance(authorityType);
 		const resp = await msalInstance.acquireTokenSilent(authParams);
 		accessToken = resp.accessToken;
 	} catch (err) {
-		if (!msalInstance) {
-			throw new Error('MSAL not initialized');
-		}
-
+		const msalInstance = await config.getMsalInstance(authorityType);
 		try {
 			const resp = await msalInstance.loginPopup(authParams);
 			msalInstance.setActiveAccount(resp.account);
@@ -88,60 +146,121 @@ async function getToken(): Promise<string> {
 	return accessToken;
 }
 
-const baseUrl = 'https://onedrive.live.com/picker';
-const params = {
-	sdk: '8.0',
+interface PickerParams {
+	sdk: string;
 	entry: {
-		oneDrive: {
-			files: {}
-		}
-	},
-	authentication: {},
+		oneDrive: Record<string, unknown>;
+	};
+	authentication: Record<string, unknown>;
 	messaging: {
-		origin: window?.location?.origin,
-		channelId: uuidv4()
-	},
+		origin: string;
+		channelId: string;
+	};
 	typesAndSources: {
-		mode: 'files',
-		pivots: {
-			oneDrive: true,
-			recent: true
+		mode: string;
+		pivots: Record<string, boolean>;
+	};
+}
+
+interface PickerResult {
+	command?: string;
+	items?: OneDriveFileInfo[];
+	[key: string]: any;
+}
+
+// Get picker parameters based on account type
+function getPickerParams(): PickerParams {
+	const channelId = uuidv4();
+	const config = OneDriveConfig.getInstance();
+	
+	const params: PickerParams = {
+		sdk: '8.0',
+		entry: {
+			oneDrive: {}
+		},
+		authentication: {},
+		messaging: {
+			origin: window?.location?.origin || '',
+			channelId
+		},
+		typesAndSources: {
+			mode: 'files',
+			pivots: {
+				oneDrive: true,
+				recent: true
+			}
 		}
+	};
+	
+	// For personal accounts, set files object in oneDrive
+	if (config.getAuthorityType() !== 'organizations') {
+		params.entry.oneDrive = { files: {} };
 	}
-};
+	
+	return params;
+}
+
+interface OneDriveFileInfo {
+	id: string;
+	name: string;
+	parentReference: {
+		driveId: string;
+	};
+	'@sharePoint.endpoint': string;
+	[key: string]: any;
+}
 
 // Download file from OneDrive
-async function downloadOneDriveFile(fileInfo: any): Promise<Blob> {
-	const accessToken = await getToken();
+async function downloadOneDriveFile(fileInfo: OneDriveFileInfo, authorityType?: 'personal' | 'organizations'): Promise<Blob> {
+	const accessToken = await getToken(undefined, authorityType);
 	if (!accessToken) {
 		throw new Error('Unable to retrieve OneDrive access token.');
 	}
+	
+	// The endpoint URL is provided in the file info
 	const fileInfoUrl = `${fileInfo['@sharePoint.endpoint']}/drives/${fileInfo.parentReference.driveId}/items/${fileInfo.id}`;
+	
 	const response = await fetch(fileInfoUrl, {
 		headers: {
 			Authorization: `Bearer ${accessToken}`
 		}
 	});
+	
 	if (!response.ok) {
-		throw new Error('Failed to fetch file information.');
+		throw new Error(`Failed to fetch file information: ${response.status} ${response.statusText}`);
 	}
+	
 	const fileData = await response.json();
 	const downloadUrl = fileData['@content.downloadUrl'];
+	
+	if (!downloadUrl) {
+		throw new Error('Download URL not found in file data');
+	}
+	
 	const downloadResponse = await fetch(downloadUrl);
+	
 	if (!downloadResponse.ok) {
-		throw new Error('Failed to download file.');
+		throw new Error(`Failed to download file: ${downloadResponse.status} ${downloadResponse.statusText}`);
 	}
+	
 	return await downloadResponse.blob();
 }
 
 // Open OneDrive file picker and return selected file metadata
-export async function openOneDrivePicker(): Promise<any | null> {
+export async function openOneDrivePicker(authorityType?: 'personal' | 'organizations'): Promise<PickerResult | null> {
 	if (typeof window === 'undefined') {
 		throw new Error('Not in browser environment');
 	}
+
+	// Initialize OneDrive config with the specified authority type
+	const config = OneDriveConfig.getInstance();
+	await config.initialize(authorityType);
+	
 	return new Promise((resolve, reject) => {
 		let pickerWindow: Window | null = null;
 		let channelPort: MessagePort | null = null;
+		const params = getPickerParams();
+		const baseUrl = config.getBaseUrl();
 
 		const handleWindowMessage = (event: MessageEvent) => {
 			if (event.source !== pickerWindow) return;
@@ -166,7 +285,9 @@ export async function openOneDrivePicker(): Promise<any | null> {
 					switch (command.command) {
 						case 'authenticate': {
 							try {
-								const newToken = await getToken();
+								// Pass the resource from the command for org accounts
+								const resource = config.getAuthorityType() === 'organizations' ? command.resource : undefined;
+								const newToken = await getToken(resource, authorityType);
 								if (newToken) {
 									channelPort?.postMessage({
 										type: 'result',
@@ -178,9 +299,12 @@ export async function openOneDrivePicker(): Promise<any | null> {
 								}
 							} catch (err) {
 								channelPort?.postMessage({
-									result: 'error',
-									error: { code: 'tokenError', message: 'Failed to get token' },
-									isExpected: true
+									type: 'result',
+									id: portData.id,
+									data: {
+										result: 'error',
+										error: { code: 'tokenError', message: 'Failed to get token' }
+									}
 								});
 							}
 							break;
@@ -227,7 +351,7 @@ export async function openOneDrivePicker(): Promise<any | null> {
 
 		const initializePicker = async () => {
 			try {
-				const authToken = await getToken();
+				const authToken = await getToken(undefined, authorityType);
 				if (!authToken) {
 					return reject(new Error('Failed to acquire access token'));
 				}
@@ -240,8 +364,14 @@ export async function openOneDrivePicker(): Promise<any | null> {
 				const queryString = new URLSearchParams({
 					filePicker: JSON.stringify(params)
 				});
-				const url = `${baseUrl}?${queryString.toString()}`;
 
+				let url = '';
+				if(config.getAuthorityType() === 'organizations') {
+					url = baseUrl + `/_layouts/15/FilePicker.aspx?${queryString}`;
+				} else {
+					url = baseUrl + `?${queryString}`;
+				}
+			
 				const form = pickerWindow.document.createElement('form');
 				form.setAttribute('action', url);
 				form.setAttribute('method', 'POST');
@@ -268,17 +398,17 @@ export async function openOneDrivePicker(): Promise<any | null> {
 }
 
 // Pick and download file from OneDrive
-export async function pickAndDownloadFile(): Promise<{ blob: Blob; name: string } | null> {
-	const pickerResult = await openOneDrivePicker();
+export async function pickAndDownloadFile(authorityType?: 'personal' | 'organizations'): Promise<{ blob: Blob; name: string } | null> {
+	const pickerResult = await openOneDrivePicker(authorityType);
 
 	if (!pickerResult || !pickerResult.items || pickerResult.items.length === 0) {
 		return null;
 	}
 
 	const selectedFile = pickerResult.items[0];
-	const blob = await downloadOneDriveFile(selectedFile);
+	const blob = await downloadOneDriveFile(selectedFile, authorityType);
 
 	return { blob, name: selectedFile.name };
 }
 
-export { downloadOneDriveFile };
+export { downloadOneDriveFile };

+ 1 - 0
src/routes/+layout.svelte

@@ -639,4 +639,5 @@
 			: 'light'}
 	richColors
 	position="top-right"
+	closeButton
 />

Неке датотеке нису приказане због велике количине промена