Explorar el Código

Resolve merge conflicts in French translations

Morgan Blangeois hace 10 meses
padre
commit
f548762892
Se han modificado 75 ficheros con 1845 adiciones y 741 borrados
  1. 2 1
      .dockerignore
  2. 1 0
      .gitignore
  3. 2 1
      backend/apps/audio/main.py
  4. 0 1
      backend/apps/images/main.py
  5. 4 1
      backend/apps/openai/main.py
  6. 113 41
      backend/apps/rag/main.py
  7. 9 9
      backend/apps/rag/utils.py
  8. 3 0
      backend/apps/webui/main.py
  9. 1 2
      backend/apps/webui/models/functions.py
  10. 1 2
      backend/apps/webui/models/tools.py
  11. 24 8
      backend/config.py
  12. 352 205
      backend/main.py
  13. 7 7
      backend/requirements.txt
  14. 14 6
      backend/utils/misc.py
  15. 2 2
      package-lock.json
  16. 1 1
      package.json
  17. 6 0
      src/lib/apis/rag/index.ts
  18. 51 1
      src/lib/components/admin/Settings/Documents.svelte
  19. 34 8
      src/lib/components/admin/Settings/Pipelines.svelte
  20. 39 10
      src/lib/components/chat/Chat.svelte
  21. 4 4
      src/lib/components/chat/MessageInput/Documents.svelte
  22. 62 58
      src/lib/components/chat/Messages/CompareMessages.svelte
  23. 37 9
      src/lib/components/chat/Settings/Valves.svelte
  24. 13 6
      src/lib/components/chat/Tags.svelte
  25. 19 0
      src/lib/components/icons/Bookmark.svelte
  26. 19 0
      src/lib/components/icons/BookmarkSlash.svelte
  27. 124 0
      src/lib/components/icons/ChatMenu.svelte
  28. 19 0
      src/lib/components/icons/Star.svelte
  29. 39 3
      src/lib/components/layout/Sidebar.svelte
  30. 8 1
      src/lib/components/layout/Sidebar/ChatItem.svelte
  31. 43 1
      src/lib/components/layout/Sidebar/ChatMenu.svelte
  32. 37 9
      src/lib/components/workspace/common/ValvesModal.svelte
  33. 9 0
      src/lib/i18n/locales/ar-BH/translation.json
  34. 9 0
      src/lib/i18n/locales/bg-BG/translation.json
  35. 9 0
      src/lib/i18n/locales/bn-BD/translation.json
  36. 9 0
      src/lib/i18n/locales/ca-ES/translation.json
  37. 9 0
      src/lib/i18n/locales/ceb-PH/translation.json
  38. 344 335
      src/lib/i18n/locales/de-DE/translation.json
  39. 9 0
      src/lib/i18n/locales/dg-DG/translation.json
  40. 9 0
      src/lib/i18n/locales/en-GB/translation.json
  41. 9 0
      src/lib/i18n/locales/en-US/translation.json
  42. 9 0
      src/lib/i18n/locales/es-ES/translation.json
  43. 9 0
      src/lib/i18n/locales/fa-IR/translation.json
  44. 9 0
      src/lib/i18n/locales/fi-FI/translation.json
  45. 8 1
      src/lib/i18n/locales/fr-CA/translation.json
  46. 7 0
      src/lib/i18n/locales/fr-FR/translation.json
  47. 9 0
      src/lib/i18n/locales/he-IL/translation.json
  48. 9 0
      src/lib/i18n/locales/hi-IN/translation.json
  49. 9 0
      src/lib/i18n/locales/hr-HR/translation.json
  50. 17 8
      src/lib/i18n/locales/id-ID/translation.json
  51. 9 0
      src/lib/i18n/locales/it-IT/translation.json
  52. 9 0
      src/lib/i18n/locales/ja-JP/translation.json
  53. 9 0
      src/lib/i18n/locales/ka-GE/translation.json
  54. 9 0
      src/lib/i18n/locales/ko-KR/translation.json
  55. 9 0
      src/lib/i18n/locales/lt-LT/translation.json
  56. 9 0
      src/lib/i18n/locales/nb-NO/translation.json
  57. 9 0
      src/lib/i18n/locales/nl-NL/translation.json
  58. 9 0
      src/lib/i18n/locales/pa-IN/translation.json
  59. 9 0
      src/lib/i18n/locales/pl-PL/translation.json
  60. 9 0
      src/lib/i18n/locales/pt-BR/translation.json
  61. 9 0
      src/lib/i18n/locales/pt-PT/translation.json
  62. 9 0
      src/lib/i18n/locales/ru-RU/translation.json
  63. 9 0
      src/lib/i18n/locales/sr-RS/translation.json
  64. 9 0
      src/lib/i18n/locales/sv-SE/translation.json
  65. 9 0
      src/lib/i18n/locales/tk-TW/translation.json
  66. 9 0
      src/lib/i18n/locales/tr-TR/translation.json
  67. 9 0
      src/lib/i18n/locales/uk-UA/translation.json
  68. 9 0
      src/lib/i18n/locales/vi-VN/translation.json
  69. 9 0
      src/lib/i18n/locales/zh-CN/translation.json
  70. 9 0
      src/lib/i18n/locales/zh-TW/translation.json
  71. 1 0
      src/lib/stores/index.ts
  72. 18 0
      src/routes/(app)/workspace/functions/create/+page.svelte
  73. 18 0
      src/routes/(app)/workspace/functions/edit/+page.svelte
  74. 18 0
      src/routes/(app)/workspace/tools/create/+page.svelte
  75. 18 0
      src/routes/(app)/workspace/tools/edit/+page.svelte

+ 2 - 1
.dockerignore

@@ -10,7 +10,8 @@ node_modules
 vite.config.js.timestamp-*
 vite.config.ts.timestamp-*
 __pycache__
-.env
+.idea
+venv
 _old
 uploads
 .ipynb_checkpoints

+ 1 - 0
.gitignore

@@ -306,3 +306,4 @@ dist
 # cypress artifacts
 cypress/videos
 cypress/screenshots
+.vscode/settings.json

+ 2 - 1
backend/apps/audio/main.py

@@ -14,7 +14,6 @@ from fastapi import (
 from fastapi.responses import StreamingResponse, JSONResponse, FileResponse
 
 from fastapi.middleware.cors import CORSMiddleware
-from faster_whisper import WhisperModel
 from pydantic import BaseModel
 
 import uuid
@@ -277,6 +276,8 @@ def transcribe(
             f.close()
 
         if app.state.config.STT_ENGINE == "":
+            from faster_whisper import WhisperModel
+
             whisper_kwargs = {
                 "model_size_or_path": WHISPER_MODEL,
                 "device": whisper_device_type,

+ 0 - 1
backend/apps/images/main.py

@@ -12,7 +12,6 @@ from fastapi import (
     Form,
 )
 from fastapi.middleware.cors import CORSMiddleware
-from faster_whisper import WhisperModel
 
 from constants import ERROR_MESSAGES
 from utils.utils import (

+ 4 - 1
backend/apps/openai/main.py

@@ -25,6 +25,7 @@ from utils.task import prompt_template
 from config import (
     SRC_LOG_LEVELS,
     ENABLE_OPENAI_API,
+    AIOHTTP_CLIENT_TIMEOUT,
     OPENAI_API_BASE_URLS,
     OPENAI_API_KEYS,
     CACHE_DIR,
@@ -463,7 +464,9 @@ async def generate_chat_completion(
     streaming = False
 
     try:
-        session = aiohttp.ClientSession(trust_env=True)
+        session = aiohttp.ClientSession(
+            trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT)
+        )
         r = await session.request(
             method="POST",
             url=f"{url}/chat/completions",

+ 113 - 41
backend/apps/rag/main.py

@@ -48,8 +48,6 @@ import mimetypes
 import uuid
 import json
 
-import sentence_transformers
-
 from apps.webui.models.documents import (
     Documents,
     DocumentForm,
@@ -93,6 +91,8 @@ from config import (
     SRC_LOG_LEVELS,
     UPLOAD_DIR,
     DOCS_DIR,
+    CONTENT_EXTRACTION_ENGINE,
+    TIKA_SERVER_URL,
     RAG_TOP_K,
     RAG_RELEVANCE_THRESHOLD,
     RAG_EMBEDDING_ENGINE,
@@ -148,6 +148,9 @@ app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION = (
     ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION
 )
 
+app.state.config.CONTENT_EXTRACTION_ENGINE = CONTENT_EXTRACTION_ENGINE
+app.state.config.TIKA_SERVER_URL = TIKA_SERVER_URL
+
 app.state.config.CHUNK_SIZE = CHUNK_SIZE
 app.state.config.CHUNK_OVERLAP = CHUNK_OVERLAP
 
@@ -190,6 +193,8 @@ def update_embedding_model(
     update_model: bool = False,
 ):
     if embedding_model and app.state.config.RAG_EMBEDDING_ENGINE == "":
+        import sentence_transformers
+
         app.state.sentence_transformer_ef = sentence_transformers.SentenceTransformer(
             get_model_path(embedding_model, update_model),
             device=DEVICE_TYPE,
@@ -204,6 +209,8 @@ def update_reranking_model(
     update_model: bool = False,
 ):
     if reranking_model:
+        import sentence_transformers
+
         app.state.sentence_transformer_rf = sentence_transformers.CrossEncoder(
             get_model_path(reranking_model, update_model),
             device=DEVICE_TYPE,
@@ -388,6 +395,10 @@ async def get_rag_config(user=Depends(get_admin_user)):
     return {
         "status": True,
         "pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
+        "content_extraction": {
+            "engine": app.state.config.CONTENT_EXTRACTION_ENGINE,
+            "tika_server_url": app.state.config.TIKA_SERVER_URL,
+        },
         "chunk": {
             "chunk_size": app.state.config.CHUNK_SIZE,
             "chunk_overlap": app.state.config.CHUNK_OVERLAP,
@@ -417,6 +428,11 @@ async def get_rag_config(user=Depends(get_admin_user)):
     }
 
 
+class ContentExtractionConfig(BaseModel):
+    engine: str = ""
+    tika_server_url: Optional[str] = None
+
+
 class ChunkParamUpdateForm(BaseModel):
     chunk_size: int
     chunk_overlap: int
@@ -450,6 +466,7 @@ class WebConfig(BaseModel):
 
 class ConfigUpdateForm(BaseModel):
     pdf_extract_images: Optional[bool] = None
+    content_extraction: Optional[ContentExtractionConfig] = None
     chunk: Optional[ChunkParamUpdateForm] = None
     youtube: Optional[YoutubeLoaderConfig] = None
     web: Optional[WebConfig] = None
@@ -463,6 +480,11 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
         else app.state.config.PDF_EXTRACT_IMAGES
     )
 
+    if form_data.content_extraction is not None:
+        log.info(f"Updating text settings: {form_data.content_extraction}")
+        app.state.config.CONTENT_EXTRACTION_ENGINE = form_data.content_extraction.engine
+        app.state.config.TIKA_SERVER_URL = form_data.content_extraction.tika_server_url
+
     if form_data.chunk is not None:
         app.state.config.CHUNK_SIZE = form_data.chunk.chunk_size
         app.state.config.CHUNK_OVERLAP = form_data.chunk.chunk_overlap
@@ -499,6 +521,10 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
     return {
         "status": True,
         "pdf_extract_images": app.state.config.PDF_EXTRACT_IMAGES,
+        "content_extraction": {
+            "engine": app.state.config.CONTENT_EXTRACTION_ENGINE,
+            "tika_server_url": app.state.config.TIKA_SERVER_URL,
+        },
         "chunk": {
             "chunk_size": app.state.config.CHUNK_SIZE,
             "chunk_overlap": app.state.config.CHUNK_OVERLAP,
@@ -985,6 +1011,41 @@ def store_docs_in_vector_db(docs, collection_name, overwrite: bool = False) -> b
         return False
 
 
+class TikaLoader:
+    def __init__(self, file_path, mime_type=None):
+        self.file_path = file_path
+        self.mime_type = mime_type
+
+    def load(self) -> List[Document]:
+        with open(self.file_path, "rb") as f:
+            data = f.read()
+
+        if self.mime_type is not None:
+            headers = {"Content-Type": self.mime_type}
+        else:
+            headers = {}
+
+        endpoint = app.state.config.TIKA_SERVER_URL
+        if not endpoint.endswith("/"):
+            endpoint += "/"
+        endpoint += "tika/text"
+
+        r = requests.put(endpoint, data=data, headers=headers)
+
+        if r.ok:
+            raw_metadata = r.json()
+            text = raw_metadata.get("X-TIKA:content", "<No text content found>")
+
+            if "Content-Type" in raw_metadata:
+                headers["Content-Type"] = raw_metadata["Content-Type"]
+
+            log.info("Tika extracted text: %s", text)
+
+            return [Document(page_content=text, metadata=headers)]
+        else:
+            raise Exception(f"Error calling Tika: {r.reason}")
+
+
 def get_loader(filename: str, file_content_type: str, file_path: str):
     file_ext = filename.split(".")[-1].lower()
     known_type = True
@@ -1035,47 +1096,58 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
         "msg",
     ]
 
-    if file_ext == "pdf":
-        loader = PyPDFLoader(
-            file_path, extract_images=app.state.config.PDF_EXTRACT_IMAGES
-        )
-    elif file_ext == "csv":
-        loader = CSVLoader(file_path)
-    elif file_ext == "rst":
-        loader = UnstructuredRSTLoader(file_path, mode="elements")
-    elif file_ext == "xml":
-        loader = UnstructuredXMLLoader(file_path)
-    elif file_ext in ["htm", "html"]:
-        loader = BSHTMLLoader(file_path, open_encoding="unicode_escape")
-    elif file_ext == "md":
-        loader = UnstructuredMarkdownLoader(file_path)
-    elif file_content_type == "application/epub+zip":
-        loader = UnstructuredEPubLoader(file_path)
-    elif (
-        file_content_type
-        == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
-        or file_ext in ["doc", "docx"]
+    if (
+        app.state.config.CONTENT_EXTRACTION_ENGINE == "tika"
+        and app.state.config.TIKA_SERVER_URL
     ):
-        loader = Docx2txtLoader(file_path)
-    elif file_content_type in [
-        "application/vnd.ms-excel",
-        "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
-    ] or file_ext in ["xls", "xlsx"]:
-        loader = UnstructuredExcelLoader(file_path)
-    elif file_content_type in [
-        "application/vnd.ms-powerpoint",
-        "application/vnd.openxmlformats-officedocument.presentationml.presentation",
-    ] or file_ext in ["ppt", "pptx"]:
-        loader = UnstructuredPowerPointLoader(file_path)
-    elif file_ext == "msg":
-        loader = OutlookMessageLoader(file_path)
-    elif file_ext in known_source_ext or (
-        file_content_type and file_content_type.find("text/") >= 0
-    ):
-        loader = TextLoader(file_path, autodetect_encoding=True)
+        if file_ext in known_source_ext or (
+            file_content_type and file_content_type.find("text/") >= 0
+        ):
+            loader = TextLoader(file_path, autodetect_encoding=True)
+        else:
+            loader = TikaLoader(file_path, file_content_type)
     else:
-        loader = TextLoader(file_path, autodetect_encoding=True)
-        known_type = False
+        if file_ext == "pdf":
+            loader = PyPDFLoader(
+                file_path, extract_images=app.state.config.PDF_EXTRACT_IMAGES
+            )
+        elif file_ext == "csv":
+            loader = CSVLoader(file_path)
+        elif file_ext == "rst":
+            loader = UnstructuredRSTLoader(file_path, mode="elements")
+        elif file_ext == "xml":
+            loader = UnstructuredXMLLoader(file_path)
+        elif file_ext in ["htm", "html"]:
+            loader = BSHTMLLoader(file_path, open_encoding="unicode_escape")
+        elif file_ext == "md":
+            loader = UnstructuredMarkdownLoader(file_path)
+        elif file_content_type == "application/epub+zip":
+            loader = UnstructuredEPubLoader(file_path)
+        elif (
+            file_content_type
+            == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
+            or file_ext in ["doc", "docx"]
+        ):
+            loader = Docx2txtLoader(file_path)
+        elif file_content_type in [
+            "application/vnd.ms-excel",
+            "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+        ] or file_ext in ["xls", "xlsx"]:
+            loader = UnstructuredExcelLoader(file_path)
+        elif file_content_type in [
+            "application/vnd.ms-powerpoint",
+            "application/vnd.openxmlformats-officedocument.presentationml.presentation",
+        ] or file_ext in ["ppt", "pptx"]:
+            loader = UnstructuredPowerPointLoader(file_path)
+        elif file_ext == "msg":
+            loader = OutlookMessageLoader(file_path)
+        elif file_ext in known_source_ext or (
+            file_content_type and file_content_type.find("text/") >= 0
+        ):
+            loader = TextLoader(file_path, autodetect_encoding=True)
+        else:
+            loader = TextLoader(file_path, autodetect_encoding=True)
+            known_type = False
 
     return loader, known_type
 

+ 9 - 9
backend/apps/rag/utils.py

@@ -294,14 +294,16 @@ def get_rag_context(
 
         extracted_collections.extend(collection_names)
 
-    context_string = ""
-
+    contexts = []
     citations = []
+
     for context in relevant_contexts:
         try:
             if "documents" in context:
-                context_string += "\n\n".join(
-                    [text for text in context["documents"][0] if text is not None]
+                contexts.append(
+                    "\n\n".join(
+                        [text for text in context["documents"][0] if text is not None]
+                    )
                 )
 
                 if "metadatas" in context:
@@ -315,9 +317,7 @@ def get_rag_context(
         except Exception as e:
             log.exception(e)
 
-    context_string = context_string.strip()
-
-    return context_string, citations
+    return contexts, citations
 
 
 def get_model_path(model: str, update_model: bool = False):
@@ -442,8 +442,6 @@ from langchain_core.documents import BaseDocumentCompressor, Document
 from langchain_core.callbacks import Callbacks
 from langchain_core.pydantic_v1 import Extra
 
-from sentence_transformers import util
-
 
 class RerankCompressor(BaseDocumentCompressor):
     embedding_function: Any
@@ -468,6 +466,8 @@ class RerankCompressor(BaseDocumentCompressor):
                 [(query, doc.page_content) for doc in documents]
             )
         else:
+            from sentence_transformers import util
+
             query_embedding = self.embedding_function(query)
             document_embedding = self.embedding_function(
                 [doc.page_content for doc in documents]

+ 3 - 0
backend/apps/webui/main.py

@@ -259,6 +259,9 @@ async def generate_function_chat_completion(form_data, user):
                         if isinstance(line, BaseModel):
                             line = line.model_dump_json()
                             line = f"data: {line}"
+                        if isinstance(line, dict):
+                            line = f"data: {json.dumps(line)}"
+
                         try:
                             line = line.decode("utf-8")
                         except:

+ 1 - 2
backend/apps/webui/models/functions.py

@@ -214,8 +214,7 @@ class FunctionsTable:
             user_settings["functions"]["valves"][id] = valves
 
             # Update the user settings in the database
-            query = Users.update_user_by_id(user_id, {"settings": user_settings})
-            query.execute()
+            Users.update_user_by_id(user_id, {"settings": user_settings})
 
             return user_settings["functions"]["valves"][id]
         except Exception as e:

+ 1 - 2
backend/apps/webui/models/tools.py

@@ -170,8 +170,7 @@ class ToolsTable:
             user_settings["tools"]["valves"][id] = valves
 
             # Update the user settings in the database
-            query = Users.update_user_by_id(user_id, {"settings": user_settings})
-            query.execute()
+            Users.update_user_by_id(user_id, {"settings": user_settings})
 
             return user_settings["tools"]["valves"][id]
         except Exception as e:

+ 24 - 8
backend/config.py

@@ -5,9 +5,8 @@ import importlib.metadata
 import pkgutil
 import chromadb
 from chromadb import Settings
-from base64 import b64encode
 from bs4 import BeautifulSoup
-from typing import TypeVar, Generic, Union
+from typing import TypeVar, Generic
 from pydantic import BaseModel
 from typing import Optional
 
@@ -19,7 +18,6 @@ import markdown
 import requests
 import shutil
 
-from secrets import token_bytes
 from constants import ERROR_MESSAGES
 
 ####################################
@@ -768,12 +766,14 @@ class BannerModel(BaseModel):
     dismissible: bool
     timestamp: int
 
+try:
+    banners = json.loads(os.environ.get("WEBUI_BANNERS", "[]"))
+    banners = [BannerModel(**banner) for banner in banners]
+except Exception as e:
+    print(f"Error loading WEBUI_BANNERS: {e}")
+    banners = []
 
-WEBUI_BANNERS = PersistentConfig(
-    "WEBUI_BANNERS",
-    "ui.banners",
-    [BannerModel(**banner) for banner in json.loads("[]")],
-)
+WEBUI_BANNERS = PersistentConfig("WEBUI_BANNERS", "ui.banners", banners)
 
 
 SHOW_ADMIN_DETAILS = PersistentConfig(
@@ -885,6 +885,22 @@ WEBUI_SESSION_COOKIE_SECURE = os.environ.get(
 if WEBUI_AUTH and WEBUI_SECRET_KEY == "":
     raise ValueError(ERROR_MESSAGES.ENV_VAR_NOT_FOUND)
 
+####################################
+# RAG document content extraction
+####################################
+
+CONTENT_EXTRACTION_ENGINE = PersistentConfig(
+    "CONTENT_EXTRACTION_ENGINE",
+    "rag.CONTENT_EXTRACTION_ENGINE",
+    os.environ.get("CONTENT_EXTRACTION_ENGINE", "").lower(),
+)
+
+TIKA_SERVER_URL = PersistentConfig(
+    "TIKA_SERVER_URL",
+    "rag.tika_server_url",
+    os.getenv("TIKA_SERVER_URL", "http://tika:9998"),  # Default for sidecar deployment
+)
+
 ####################################
 # RAG
 ####################################

+ 352 - 205
backend/main.py

@@ -33,7 +33,7 @@ from starlette.middleware.sessions import SessionMiddleware
 from starlette.responses import StreamingResponse, Response, RedirectResponse
 
 
-from apps.socket.main import app as socket_app
+from apps.socket.main import sio, app as socket_app
 from apps.ollama.main import (
     app as ollama_app,
     OpenAIChatCompletionForm,
@@ -212,8 +212,79 @@ origins = ["*"]
 ##################################
 
 
+async def get_body_and_model_and_user(request):
+    # Read the original request body
+    body = await request.body()
+    body_str = body.decode("utf-8")
+    body = json.loads(body_str) if body_str else {}
+
+    model_id = body["model"]
+    if model_id not in app.state.MODELS:
+        raise "Model not found"
+    model = app.state.MODELS[model_id]
+
+    user = get_current_user(
+        request,
+        get_http_authorization_cred(request.headers.get("Authorization")),
+    )
+
+    return body, model, user
+
+
+def get_task_model_id(default_model_id):
+    # Set the task model
+    task_model_id = default_model_id
+    # Check if the user has a custom task model and use that model
+    if app.state.MODELS[task_model_id]["owned_by"] == "ollama":
+        if (
+            app.state.config.TASK_MODEL
+            and app.state.config.TASK_MODEL in app.state.MODELS
+        ):
+            task_model_id = app.state.config.TASK_MODEL
+    else:
+        if (
+            app.state.config.TASK_MODEL_EXTERNAL
+            and app.state.config.TASK_MODEL_EXTERNAL in app.state.MODELS
+        ):
+            task_model_id = app.state.config.TASK_MODEL_EXTERNAL
+
+    return task_model_id
+
+
+def get_filter_function_ids(model):
+    def get_priority(function_id):
+        function = Functions.get_function_by_id(function_id)
+        if function is not None and hasattr(function, "valves"):
+            return (function.valves if function.valves else {}).get("priority", 0)
+        return 0
+
+    filter_ids = [function.id for function in Functions.get_global_filter_functions()]
+    if "info" in model and "meta" in model["info"]:
+        filter_ids.extend(model["info"]["meta"].get("filterIds", []))
+        filter_ids = list(set(filter_ids))
+
+    enabled_filter_ids = [
+        function.id
+        for function in Functions.get_functions_by_type("filter", active_only=True)
+    ]
+
+    filter_ids = [
+        filter_id for filter_id in filter_ids if filter_id in enabled_filter_ids
+    ]
+
+    filter_ids.sort(key=get_priority)
+    return filter_ids
+
+
 async def get_function_call_response(
-    messages, files, tool_id, template, task_model_id, user
+    messages,
+    files,
+    tool_id,
+    template,
+    task_model_id,
+    user,
+    model,
+    __event_emitter__=None,
 ):
     tool = Tools.get_tool_by_id(tool_id)
     tools_specs = json.dumps(tool.specs, indent=2)
@@ -350,6 +421,13 @@ async def get_function_call_response(
                             "__id__": tool_id,
                         }
 
+                    if "__event_emitter__" in sig.parameters:
+                        # Call the function with the '__event_emitter__' parameter included
+                        params = {
+                            **params,
+                            "__event_emitter__": __event_emitter__,
+                        }
+
                     if inspect.iscoroutinefunction(function):
                         function_result = await function(**params)
                     else:
@@ -373,227 +451,267 @@ async def get_function_call_response(
     return None, None, False
 
 
-class ChatCompletionMiddleware(BaseHTTPMiddleware):
-    async def dispatch(self, request: Request, call_next):
-        data_items = []
+async def chat_completion_functions_handler(body, model, user, __event_emitter__):
+    skip_files = None
+
+    filter_ids = get_filter_function_ids(model)
+    for filter_id in filter_ids:
+        filter = Functions.get_function_by_id(filter_id)
+        if filter:
+            if filter_id in webui_app.state.FUNCTIONS:
+                function_module = webui_app.state.FUNCTIONS[filter_id]
+            else:
+                function_module, function_type, frontmatter = (
+                    load_function_module_by_id(filter_id)
+                )
+                webui_app.state.FUNCTIONS[filter_id] = function_module
+
+            # Check if the function has a file_handler variable
+            if hasattr(function_module, "file_handler"):
+                skip_files = function_module.file_handler
+
+            if hasattr(function_module, "valves") and hasattr(
+                function_module, "Valves"
+            ):
+                valves = Functions.get_function_valves_by_id(filter_id)
+                function_module.valves = function_module.Valves(
+                    **(valves if valves else {})
+                )
+
+            try:
+                if hasattr(function_module, "inlet"):
+                    inlet = function_module.inlet
+
+                    # Get the signature of the function
+                    sig = inspect.signature(inlet)
+                    params = {"body": body}
+
+                    if "__user__" in sig.parameters:
+                        __user__ = {
+                            "id": user.id,
+                            "email": user.email,
+                            "name": user.name,
+                            "role": user.role,
+                        }
+
+                        try:
+                            if hasattr(function_module, "UserValves"):
+                                __user__["valves"] = function_module.UserValves(
+                                    **Functions.get_user_valves_by_id_and_user_id(
+                                        filter_id, user.id
+                                    )
+                                )
+                        except Exception as e:
+                            print(e)
+
+                        params = {**params, "__user__": __user__}
+
+                    if "__id__" in sig.parameters:
+                        params = {
+                            **params,
+                            "__id__": filter_id,
+                        }
+
+                    if "__model__" in sig.parameters:
+                        params = {
+                            **params,
+                            "__model__": model,
+                        }
+                    if "__event_emitter__" in sig.parameters:
+                        params = {
+                            **params,
+                            "__event_emitter__": __event_emitter__,
+                        }
+
+                    if inspect.iscoroutinefunction(inlet):
+                        body = await inlet(**params)
+                    else:
+                        body = inlet(**params)
+
+            except Exception as e:
+                print(f"Error: {e}")
+                raise e
+
+    if skip_files:
+        if "files" in body:
+            del body["files"]
+
+    return body, {}
+
+
+async def chat_completion_tools_handler(body, model, user, __event_emitter__):
+    skip_files = None
+
+    contexts = []
+    citations = None
+
+    task_model_id = get_task_model_id(body["model"])
+
+    # If tool_ids field is present, call the functions
+    if "tool_ids" in body:
+        print(body["tool_ids"])
+        for tool_id in body["tool_ids"]:
+            print(tool_id)
+            try:
+                response, citation, file_handler = await get_function_call_response(
+                    messages=body["messages"],
+                    files=body.get("files", []),
+                    tool_id=tool_id,
+                    template=app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
+                    task_model_id=task_model_id,
+                    user=user,
+                    model=model,
+                    __event_emitter__=__event_emitter__,
+                )
+
+                print(file_handler)
+                if isinstance(response, str):
+                    contexts.append(response)
 
-        show_citations = False
-        citations = []
+                if citation:
+                    if citations is None:
+                        citations = [citation]
+                    else:
+                        citations.append(citation)
+
+                if file_handler:
+                    skip_files = True
+
+            except Exception as e:
+                print(f"Error: {e}")
+        del body["tool_ids"]
+        print(f"tool_contexts: {contexts}")
+
+    if skip_files:
+        if "files" in body:
+            del body["files"]
+
+    return body, {
+        **({"contexts": contexts} if contexts is not None else {}),
+        **({"citations": citations} if citations is not None else {}),
+    }
+
+
+async def chat_completion_files_handler(body):
+    contexts = []
+    citations = None
+
+    if "files" in body:
+        files = body["files"]
+        del body["files"]
+
+        contexts, citations = get_rag_context(
+            files=files,
+            messages=body["messages"],
+            embedding_function=rag_app.state.EMBEDDING_FUNCTION,
+            k=rag_app.state.config.TOP_K,
+            reranking_function=rag_app.state.sentence_transformer_rf,
+            r=rag_app.state.config.RELEVANCE_THRESHOLD,
+            hybrid_search=rag_app.state.config.ENABLE_RAG_HYBRID_SEARCH,
+        )
 
+        log.debug(f"rag_contexts: {contexts}, citations: {citations}")
+
+    return body, {
+        **({"contexts": contexts} if contexts is not None else {}),
+        **({"citations": citations} if citations is not None else {}),
+    }
+
+
+class ChatCompletionMiddleware(BaseHTTPMiddleware):
+    async def dispatch(self, request: Request, call_next):
         if request.method == "POST" and any(
             endpoint in request.url.path
             for endpoint in ["/ollama/api/chat", "/chat/completions"]
         ):
             log.debug(f"request.url.path: {request.url.path}")
 
-            # Read the original request body
-            body = await request.body()
-            body_str = body.decode("utf-8")
-            data = json.loads(body_str) if body_str else {}
-
-            user = get_current_user(
-                request,
-                get_http_authorization_cred(request.headers.get("Authorization")),
-            )
-            # Flag to skip RAG completions if file_handler is present in tools/functions
-            skip_files = False
-            if data.get("citations"):
-                show_citations = True
-                del data["citations"]
-
-            model_id = data["model"]
-            if model_id not in app.state.MODELS:
-                raise HTTPException(
-                    status_code=status.HTTP_404_NOT_FOUND,
-                    detail="Model not found",
+            try:
+                body, model, user = await get_body_and_model_and_user(request)
+            except Exception as e:
+                return JSONResponse(
+                    status_code=status.HTTP_400_BAD_REQUEST,
+                    content={"detail": str(e)},
                 )
-            model = app.state.MODELS[model_id]
 
-            def get_priority(function_id):
-                function = Functions.get_function_by_id(function_id)
-                if function is not None and hasattr(function, "valves"):
-                    return (function.valves if function.valves else {}).get(
-                        "priority", 0
-                    )
-                return 0
-
-            filter_ids = [
-                function.id for function in Functions.get_global_filter_functions()
-            ]
-            if "info" in model and "meta" in model["info"]:
-                filter_ids.extend(model["info"]["meta"].get("filterIds", []))
-                filter_ids = list(set(filter_ids))
-
-            enabled_filter_ids = [
-                function.id
-                for function in Functions.get_functions_by_type(
-                    "filter", active_only=True
+            # Extract session_id, chat_id and message_id from the request body
+            session_id = None
+            if "session_id" in body:
+                session_id = body["session_id"]
+                del body["session_id"]
+            chat_id = None
+            if "chat_id" in body:
+                chat_id = body["chat_id"]
+                del body["chat_id"]
+            message_id = None
+            if "id" in body:
+                message_id = body["id"]
+                del body["id"]
+
+            async def __event_emitter__(data):
+                await sio.emit(
+                    "chat-events",
+                    {
+                        "chat_id": chat_id,
+                        "message_id": message_id,
+                        "data": data,
+                    },
+                    to=session_id,
                 )
-            ]
-            filter_ids = [
-                filter_id for filter_id in filter_ids if filter_id in enabled_filter_ids
-            ]
 
-            filter_ids.sort(key=get_priority)
-            for filter_id in filter_ids:
-                filter = Functions.get_function_by_id(filter_id)
-                if filter:
-                    if filter_id in webui_app.state.FUNCTIONS:
-                        function_module = webui_app.state.FUNCTIONS[filter_id]
-                    else:
-                        function_module, function_type, frontmatter = (
-                            load_function_module_by_id(filter_id)
-                        )
-                        webui_app.state.FUNCTIONS[filter_id] = function_module
-
-                    # Check if the function has a file_handler variable
-                    if hasattr(function_module, "file_handler"):
-                        skip_files = function_module.file_handler
-
-                    if hasattr(function_module, "valves") and hasattr(
-                        function_module, "Valves"
-                    ):
-                        valves = Functions.get_function_valves_by_id(filter_id)
-                        function_module.valves = function_module.Valves(
-                            **(valves if valves else {})
-                        )
-
-                    try:
-                        if hasattr(function_module, "inlet"):
-                            inlet = function_module.inlet
-
-                            # Get the signature of the function
-                            sig = inspect.signature(inlet)
-                            params = {"body": data}
-
-                            if "__user__" in sig.parameters:
-                                __user__ = {
-                                    "id": user.id,
-                                    "email": user.email,
-                                    "name": user.name,
-                                    "role": user.role,
-                                }
-
-                                try:
-                                    if hasattr(function_module, "UserValves"):
-                                        __user__["valves"] = function_module.UserValves(
-                                            **Functions.get_user_valves_by_id_and_user_id(
-                                                filter_id, user.id
-                                            )
-                                        )
-                                except Exception as e:
-                                    print(e)
-
-                                params = {**params, "__user__": __user__}
-
-                            if "__id__" in sig.parameters:
-                                params = {
-                                    **params,
-                                    "__id__": filter_id,
-                                }
-
-                            if inspect.iscoroutinefunction(inlet):
-                                data = await inlet(**params)
-                            else:
-                                data = inlet(**params)
-
-                    except Exception as e:
-                        print(f"Error: {e}")
-                        return JSONResponse(
-                            status_code=status.HTTP_400_BAD_REQUEST,
-                            content={"detail": str(e)},
-                        )
+            # Initialize data_items to store additional data to be sent to the client
+            data_items = []
 
-            # Set the task model
-            task_model_id = data["model"]
-            # Check if the user has a custom task model and use that model
-            if app.state.MODELS[task_model_id]["owned_by"] == "ollama":
-                if (
-                    app.state.config.TASK_MODEL
-                    and app.state.config.TASK_MODEL in app.state.MODELS
-                ):
-                    task_model_id = app.state.config.TASK_MODEL
-            else:
-                if (
-                    app.state.config.TASK_MODEL_EXTERNAL
-                    and app.state.config.TASK_MODEL_EXTERNAL in app.state.MODELS
-                ):
-                    task_model_id = app.state.config.TASK_MODEL_EXTERNAL
-
-            prompt = get_last_user_message(data["messages"])
-            context = ""
-
-            # If tool_ids field is present, call the functions
-            if "tool_ids" in data:
-                print(data["tool_ids"])
-                for tool_id in data["tool_ids"]:
-                    print(tool_id)
-                    try:
-                        response, citation, file_handler = (
-                            await get_function_call_response(
-                                messages=data["messages"],
-                                files=data.get("files", []),
-                                tool_id=tool_id,
-                                template=app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE,
-                                task_model_id=task_model_id,
-                                user=user,
-                            )
-                        )
+            # Initialize context, and citations
+            contexts = []
+            citations = []
 
-                        print(file_handler)
-                        if isinstance(response, str):
-                            context += ("\n" if context != "" else "") + response
-
-                        if citation:
-                            citations.append(citation)
-                            show_citations = True
-
-                        if file_handler:
-                            skip_files = True
-
-                    except Exception as e:
-                        print(f"Error: {e}")
-                del data["tool_ids"]
-
-                print(f"tool_context: {context}")
-
-            # If files field is present, generate RAG completions
-            # If skip_files is True, skip the RAG completions
-            if "files" in data:
-                if not skip_files:
-                    data = {**data}
-                    rag_context, rag_citations = get_rag_context(
-                        files=data["files"],
-                        messages=data["messages"],
-                        embedding_function=rag_app.state.EMBEDDING_FUNCTION,
-                        k=rag_app.state.config.TOP_K,
-                        reranking_function=rag_app.state.sentence_transformer_rf,
-                        r=rag_app.state.config.RELEVANCE_THRESHOLD,
-                        hybrid_search=rag_app.state.config.ENABLE_RAG_HYBRID_SEARCH,
-                    )
-                    if rag_context:
-                        context += ("\n" if context != "" else "") + rag_context
+            try:
+                body, flags = await chat_completion_functions_handler(
+                    body, model, user, __event_emitter__
+                )
+            except Exception as e:
+                return JSONResponse(
+                    status_code=status.HTTP_400_BAD_REQUEST,
+                    content={"detail": str(e)},
+                )
 
-                    log.debug(f"rag_context: {rag_context}, citations: {citations}")
+            try:
+                body, flags = await chat_completion_tools_handler(
+                    body, model, user, __event_emitter__
+                )
 
-                    if rag_citations:
-                        citations.extend(rag_citations)
+                contexts.extend(flags.get("contexts", []))
+                citations.extend(flags.get("citations", []))
+            except Exception as e:
+                print(e)
+                pass
 
-                del data["files"]
+            try:
+                body, flags = await chat_completion_files_handler(body)
 
-            if show_citations and len(citations) > 0:
-                data_items.append({"citations": citations})
+                contexts.extend(flags.get("contexts", []))
+                citations.extend(flags.get("citations", []))
+            except Exception as e:
+                print(e)
+                pass
 
-            if context != "":
-                system_prompt = rag_template(
-                    rag_app.state.config.RAG_TEMPLATE, context, prompt
-                )
-                print(system_prompt)
-                data["messages"] = add_or_update_system_message(
-                    system_prompt, data["messages"]
+            # If context is not empty, insert it into the messages
+            if len(contexts) > 0:
+                context_string = "/n".join(contexts).strip()
+                prompt = get_last_user_message(body["messages"])
+                body["messages"] = add_or_update_system_message(
+                    rag_template(
+                        rag_app.state.config.RAG_TEMPLATE, context_string, prompt
+                    ),
+                    body["messages"],
                 )
 
-            modified_body_bytes = json.dumps(data).encode("utf-8")
+            # If there are citations, add them to the data_items
+            if len(citations) > 0:
+                data_items.append({"citations": citations})
+
+            modified_body_bytes = json.dumps(body).encode("utf-8")
             # Replace the request body with the modified one
             request._body = modified_body_bytes
             # Set custom header to ensure content-length matches new body length
@@ -715,9 +833,6 @@ def filter_pipeline(payload, user):
                 pass
 
     if "pipeline" not in app.state.MODELS[model_id]:
-        if "chat_id" in payload:
-            del payload["chat_id"]
-
         if "title" in payload:
             del payload["title"]
 
@@ -1008,6 +1123,17 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
             else:
                 pass
 
+    async def __event_emitter__(data):
+        await sio.emit(
+            "chat-events",
+            {
+                "chat_id": data["chat_id"],
+                "message_id": data["id"],
+                "data": data,
+            },
+            to=data["session_id"],
+        )
+
     def get_priority(function_id):
         function = Functions.get_function_by_id(function_id)
         if function is not None and hasattr(function, "valves"):
@@ -1083,6 +1209,18 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
                             "__id__": filter_id,
                         }
 
+                    if "__model__" in sig.parameters:
+                        params = {
+                            **params,
+                            "__model__": model,
+                        }
+
+                    if "__event_emitter__" in sig.parameters:
+                        params = {
+                            **params,
+                            "__event_emitter__": __event_emitter__,
+                        }
+
                     if inspect.iscoroutinefunction(outlet):
                         data = await outlet(**params)
                     else:
@@ -1213,6 +1351,9 @@ async def generate_title(form_data: dict, user=Depends(get_verified_user)):
             content={"detail": e.args[1]},
         )
 
+    if "chat_id" in payload:
+        del payload["chat_id"]
+
     return await generate_chat_completions(form_data=payload, user=user)
 
 
@@ -1273,6 +1414,9 @@ async def generate_search_query(form_data: dict, user=Depends(get_verified_user)
             content={"detail": e.args[1]},
         )
 
+    if "chat_id" in payload:
+        del payload["chat_id"]
+
     return await generate_chat_completions(form_data=payload, user=user)
 
 
@@ -1337,6 +1481,9 @@ Message: """{{prompt}}"""
             content={"detail": e.args[1]},
         )
 
+    if "chat_id" in payload:
+        del payload["chat_id"]
+
     return await generate_chat_completions(form_data=payload, user=user)
 
 

+ 7 - 7
backend/requirements.txt

@@ -10,7 +10,7 @@ python-socketio==5.11.3
 python-jose==3.3.0
 passlib[bcrypt]==1.7.4
 
-requests==2.32.2
+requests==2.32.3
 aiohttp==3.9.5
 peewee==3.17.5
 peewee-migrate==1.12.2
@@ -30,21 +30,21 @@ openai
 anthropic
 google-generativeai==0.5.4
 
-langchain==0.2.0
-langchain-community==0.2.0
+langchain==0.2.6
+langchain-community==0.2.6
 langchain-chroma==0.1.2
 
 fake-useragent==1.5.1
 chromadb==0.5.3
-sentence-transformers==2.7.0
+sentence-transformers==3.0.1
 pypdf==4.2.0
 docx2txt==0.8
 python-pptx==0.6.23
-unstructured==0.14.0
+unstructured==0.14.9
 Markdown==3.6
 pypandoc==1.13
 pandas==2.2.2
-openpyxl==3.1.2
+openpyxl==3.1.5
 pyxlsb==1.0.10
 xlrd==2.0.1
 validators==0.28.1
@@ -61,7 +61,7 @@ PyJWT[crypto]==2.8.0
 authlib==1.3.1
 
 black==24.4.2
-langfuse==2.33.0
+langfuse==2.36.2
 youtube-transcript-api==0.6.2
 pytube==15.0.0
 

+ 14 - 6
backend/utils/misc.py

@@ -8,14 +8,22 @@ import uuid
 import time
 
 
-def get_last_user_message(messages: List[dict]) -> str:
+def get_last_user_message_item(messages: List[dict]) -> str:
     for message in reversed(messages):
         if message["role"] == "user":
-            if isinstance(message["content"], list):
-                for item in message["content"]:
-                    if item["type"] == "text":
-                        return item["text"]
-            return message["content"]
+            return message
+    return None
+
+
+def get_last_user_message(messages: List[dict]) -> str:
+    message = get_last_user_message_item(messages)
+
+    if message is not None:
+        if isinstance(message["content"], list):
+            for item in message["content"]:
+                if item["type"] == "text":
+                    return item["text"]
+        return message["content"]
     return None
 
 

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
 	"name": "open-webui",
-	"version": "0.3.7",
+	"version": "0.3.8",
 	"lockfileVersion": 3,
 	"requires": true,
 	"packages": {
 		"": {
 			"name": "open-webui",
-			"version": "0.3.7",
+			"version": "0.3.8",
 			"dependencies": {
 				"@codemirror/lang-javascript": "^6.2.2",
 				"@codemirror/lang-python": "^6.1.6",

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "open-webui",
-	"version": "0.3.7",
+	"version": "0.3.8",
 	"private": true,
 	"scripts": {
 		"dev": "npm run pyodide:fetch && vite dev --host",

+ 6 - 0
src/lib/apis/rag/index.ts

@@ -32,6 +32,11 @@ type ChunkConfigForm = {
 	chunk_overlap: number;
 };
 
+type ContentExtractConfigForm = {
+	engine: string;
+	tika_server_url: string | null;
+};
+
 type YoutubeConfigForm = {
 	language: string[];
 	translation?: string | null;
@@ -40,6 +45,7 @@ type YoutubeConfigForm = {
 type RAGConfigForm = {
 	pdf_extract_images?: boolean;
 	chunk?: ChunkConfigForm;
+	content_extraction?: ContentExtractConfigForm;
 	web_loader_ssl_verification?: boolean;
 	youtube?: YoutubeConfigForm;
 };

+ 51 - 1
src/lib/components/admin/Settings/Documents.svelte

@@ -37,6 +37,10 @@
 	let embeddingModel = '';
 	let rerankingModel = '';
 
+	let contentExtractionEngine = 'default';
+	let tikaServerUrl = '';
+	let showTikaServerUrl = false;
+
 	let chunkSize = 0;
 	let chunkOverlap = 0;
 	let pdfExtractImages = true;
@@ -163,11 +167,20 @@
 			rerankingModelUpdateHandler();
 		}
 
+		if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
+			toast.error($i18n.t('Tika Server URL required.'));
+			return;
+		}
+
 		const res = await updateRAGConfig(localStorage.token, {
 			pdf_extract_images: pdfExtractImages,
 			chunk: {
 				chunk_overlap: chunkOverlap,
 				chunk_size: chunkSize
+			},
+			content_extraction: {
+				engine: contentExtractionEngine,
+				tika_server_url: tikaServerUrl
 			}
 		});
 
@@ -213,6 +226,10 @@
 
 			chunkSize = res.chunk.chunk_size;
 			chunkOverlap = res.chunk.chunk_overlap;
+
+			contentExtractionEngine = res.content_extraction.engine;
+			tikaServerUrl = res.content_extraction.tika_server_url;
+			showTikaServerUrl = contentExtractionEngine === 'tika';
 		}
 	});
 </script>
@@ -388,7 +405,7 @@
 			</div>
 		</div>
 
-		<hr class=" dark:border-gray-850 my-1" />
+		<hr class="dark:border-gray-850" />
 
 		<div class="space-y-2" />
 		<div>
@@ -562,6 +579,39 @@
 
 		<hr class=" dark:border-gray-850" />
 
+		<div class="">
+			<div class="text-sm font-medium">{$i18n.t('Content Extraction')}</div>
+
+			<div class="flex w-full justify-between mt-2">
+				<div class="self-center text-xs font-medium">{$i18n.t('Engine')}</div>
+				<div class="flex items-center relative">
+					<select
+						class="dark:bg-gray-900 w-fit pr-8 rounded px-2 p-1 text-xs bg-transparent outline-none text-right"
+						bind:value={contentExtractionEngine}
+						on:change={(e) => {
+							showTikaServerUrl = e.target.value === 'tika';
+						}}
+					>
+						<option value="">{$i18n.t('Default')} </option>
+						<option value="tika">{$i18n.t('Tika')}</option>
+					</select>
+				</div>
+			</div>
+
+			{#if showTikaServerUrl}
+				<div class="flex w-full mt-2">
+					<div class="flex-1 mr-2">
+						<input
+							class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+							placeholder={$i18n.t('Enter Tika Server URL')}
+							bind:value={tikaServerUrl}
+						/>
+					</div>
+				</div>
+			{/if}
+		</div>
+		<hr class=" dark:border-gray-850" />
+
 		<div class=" ">
 			<div class=" text-sm font-medium">{$i18n.t('Query Params')}</div>
 

+ 34 - 8
src/lib/components/admin/Settings/Pipelines.svelte

@@ -19,6 +19,7 @@
 	} from '$lib/apis';
 
 	import Spinner from '$lib/components/common/Spinner.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
 
 	const i18n: Writable<i18nType> = getContext('i18n');
 
@@ -476,15 +477,40 @@
 												</div>
 
 												{#if (valves[property] ?? null) !== null}
-													<div class="flex mt-0.5 space-x-2">
+													<!-- {valves[property]} -->
+													<div class="flex mt-0.5 mb-1.5 space-x-2">
 														<div class=" flex-1">
-															<input
-																class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-																type="text"
-																placeholder={valves_spec.properties[property].title}
-																bind:value={valves[property]}
-																autocomplete="off"
-															/>
+															{#if valves_spec.properties[property]?.enum ?? null}
+																<select
+																	class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+																	bind:value={valves[property]}
+																>
+																	{#each valves_spec.properties[property].enum as option}
+																		<option value={option} selected={option === valves[property]}>
+																			{option}
+																		</option>
+																	{/each}
+																</select>
+															{:else if (valves_spec.properties[property]?.type ?? null) === 'boolean'}
+																<div class="flex justify-between items-center">
+																	<div class="text-xs text-gray-500">
+																		{valves[property] ? 'Enabled' : 'Disabled'}
+																	</div>
+
+																	<div class=" pr-2">
+																		<Switch bind:state={valves[property]} />
+																	</div>
+																</div>
+															{:else}
+																<input
+																	class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+																	type="text"
+																	placeholder={valves_spec.properties[property].title}
+																	bind:value={valves[property]}
+																	autocomplete="off"
+																	required
+																/>
+															{/if}
 														</div>
 													</div>
 												{/if}

+ 39 - 10
src/lib/components/chat/Chat.svelte

@@ -126,6 +126,27 @@
 		})();
 	}
 
+	const chatEventHandler = async (data) => {
+		if (data.chat_id === $chatId) {
+			await tick();
+			console.log(data);
+			let message = history.messages[data.message_id];
+
+			const status = {
+				done: data?.data?.done ?? null,
+				description: data?.data?.status ?? null
+			};
+
+			if (message.statusHistory) {
+				message.statusHistory.push(status);
+			} else {
+				message.statusHistory = [status];
+			}
+
+			messages = messages;
+		}
+	};
+
 	onMount(async () => {
 		const onMessageHandler = async (event) => {
 			if (event.origin === window.origin) {
@@ -163,6 +184,8 @@
 		};
 		window.addEventListener('message', onMessageHandler);
 
+		$socket.on('chat-events', chatEventHandler);
+
 		if (!$chatId) {
 			chatId.subscribe(async (value) => {
 				if (!value) {
@@ -177,6 +200,8 @@
 
 		return () => {
 			window.removeEventListener('message', onMessageHandler);
+
+			$socket.off('chat-events');
 		};
 	});
 
@@ -302,7 +327,7 @@
 		}
 	};
 
-	const chatCompletedHandler = async (modelId, messages) => {
+	const chatCompletedHandler = async (modelId, responseMessageId, messages) => {
 		await mermaid.run({
 			querySelector: '.mermaid'
 		});
@@ -316,7 +341,9 @@
 				info: m.info ? m.info : undefined,
 				timestamp: m.timestamp
 			})),
-			chat_id: $chatId
+			chat_id: $chatId,
+			session_id: $socket?.id,
+			id: responseMessageId
 		}).catch((error) => {
 			toast.error(error);
 			messages.at(-1).error = { content: error };
@@ -665,6 +692,7 @@
 		await tick();
 
 		const [res, controller] = await generateChatCompletion(localStorage.token, {
+			stream: true,
 			model: model.id,
 			messages: messagesBody,
 			options: {
@@ -682,8 +710,9 @@
 			keep_alive: $settings.keepAlive ?? undefined,
 			tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
 			files: files.length > 0 ? files : undefined,
-			citations: files.length > 0 ? true : undefined,
-			chat_id: $chatId
+			session_id: $socket?.id,
+			chat_id: $chatId,
+			id: responseMessageId
 		});
 
 		if (res && res.ok) {
@@ -704,7 +733,7 @@
 						controller.abort('User: Stop Response');
 					} else {
 						const messages = createMessagesList(responseMessageId);
-						await chatCompletedHandler(model.id, messages);
+						await chatCompletedHandler(model.id, responseMessageId, messages);
 					}
 
 					_response = responseMessage.content;
@@ -912,8 +941,8 @@
 			const [res, controller] = await generateOpenAIChatCompletion(
 				localStorage.token,
 				{
-					model: model.id,
 					stream: true,
+					model: model.id,
 					stream_options:
 						model.info?.meta?.capabilities?.usage ?? false
 							? {
@@ -983,9 +1012,9 @@
 					max_tokens: $settings?.params?.max_tokens ?? undefined,
 					tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
 					files: files.length > 0 ? files : undefined,
-					citations: files.length > 0 ? true : undefined,
-
-					chat_id: $chatId
+					session_id: $socket?.id,
+					chat_id: $chatId,
+					id: responseMessageId
 				},
 				`${WEBUI_BASE_URL}/api`
 			);
@@ -1014,7 +1043,7 @@
 						} else {
 							const messages = createMessagesList(responseMessageId);
 
-							await chatCompletedHandler(model.id, messages);
+							await chatCompletedHandler(model.id, responseMessageId, messages);
 						}
 
 						_response = responseMessage.content;

+ 4 - 4
src/lib/components/chat/MessageInput/Documents.svelte

@@ -162,7 +162,7 @@
 									.substring(1)
 									.startsWith('https://youtu.be'))}
 						<button
-							class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-100 selected-command-option-button"
+							class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-850 dark:text-gray-100 selected-command-option-button"
 							type="button"
 							on:click={() => {
 								const url = prompt.split(' ')?.at(0)?.substring(1);
@@ -177,7 +177,7 @@
 								}
 							}}
 						>
-							<div class=" font-medium text-black line-clamp-1">
+							<div class=" font-medium text-black dark:text-gray-100 line-clamp-1">
 								{prompt.split(' ')?.at(0)?.substring(1)}
 							</div>
 
@@ -185,7 +185,7 @@
 						</button>
 					{:else if prompt.split(' ')?.at(0)?.substring(1).startsWith('http')}
 						<button
-							class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-100 selected-command-option-button"
+							class="px-3 py-1.5 rounded-xl w-full text-left bg-gray-50 dark:bg-gray-850 dark:text-gray-100 selected-command-option-button"
 							type="button"
 							on:click={() => {
 								const url = prompt.split(' ')?.at(0)?.substring(1);
@@ -200,7 +200,7 @@
 								}
 							}}
 						>
-							<div class=" font-medium text-black line-clamp-1">
+							<div class=" font-medium text-black dark:text-gray-100 line-clamp-1">
 								{prompt.split(' ')?.at(0)?.substring(1)}
 							</div>
 

+ 62 - 58
src/lib/components/chat/Messages/CompareMessages.svelte

@@ -100,64 +100,68 @@
 		class="flex snap-x snap-mandatory overflow-x-auto scrollbar-hidden"
 		id="responses-container-{parentMessage.id}"
 	>
-		{#each Object.keys(groupedMessages) as model}
-			{#if groupedMessagesIdx[model] !== undefined && groupedMessages[model].messages.length > 0}
-				<!-- svelte-ignore a11y-no-static-element-interactions -->
-				<!-- svelte-ignore a11y-click-events-have-key-events -->
-
-				<div
-					class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
-						currentMessageId
-					].model === model
-						? 'border-gray-100 dark:border-gray-850 border-[1.5px]'
-						: 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl"
-					on:click={() => {
-						currentMessageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id;
-
-						let messageId = groupedMessages[model].messages[groupedMessagesIdx[model]].id;
-
-						console.log(messageId);
-						let messageChildrenIds = history.messages[messageId].childrenIds;
-
-						while (messageChildrenIds.length !== 0) {
-							messageId = messageChildrenIds.at(-1);
-							messageChildrenIds = history.messages[messageId].childrenIds;
-						}
-
-						history.currentId = messageId;
-						dispatch('change');
-					}}
-				>
-					<ResponseMessage
-						message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
-						siblings={groupedMessages[model].messages.map((m) => m.id)}
-						isLastMessage={true}
-						{updateChatMessages}
-						{confirmEditResponseMessage}
-						showPreviousMessage={() => showPreviousMessage(model)}
-						showNextMessage={() => showNextMessage(model)}
-						{readOnly}
-						{rateMessage}
-						{copyToClipboard}
-						{continueGeneration}
-						regenerateResponse={async (message) => {
-							regenerateResponse(message);
-							await tick();
-							groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
+		{#key currentMessageId}
+			{#each Object.keys(groupedMessages) as model}
+				{#if groupedMessagesIdx[model] !== undefined && groupedMessages[model].messages.length > 0}
+					<!-- svelte-ignore a11y-no-static-element-interactions -->
+					<!-- svelte-ignore a11y-click-events-have-key-events -->
+					{@const message = groupedMessages[model].messages[groupedMessagesIdx[model]]}
+
+					<div
+						class=" snap-center min-w-80 w-full max-w-full m-1 border {history.messages[
+							currentMessageId
+						].model === model
+							? 'border-gray-100 dark:border-gray-800 border-[1.5px]'
+							: 'border-gray-50 dark:border-gray-850 '} transition p-5 rounded-3xl"
+						on:click={() => {
+							if (currentMessageId != message.id) {
+								currentMessageId = message.id;
+								let messageId = message.id;
+								console.log(messageId);
+
+								//
+								let messageChildrenIds = history.messages[messageId].childrenIds;
+								while (messageChildrenIds.length !== 0) {
+									messageId = messageChildrenIds.at(-1);
+									messageChildrenIds = history.messages[messageId].childrenIds;
+								}
+
+								history.currentId = messageId;
+								dispatch('change');
+							}
 						}}
-						on:save={async (e) => {
-							console.log('save', e);
-
-							const message = e.detail;
-							history.messages[message.id] = message;
-							await updateChatById(localStorage.token, chatId, {
-								messages: messages,
-								history: history
-							});
-						}}
-					/>
-				</div>
-			{/if}
-		{/each}
+					>
+						<ResponseMessage
+							message={groupedMessages[model].messages[groupedMessagesIdx[model]]}
+							siblings={groupedMessages[model].messages.map((m) => m.id)}
+							isLastMessage={true}
+							{updateChatMessages}
+							{confirmEditResponseMessage}
+							showPreviousMessage={() => showPreviousMessage(model)}
+							showNextMessage={() => showNextMessage(model)}
+							{readOnly}
+							{rateMessage}
+							{copyToClipboard}
+							{continueGeneration}
+							regenerateResponse={async (message) => {
+								regenerateResponse(message);
+								await tick();
+								groupedMessagesIdx[model] = groupedMessages[model].messages.length - 1;
+							}}
+							on:save={async (e) => {
+								console.log('save', e);
+
+								const message = e.detail;
+								history.messages[message.id] = message;
+								await updateChatById(localStorage.token, chatId, {
+									messages: messages,
+									history: history
+								});
+							}}
+						/>
+					</div>
+				{/if}
+			{/each}
+		{/key}
 	</div>
 </div>

+ 37 - 9
src/lib/components/chat/Settings/Valves.svelte

@@ -18,6 +18,7 @@
 	import ManageModal from './Personalization/ManageModal.svelte';
 	import Tooltip from '$lib/components/common/Tooltip.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
 
 	const dispatch = createEventDispatcher();
 
@@ -185,7 +186,10 @@
 										class="p-1 px-3 text-xs flex rounded transition"
 										type="button"
 										on:click={() => {
-											valves[property] = (valves[property] ?? null) === null ? '' : null;
+											valves[property] =
+												(valves[property] ?? null) === null
+													? valvesSpec.properties[property]?.default ?? ''
+													: null;
 										}}
 									>
 										{#if (valves[property] ?? null) === null}
@@ -203,16 +207,40 @@
 								</div>
 
 								{#if (valves[property] ?? null) !== null}
+									<!-- {valves[property]} -->
 									<div class="flex mt-0.5 mb-1.5 space-x-2">
 										<div class=" flex-1">
-											<input
-												class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-												type="text"
-												placeholder={valvesSpec.properties[property].title}
-												bind:value={valves[property]}
-												autocomplete="off"
-												required
-											/>
+											{#if valvesSpec.properties[property]?.enum ?? null}
+												<select
+													class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+													bind:value={valves[property]}
+												>
+													{#each valvesSpec.properties[property].enum as option}
+														<option value={option} selected={option === valves[property]}>
+															{option}
+														</option>
+													{/each}
+												</select>
+											{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
+												<div class="flex justify-between items-center">
+													<div class="text-xs text-gray-500">
+														{valves[property] ? 'Enabled' : 'Disabled'}
+													</div>
+
+													<div class=" pr-2">
+														<Switch bind:state={valves[property]} />
+													</div>
+												</div>
+											{:else}
+												<input
+													class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+													type="text"
+													placeholder={valvesSpec.properties[property].title}
+													bind:value={valves[property]}
+													autocomplete="off"
+													required
+												/>
+											{/if}
 										</div>
 									</div>
 								{/if}

+ 13 - 6
src/lib/components/chat/Tags.svelte

@@ -8,7 +8,7 @@
 		getTagsById,
 		updateChatById
 	} from '$lib/apis/chats';
-	import { tags as _tags, chats } from '$lib/stores';
+	import { tags as _tags, chats, pinnedChats } from '$lib/stores';
 	import { createEventDispatcher, onMount } from 'svelte';
 
 	const dispatch = createEventDispatcher();
@@ -19,9 +19,11 @@
 	let tags = [];
 
 	const getTags = async () => {
-		return await getTagsById(localStorage.token, chatId).catch(async (error) => {
-			return [];
-		});
+		return (
+			await getTagsById(localStorage.token, chatId).catch(async (error) => {
+				return [];
+			})
+		).filter((tag) => tag.name !== 'pinned');
 	};
 
 	const addTag = async (tagName) => {
@@ -33,6 +35,7 @@
 		});
 
 		_tags.set(await getAllChatTags(localStorage.token));
+		await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 	};
 
 	const deleteTag = async (tagName) => {
@@ -44,19 +47,23 @@
 		});
 
 		console.log($_tags);
-
 		await _tags.set(await getAllChatTags(localStorage.token));
 
 		console.log($_tags);
 
 		if ($_tags.map((t) => t.name).includes(tagName)) {
-			await chats.set(await getChatListByTagName(localStorage.token, tagName));
+			if (tagName === 'pinned') {
+				await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
+			} else {
+				await chats.set(await getChatListByTagName(localStorage.token, tagName));
+			}
 
 			if ($chats.find((chat) => chat.id === chatId)) {
 				dispatch('close');
 			}
 		} else {
 			await chats.set(await getChatList(localStorage.token));
+			await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 		}
 	};
 

+ 19 - 0
src/lib/components/icons/Bookmark.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'w-4 h-4';
+	export let strokeWidth = '1.5';
+</script>
+
+<svg
+	xmlns="http://www.w3.org/2000/svg"
+	fill="none"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	stroke="currentColor"
+	class={className}
+>
+	<path
+		stroke-linecap="round"
+		stroke-linejoin="round"
+		d="M17.593 3.322c1.1.128 1.907 1.077 1.907 2.185V21L12 17.25 4.5 21V5.507c0-1.108.806-2.057 1.907-2.185a48.507 48.507 0 0 1 11.186 0Z"
+	/>
+</svg>

+ 19 - 0
src/lib/components/icons/BookmarkSlash.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'w-4 h-4';
+	export let strokeWidth = '1.5';
+</script>
+
+<svg
+	xmlns="http://www.w3.org/2000/svg"
+	fill="none"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	stroke="currentColor"
+	class={className}
+>
+	<path
+		stroke-linecap="round"
+		stroke-linejoin="round"
+		d="m3 3 1.664 1.664M21 21l-1.5-1.5m-5.485-1.242L12 17.25 4.5 21V8.742m.164-4.078a2.15 2.15 0 0 1 1.743-1.342 48.507 48.507 0 0 1 11.186 0c1.1.128 1.907 1.077 1.907 2.185V19.5M4.664 4.664 19.5 19.5"
+	/>
+</svg>

+ 124 - 0
src/lib/components/icons/ChatMenu.svelte

@@ -0,0 +1,124 @@
+<script lang="ts">
+	import { DropdownMenu } from 'bits-ui';
+	import { flyAndScale } from '$lib/utils/transitions';
+	import { getContext } from 'svelte';
+
+	import Dropdown from '$lib/components/common/Dropdown.svelte';
+	import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
+	import Pencil from '$lib/components/icons/Pencil.svelte';
+	import Tooltip from '$lib/components/common/Tooltip.svelte';
+	import Tags from '$lib/components/chat/Tags.svelte';
+	import Share from '$lib/components/icons/Share.svelte';
+	import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
+	import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte';
+	import Star from '$lib/components/icons/Star.svelte';
+
+	const i18n = getContext('i18n');
+
+	export let pinHandler: Function;
+	export let shareHandler: Function;
+	export let cloneChatHandler: Function;
+	export let archiveChatHandler: Function;
+	export let renameHandler: Function;
+	export let deleteHandler: Function;
+	export let onClose: Function;
+
+	export let chatId = '';
+
+	let show = false;
+</script>
+
+<Dropdown
+	bind:show
+	on:change={(e) => {
+		if (e.detail === false) {
+			onClose();
+		}
+	}}
+>
+	<Tooltip content={$i18n.t('More')}>
+		<slot />
+	</Tooltip>
+
+	<div slot="content">
+		<DropdownMenu.Content
+			class="w-full max-w-[180px] rounded-xl px-1 py-1.5 border border-gray-300/30 dark:border-gray-700/50 z-50 bg-white dark:bg-gray-850 dark:text-white shadow"
+			sideOffset={-2}
+			side="bottom"
+			align="start"
+			transition={flyAndScale}
+		>
+			<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-md"
+				on:click={() => {
+					pinHandler();
+				}}
+			>
+				<Star strokeWidth="2" />
+				<div class="flex items-center">{$i18n.t('Pin')}</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-md"
+				on:click={() => {
+					renameHandler();
+				}}
+			>
+				<Pencil strokeWidth="2" />
+				<div class="flex items-center">{$i18n.t('Rename')}</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-md"
+				on:click={() => {
+					cloneChatHandler();
+				}}
+			>
+				<DocumentDuplicate strokeWidth="2" />
+				<div class="flex items-center">{$i18n.t('Clone')}</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-md"
+				on:click={() => {
+					archiveChatHandler();
+				}}
+			>
+				<ArchiveBox strokeWidth="2" />
+				<div class="flex items-center">{$i18n.t('Archive')}</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-md"
+				on:click={() => {
+					shareHandler();
+				}}
+			>
+				<Share />
+				<div class="flex items-center">{$i18n.t('Share')}</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-md"
+				on:click={() => {
+					deleteHandler();
+				}}
+			>
+				<GarbageBin strokeWidth="2" />
+				<div class="flex items-center">{$i18n.t('Delete')}</div>
+			</DropdownMenu.Item>
+
+			<hr class="border-gray-100 dark:border-gray-800 mt-2.5 mb-1.5" />
+
+			<div class="flex p-1">
+				<Tags
+					{chatId}
+					on:close={() => {
+						show = false;
+						onClose();
+					}}
+				/>
+			</div>
+		</DropdownMenu.Content>
+	</div>
+</Dropdown>

+ 19 - 0
src/lib/components/icons/Star.svelte

@@ -0,0 +1,19 @@
+<script lang="ts">
+	export let className = 'w-4 h-4';
+	export let strokeWidth = '1.5';
+</script>
+
+<svg
+	xmlns="http://www.w3.org/2000/svg"
+	fill="none"
+	viewBox="0 0 24 24"
+	stroke-width={strokeWidth}
+	stroke="currentColor"
+	class={className}
+>
+	<path
+		stroke-linecap="round"
+		stroke-linejoin="round"
+		d="M11.48 3.499a.562.562 0 0 1 1.04 0l2.125 5.111a.563.563 0 0 0 .475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 0 0-.182.557l1.285 5.385a.562.562 0 0 1-.84.61l-4.725-2.885a.562.562 0 0 0-.586 0L6.982 20.54a.562.562 0 0 1-.84-.61l1.285-5.386a.562.562 0 0 0-.182-.557l-4.204-3.602a.562.562 0 0 1 .321-.988l5.518-.442a.563.563 0 0 0 .475-.345L11.48 3.5Z"
+	/>
+</svg>

+ 39 - 3
src/lib/components/layout/Sidebar.svelte

@@ -10,7 +10,8 @@
 		tags,
 		showSidebar,
 		mobile,
-		showArchivedChats
+		showArchivedChats,
+		pinnedChats
 	} from '$lib/stores';
 	import { onMount, getContext, tick } from 'svelte';
 
@@ -46,6 +47,7 @@
 
 	let showDeleteConfirm = false;
 	let showDropdown = false;
+
 	let filteredChatList = [];
 
 	$: filteredChatList = $chats.filter((chat) => {
@@ -80,6 +82,8 @@
 		});
 
 		showSidebar.set(window.innerWidth > BREAKPOINT);
+
+		await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 		await chats.set(await getChatList(localStorage.token));
 
 		let touchstart;
@@ -412,7 +416,7 @@
 				</div>
 			</div>
 
-			{#if $tags.length > 0}
+			{#if $tags.filter((t) => t.name !== 'pinned').length > 0}
 				<div class="px-2.5 mb-2 flex gap-1 flex-wrap">
 					<button
 						class="px-2.5 text-xs font-medium bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-800 transition rounded-full"
@@ -422,7 +426,7 @@
 					>
 						{$i18n.t('all')}
 					</button>
-					{#each $tags as tag}
+					{#each $tags.filter((t) => t.name !== 'pinned') as tag}
 						<button
 							class="px-2.5 text-xs font-medium bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-800 transition rounded-full"
 							on:click={async () => {
@@ -440,6 +444,38 @@
 				</div>
 			{/if}
 
+			{#if $pinnedChats.length > 0}
+				<div class="pl-2 py-2 flex flex-col space-y-1">
+					<div class="">
+						<div class="w-full pl-2.5 text-xs text-gray-500 dark:text-gray-500 font-medium pb-1.5">
+							{$i18n.t('Pinned')}
+						</div>
+
+						{#each $pinnedChats as chat, idx}
+							<ChatItem
+								{chat}
+								{shiftKey}
+								selected={selectedChatId === chat.id}
+								on:select={() => {
+									selectedChatId = chat.id;
+								}}
+								on:unselect={() => {
+									selectedChatId = null;
+								}}
+								on:delete={(e) => {
+									if ((e?.detail ?? '') === 'shift') {
+										deleteChatHandler(chat.id);
+									} else {
+										deleteChat = chat;
+										showDeleteConfirm = true;
+									}
+								}}
+							/>
+						{/each}
+					</div>
+				</div>
+			{/if}
+
 			<div class="pl-2 my-2 flex-1 flex flex-col space-y-1 overflow-y-auto scrollbar-hidden">
 				{#each filteredChatList as chat, idx}
 					{#if idx === 0 || (idx > 0 && chat.time_range !== filteredChatList[idx - 1].time_range)}

+ 8 - 1
src/lib/components/layout/Sidebar/ChatItem.svelte

@@ -11,9 +11,10 @@
 		cloneChatById,
 		deleteChatById,
 		getChatList,
+		getChatListByTagName,
 		updateChatById
 	} from '$lib/apis/chats';
-	import { chatId, chats, mobile, showSidebar } from '$lib/stores';
+	import { chatId, chats, mobile, pinnedChats, showSidebar } from '$lib/stores';
 
 	import ChatMenu from './ChatMenu.svelte';
 	import ShareChatModal from '$lib/components/chat/ShareChatModal.svelte';
@@ -40,6 +41,7 @@
 				title: _title
 			});
 			await chats.set(await getChatList(localStorage.token));
+			await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 		}
 	};
 
@@ -52,12 +54,14 @@
 		if (res) {
 			goto(`/c/${res.id}`);
 			await chats.set(await getChatList(localStorage.token));
+			await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 		}
 	};
 
 	const archiveChatHandler = async (id) => {
 		await archiveChatById(localStorage.token, id);
 		await chats.set(await getChatList(localStorage.token));
+		await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
 	};
 
 	const focusEdit = async (node: HTMLInputElement) => {
@@ -233,6 +237,9 @@
 					onClose={() => {
 						dispatch('unselect');
 					}}
+					on:change={async () => {
+						await pinnedChats.set(await getChatListByTagName(localStorage.token, 'pinned'));
+					}}
 				>
 					<button
 						aria-label="Chat Menu"

+ 43 - 1
src/lib/components/layout/Sidebar/ChatMenu.svelte

@@ -1,7 +1,9 @@
 <script lang="ts">
 	import { DropdownMenu } from 'bits-ui';
 	import { flyAndScale } from '$lib/utils/transitions';
-	import { getContext } from 'svelte';
+	import { getContext, createEventDispatcher } from 'svelte';
+
+	const dispatch = createEventDispatcher();
 
 	import Dropdown from '$lib/components/common/Dropdown.svelte';
 	import GarbageBin from '$lib/components/icons/GarbageBin.svelte';
@@ -11,6 +13,9 @@
 	import Share from '$lib/components/icons/Share.svelte';
 	import ArchiveBox from '$lib/components/icons/ArchiveBox.svelte';
 	import DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte';
+	import Bookmark from '$lib/components/icons/Bookmark.svelte';
+	import BookmarkSlash from '$lib/components/icons/BookmarkSlash.svelte';
+	import { addTagById, deleteTagById, getTagsById } from '$lib/apis/chats';
 
 	const i18n = getContext('i18n');
 
@@ -24,6 +29,28 @@
 	export let chatId = '';
 
 	let show = false;
+	let pinned = false;
+
+	const pinHandler = async () => {
+		if (pinned) {
+			await deleteTagById(localStorage.token, chatId, 'pinned');
+		} else {
+			await addTagById(localStorage.token, chatId, 'pinned');
+		}
+		dispatch('change');
+	};
+
+	const checkPinned = async () => {
+		pinned = (
+			await getTagsById(localStorage.token, chatId).catch(async (error) => {
+				return [];
+			})
+		).find((tag) => tag.name === 'pinned');
+	};
+
+	$: if (show) {
+		checkPinned();
+	}
 </script>
 
 <Dropdown
@@ -46,6 +73,21 @@
 			align="start"
 			transition={flyAndScale}
 		>
+			<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-md"
+				on:click={() => {
+					pinHandler();
+				}}
+			>
+				{#if pinned}
+					<BookmarkSlash strokeWidth="2" />
+					<div class="flex items-center">{$i18n.t('Unpin')}</div>
+				{:else}
+					<Bookmark strokeWidth="2" />
+					<div class="flex items-center">{$i18n.t('Pin')}</div>
+				{/if}
+			</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-md"
 				on:click={() => {

+ 37 - 9
src/lib/components/workspace/common/ValvesModal.svelte

@@ -12,6 +12,7 @@
 	} from '$lib/apis/functions';
 	import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools';
 	import Spinner from '../../common/Spinner.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
 
 	const i18n = getContext('i18n');
 	const dispatch = createEventDispatcher();
@@ -142,7 +143,10 @@
 												class="p-1 px-3 text-xs flex rounded transition"
 												type="button"
 												on:click={() => {
-													valves[property] = (valves[property] ?? null) === null ? '' : null;
+													valves[property] =
+														(valves[property] ?? null) === null
+															? valvesSpec.properties[property]?.default ?? ''
+															: null;
 												}}
 											>
 												{#if (valves[property] ?? null) === null}
@@ -160,16 +164,40 @@
 										</div>
 
 										{#if (valves[property] ?? null) !== null}
+											<!-- {valves[property]} -->
 											<div class="flex mt-0.5 mb-1.5 space-x-2">
 												<div class=" flex-1">
-													<input
-														class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
-														type="text"
-														placeholder={valvesSpec.properties[property].title}
-														bind:value={valves[property]}
-														autocomplete="off"
-														required
-													/>
+													{#if valvesSpec.properties[property]?.enum ?? null}
+														<select
+															class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+															bind:value={valves[property]}
+														>
+															{#each valvesSpec.properties[property].enum as option}
+																<option value={option} selected={option === valves[property]}>
+																	{option}
+																</option>
+															{/each}
+														</select>
+													{:else if (valvesSpec.properties[property]?.type ?? null) === 'boolean'}
+														<div class="flex justify-between items-center">
+															<div class="text-xs text-gray-500">
+																{valves[property] ? 'Enabled' : 'Disabled'}
+															</div>
+
+															<div class=" pr-2">
+																<Switch bind:state={valves[property]} />
+															</div>
+														</div>
+													{:else}
+														<input
+															class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
+															type="text"
+															placeholder={valvesSpec.properties[property].title}
+															bind:value={valves[property]}
+															autocomplete="off"
+															required
+														/>
+													{/if}
 												</div>
 											</div>
 										{/if}

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

@@ -126,6 +126,7 @@
 	"Connections": "اتصالات",
 	"Contact Admin for WebUI Access": "",
 	"Content": "الاتصال",
+	"Content Extraction": "",
 	"Context Length": "طول السياق",
 	"Continue Response": "متابعة الرد",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "تمكين مشاركة المجتمع",
 	"Enable New Sign Ups": "تفعيل عمليات التسجيل الجديدة",
 	"Enable Web Search": "تمكين بحث الويب",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "تأكد من أن ملف CSV الخاص بك يتضمن 4 أعمدة بهذا الترتيب: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "أدخل رسالة {{role}} هنا",
 	"Enter a detail about yourself for your LLMs to recall": "ادخل معلومات عنك تريد أن يتذكرها الموديل",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serpstack",
 	"Enter stop sequence": "أدخل تسلسل التوقف",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "أدخل Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "الرابط (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL (e.g. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "فتح",
 	"Open AI (Dall-E)": "AI (Dall-E) فتح",
 	"Open new chat": "فتح محادثة جديده",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API إعدادات",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ",
 	"Personalization": "التخصيص",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "خطوط الانابيب",
@@ -577,6 +583,8 @@
 	"This setting does not sync across browsers or devices.": "لا تتم مزامنة هذا الإعداد عبر المتصفحات أو الأجهزة.",
 	"This will delete": "",
 	"Thorough explanation": "شرح شامل",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ملاحضة: قم بتحديث عدة فتحات متغيرة على التوالي عن طريق الضغط على مفتاح tab في مدخلات الدردشة بعد كل استبدال.",
 	"Title": "العنوان",
 	"Title (e.g. Tell me a fun fact)": "(e.g. Tell me a fun fact) العناون",
@@ -611,6 +619,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}خطاء أوه! حدثت مشكلة في الاتصال بـ ",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "تحديث ونسخ الرابط",
 	"Update password": "تحديث كلمة المرور",

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

@@ -126,6 +126,7 @@
 	"Connections": "Връзки",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Съдържание",
+	"Content Extraction": "",
 	"Context Length": "Дължина на Контекста",
 	"Continue Response": "Продължи отговора",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Разрешаване на споделяне в общност",
 	"Enable New Sign Ups": "Вклюване на Нови Потребители",
 	"Enable Web Search": "Разрешаване на търсене в уеб",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Уверете се, че вашият CSV файл включва 4 колони в следния ред: Име, Имейл, Парола, Роля.",
 	"Enter {{role}} message here": "Въведете съобщение за {{role}} тук",
 	"Enter a detail about yourself for your LLMs to recall": "Въведете подробности за себе си, за да се herinnerат вашите LLMs",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Въведете Serpstack API ключ",
 	"Enter stop sequence": "Въведете стоп последователност",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Въведете Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Въведете URL (напр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Въведете URL (напр. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Отвори",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Отвори нов чат",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API Config",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
 	"Personalization": "Персонализация",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Тръбопроводи",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Тази настройка не се синхронизира между браузъри или устройства.",
 	"This will delete": "",
 	"Thorough explanation": "Това е подробно описание.",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Съвет: Актуализирайте няколко слота за променливи последователно, като натискате клавиша Tab в чат входа след всяка подмяна.",
 	"Title": "Заглавие",
 	"Title (e.g. Tell me a fun fact)": "Заглавие (напр. Моля, кажете ми нещо забавно)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "О, не! Възникна проблем при свързването с {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Обнови и копирай връзка",
 	"Update password": "Обновяване на парола",

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

@@ -126,6 +126,7 @@
 	"Connections": "কানেকশনগুলো",
 	"Contact Admin for WebUI Access": "",
 	"Content": "বিষয়বস্তু",
+	"Content Extraction": "",
 	"Context Length": "কনটেক্সটের দৈর্ঘ্য",
 	"Continue Response": "যাচাই করুন",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "সম্প্রদায় শেয়ারকরণ সক্ষম করুন",
 	"Enable New Sign Ups": "নতুন সাইনআপ চালু করুন",
 	"Enable Web Search": "ওয়েব অনুসন্ধান সক্ষম করুন",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "আপনার সিএসভি ফাইলটিতে এই ক্রমে 4 টি কলাম অন্তর্ভুক্ত রয়েছে তা নিশ্চিত করুন: নাম, ইমেল, পাসওয়ার্ড, ভূমিকা।.",
 	"Enter {{role}} message here": "{{role}} মেসেজ এখানে লিখুন",
 	"Enter a detail about yourself for your LLMs to recall": "আপনার এলএলএমগুলি স্মরণ করার জন্য নিজের সম্পর্কে একটি বিশদ লিখুন",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Serpstack API কী লিখুন",
 	"Enter stop sequence": "স্টপ সিকোয়েন্স লিখুন",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Top K লিখুন",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "ইউআরএল দিন (যেমন http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "ইউআরএল দিন (যেমন http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "খোলা",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "নতুন চ্যাট খুলুন",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI এপিআই",
 	"OpenAI API Config": "OpenAI এপিআই কনফিগ",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "মাইক্রোফোন ব্যবহারের অনুমতি পাওয়া যায়নি: {{error}}",
 	"Personalization": "ডিজিটাল বাংলা",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "পাইপলাইন",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "এই সেটিং অন্যন্য ব্রাউজার বা ডিভাইসের সাথে সিঙ্ক্রোনাইজ নয় না।",
 	"This will delete": "",
 	"Thorough explanation": "পুঙ্খানুপুঙ্খ ব্যাখ্যা",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "পরামর্শ: একাধিক ভেরিয়েবল স্লট একের পর এক রিপ্লেস করার জন্য চ্যাট ইনপুটে কিবোর্ডের Tab বাটন ব্যবহার করুন।",
 	"Title": "শিরোনাম",
 	"Title (e.g. Tell me a fun fact)": "শিরোনাম (একটি উপস্থিতি বিবরণ জানান)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "ওহ-হো! {{provider}} এর সাথে কানেকশনে সমস্যা হয়েছে।",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "আপডেট এবং লিংক কপি করুন",
 	"Update password": "পাসওয়ার্ড আপডেট করুন",

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

@@ -126,6 +126,7 @@
 	"Connections": "Connexions",
 	"Contact Admin for WebUI Access": "Posat en contacte amb l'administrador per accedir a WebUI",
 	"Content": "Contingut",
+	"Content Extraction": "",
 	"Context Length": "Mida del context",
 	"Continue Response": "Continuar la resposta",
 	"Continue with {{provider}}": "Continuar amb {{provider}}",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Activar l'ús compartit amb la comunitat",
 	"Enable New Sign Ups": "Permetre nous registres",
 	"Enable Web Search": "Activar la cerca web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que els teus fitxers CSV inclouen 4 columnes en aquest ordre: Nom, Correu electrònic, Contrasenya, Rol.",
 	"Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}",
 	"Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu què els teus models de llenguatge puguin recordar",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Introdueix la clau API Serpstack",
 	"Enter stop sequence": "Introdueix la seqüència de parada",
 	"Enter Tavily API Key": "Introdueix la clau API de Tavily",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Introdueix Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Obre",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Obre un xat nou",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API d'OpenAI",
 	"OpenAI API Config": "Configuració de l'API d'OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Permís denegat en accedir al micròfon",
 	"Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}",
 	"Personalization": "Personalització",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Pipeline eliminada correctament",
 	"Pipeline downloaded successfully": "Pipeline descarregada correctament",
 	"Pipelines": "Pipelines",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Aquesta preferència no es sincronitza entre navegadors ni dispositius.",
 	"This will delete": "Això eliminarà",
 	"Thorough explanation": "Explicació en detall",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza les diverses variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.",
 	"Title": "Títol",
 	"Title (e.g. Tell me a fun fact)": "Títol (p. ex. Digues-me quelcom divertit)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Oh! Hi ha hagut un problema connectant a {{provider}}.",
 	"UI": "UI",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipus de fitxer desconegut '{{file_type}}'. Continuant amb la càrrega del fitxer.",
+	"Unpin": "",
 	"Update": "Actualitzar",
 	"Update and Copy Link": "Actualitzar i copiar l'enllaç",
 	"Update password": "Actualitzar la contrasenya",

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

@@ -126,6 +126,7 @@
 	"Connections": "Mga koneksyon",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Kontento",
+	"Content Extraction": "",
 	"Context Length": "Ang gitas-on sa konteksto",
 	"Continue Response": "",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "I-enable ang bag-ong mga rehistro",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "",
 	"Enter {{role}} message here": "Pagsulod sa mensahe {{role}} dinhi",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Pagsulod sa katapusan nga han-ay",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Pagsulod sa Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Pagsulod sa URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -409,6 +412,7 @@
 	"Open": "Bukas",
 	"Open AI (Dall-E)": "Buksan ang AI (Dall-E)",
 	"Open new chat": "Ablihi ang bag-ong diskusyon",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Gidili ang pagtugot sa dihang nag-access sa mikropono: {{error}}",
 	"Personalization": "",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Kini nga setting wala mag-sync tali sa mga browser o device.",
 	"This will delete": "",
 	"Thorough explanation": "",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Sugyot: Pag-update sa daghang variable nga lokasyon nga sunud-sunod pinaagi sa pagpindot sa tab key sa chat entry pagkahuman sa matag puli.",
 	"Title": "Titulo",
 	"Title (e.g. Tell me a fun fact)": "",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh!  {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "",
 	"Update password": "I-update ang password",

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

@@ -1,135 +1,136 @@
 {
-	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' oder '-1' für kein Ablaufdatum.",
+	"'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' oder '-1' für keine Ablaufzeit.",
 	"(Beta)": "(Beta)",
-	"(e.g. `sh webui.sh --api --api-auth username_password`)": "",
-	"(e.g. `sh webui.sh --api`)": "(z.B. `sh webui.sh --api`)",
+	"(e.g. `sh webui.sh --api --api-auth username_password`)": "(z. B. `sh webui.sh --api --api-auth username_password`)",
+	"(e.g. `sh webui.sh --api`)": "(z. B. `sh webui.sh --api`)",
 	"(latest)": "(neueste)",
 	"{{ models }}": "{{ Modelle }}",
 	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Sie können ein Basismodell nicht löschen",
 	"{{modelName}} is thinking...": "{{modelName}} denkt nach...",
-	"{{user}}'s Chats": "{{user}}s Chats",
+	"{{user}}'s Chats": "{{user}}s Unterhaltungen",
 	"{{webUIName}} Backend Required": "{{webUIName}}-Backend erforderlich",
-	"A task model is used when performing tasks such as generating titles for chats and web search queries": "Ein Aufgabenmodell wird verwendet, wenn Aufgaben wie das Generieren von Titeln für Chats und Websuchanfragen ausgeführt werden",
+	"A task model is used when performing tasks such as generating titles for chats and web search queries": "Aufgabenmodelle können Unterhaltungstitel oder Websuchanfragen generieren.",
 	"a user": "ein Benutzer",
 	"About": "Über",
-	"Account": "Account",
-	"Account Activation Pending": "",
-	"Accurate information": "Genaue Information",
+	"Account": "Konto",
+	"Account Activation Pending": "Kontoaktivierung ausstehend",
+	"Accurate information": "Präzise Information(en)",
 	"Active Users": "Aktive Benutzer",
 	"Add": "Hinzufügen",
-	"Add a model id": "Hinzufügen einer Modell-ID",
-	"Add a short description about what this model does": "Fügen Sie eine kurze Beschreibung hinzu, was dieses Modell tut",
-	"Add a short title for this prompt": "Füge einen kurzen Titel für diesen Prompt hinzu",
-	"Add a tag": "benenne",
-	"Add custom prompt": "Eigenen Prompt hinzufügen",
+	"Add a model id": "Modell-ID hinzufügen",
+	"Add a short description about what this model does": "Fügen Sie eine kurze Beschreibung über dieses Modell hinzu",
+	"Add a short title for this prompt": "Fügen Sie einen kurzen Titel für diesen Prompt hinzu",
+	"Add a tag": "Tag hinzufügen",
+	"Add custom prompt": "Benutzerdefinierten Prompt hinzufügen",
 	"Add Docs": "Dokumente hinzufügen",
 	"Add Files": "Dateien hinzufügen",
-	"Add Memory": "Speicher hinzufügen",
-	"Add message": "Nachricht eingeben",
+	"Add Memory": "Erinnerung hinzufügen",
+	"Add message": "Nachricht hinzufügen",
 	"Add Model": "Modell hinzufügen",
 	"Add Tags": "Tags hinzufügen",
-	"Add User": "User hinzufügen",
-	"Adjusting these settings will apply changes universally to all users.": "Das Anpassen dieser Einstellungen wirkt sich universell auf alle Benutzer aus.",
+	"Add User": "Benutzer hinzufügen",
+	"Adjusting these settings will apply changes universally to all users.": "Das Anpassen dieser Einstellungen wird Änderungen universell auf alle Benutzer anwenden.",
 	"admin": "Administrator",
-	"Admin": "",
-	"Admin Panel": "Admin Panel",
-	"Admin Settings": "Admin Einstellungen",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
+	"Admin": "Administrator",
+	"Admin Panel": "Administrationsbereich",
+	"Admin Settings": "Administrator-Einstellungen",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratoren haben jederzeit Zugriff auf alle Werkzeuge. Benutzer können im Arbeitsbereich zugewiesen.",
 	"Advanced Parameters": "Erweiterte Parameter",
 	"Advanced Params": "Erweiterte Parameter",
 	"all": "Alle",
 	"All Documents": "Alle Dokumente",
 	"All Users": "Alle Benutzer",
 	"Allow": "Erlauben",
-	"Allow Chat Deletion": "Chat Löschung erlauben",
+	"Allow Chat Deletion": "Unterhaltungen löschen erlauben",
 	"Allow non-local voices": "Nicht-lokale Stimmen erlauben",
-	"Allow User Location": "",
-	"Allow Voice Interruption in Call": "",
+	"Allow User Location": "Standort freigeben",
+	"Allow Voice Interruption in Call": "Unterbrechung durch Stimme im Anruf zulassen",
 	"alphanumeric characters and hyphens": "alphanumerische Zeichen und Bindestriche",
-	"Already have an account?": "Hast du vielleicht schon ein Account?",
+	"Already have an account?": "Haben Sie bereits einen Account?",
 	"an assistant": "ein Assistent",
 	"and": "und",
-	"and create a new shared link.": "und einen neuen geteilten Link zu erstellen.",
-	"API Base URL": "API Basis URL",
-	"API Key": "API Key",
-	"API Key created.": "API Key erstellt",
-	"API keys": "API Schlüssel",
+	"and create a new shared link.": "und erstellen Sie einen neuen freigegebenen Link.",
+	"API Base URL": "API-Basis-URL",
+	"API Key": "API-Schlüssel",
+	"API Key created.": "API-Schlüssel erstellt.",
+	"API keys": "API-Schlüssel",
 	"April": "April",
 	"Archive": "Archivieren",
-	"Archive All Chats": "Alle Chats archivieren",
-	"Archived Chats": "Archivierte Chats",
-	"are allowed - Activate this command by typing": "sind erlaubt - Aktiviere diesen Befehl, indem du",
-	"Are you sure?": "Bist du sicher?",
+	"Archive All Chats": "Alle Unterhaltungen archivieren",
+	"Archived Chats": "Archivierte Unterhaltungen",
+	"are allowed - Activate this command by typing": "sind erlaubt — Aktivieren Sie diesen Befehl durch Eingabe von",
+	"Are you sure?": "Sind Sie sicher?",
 	"Attach file": "Datei anhängen",
-	"Attention to detail": "Auge fürs Detail",
+	"Attention to detail": "Aufmerksamkeit für Details",
 	"Audio": "Audio",
-	"Audio settings updated successfully": "",
+	"Audio settings updated successfully": "Audioeinstellungen erfolgreich aktualisiert",
 	"August": "August",
-	"Auto-playback response": "Automatische Wiedergabe der Antwort",
-	"AUTOMATIC1111 Api Auth String": "",
-	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 Basis URL",
-	"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Basis URL wird benötigt",
-	"available!": "verfügbar!",
+	"Auto-playback response": "Antwort automatisch abspielen",
+	"AUTOMATIC1111 Api Auth String": "AUTOMATIC1111-API-Authentifizierungszeichenfolge",
+	"AUTOMATIC1111 Base URL": "AUTOMATIC1111-Basis-URL",
+	"AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111-Basis-URL ist erforderlich.",
+	"available!": "Verfügbar!",
 	"Back": "Zurück",
 	"Bad Response": "Schlechte Antwort",
 	"Banners": "Banner",
-	"Base Model (From)": "Basismodell (von)",
-	"Batch Size (num_batch)": "",
+	"Base Model (From)": "Basismodell (From)",
+	"Batch Size (num_batch)": "Stapelgröße (num_batch)",
 	"before": "bereits geteilt",
-	"Being lazy": "Faul sein",
-	"Brave Search API Key": "API-Schlüssel für die Brave-Suche",
-	"Bypass SSL verification for Websites": "Bypass SSL-Verifizierung für Websites",
-	"Call": "",
-	"Call feature is not supported when using Web STT engine": "",
-	"Camera": "",
+	"Being lazy": "Faulheit",
+	"Brave Search API Key": "Brave Search API-Schlüssel",
+	"Bypass SSL verification for Websites": "SSL-Überprüfung für Webseiten umgehen",
+	"Call": "Anrufen",
+	"Call feature is not supported when using Web STT engine": "Die Anruffunktion wird nicht unterstützt, wenn die Web-STT-Engine verwendet wird.",
+	"Camera": "Kamera",
 	"Cancel": "Abbrechen",
 	"Capabilities": "Fähigkeiten",
 	"Change Password": "Passwort ändern",
-	"Chat": "Chat",
-	"Chat Background Image": "",
+	"Chat": "Gespräch",
+	"Chat Background Image": "Unterhaltungs-Hintergrundbild",
 	"Chat Bubble UI": "Chat Bubble UI",
-	"Chat direction": "Chat Richtung",
-	"Chat History": "Chat Verlauf",
-	"Chat History is off for this browser.": "Chat Verlauf ist für diesen Browser ausgeschaltet.",
-	"Chats": "Chats",
+	"Chat direction": "Textrichtung",
+	"Chat History": "Unterhaltungsverlauf",
+	"Chat History is off for this browser.": "Unterhaltungsverlauf ist in diesem Browser deaktiviert.",
+	"Chats": "Unterhaltungen",
 	"Check Again": "Erneut überprüfen",
 	"Check for updates": "Nach Updates suchen",
 	"Checking for updates...": "Sucht nach Updates...",
-	"Choose a model before saving...": "Wähle bitte zuerst ein Modell, bevor du speicherst...",
-	"Chunk Overlap": "Chunk Overlap",
-	"Chunk Params": "Chunk Parameter",
-	"Chunk Size": "Chunk Size",
+	"Choose a model before saving...": "Wählen Sie ein Modell, bevor Sie speichern...",
+	"Chunk Overlap": "Blocküberlappung",
+	"Chunk Params": "Blockparameter",
+	"Chunk Size": "Blockgröße",
 	"Citation": "Zitate",
-	"Clear memory": "Memory löschen",
-	"Click here for help.": "Klicke hier für Hilfe.",
-	"Click here to": "Klicke hier, um",
-	"Click here to download user import template file.": "",
-	"Click here to select": "Klicke hier um auszuwählen",
-	"Click here to select a csv file.": "Klicke hier um eine CSV-Datei auszuwählen.",
-	"Click here to select a py file.": "",
-	"Click here to select documents.": "Klicke hier um Dokumente auszuwählen",
+	"Clear memory": "Erinnerungen löschen",
+	"Click here for help.": "Klicken Sie hier für Hilfe.",
+	"Click here to": "Klicke Sie hier, um",
+	"Click here to download user import template file.": "Klicken Sie hier, um die Vorlage für den Benutzerimport herunterzuladen.",
+	"Click here to select": "Klicke Sie zum Auswählen hier",
+	"Click here to select a csv file.": "Klicken Sie zum Auswählen einer CSV-Datei hier.",
+	"Click here to select a py file.": "Klicken Sie zum Auswählen einer py-Datei hier.",
+	"Click here to select documents.": "Klicken Sie zum Auswählen von Dokumenten hier",
 	"click here.": "hier klicken.",
-	"Click on the user role button to change a user's role.": "Klicke auf die Benutzerrollenschaltfläche, um die Rolle eines Benutzers zu ändern.",
-	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "",
+	"Click on the user role button to change a user's role.": "Klicken Sie auf die Benutzerrolle, um sie zu ändern.",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Schreibberechtigung für die Zwischenablage verweigert. Bitte überprüfen Sie Ihre Browsereinstellungen, um den erforderlichen Zugriff zu erlauben.",
 	"Clone": "Klonen",
-	"Close": "Schließe",
-	"Code formatted successfully": "",
+	"Close": "Schließen",
+	"Code formatted successfully": "Code erfolgreich formatiert",
 	"Collection": "Kollektion",
 	"ComfyUI": "ComfyUI",
-	"ComfyUI Base URL": "ComfyUI Base URL",
-	"ComfyUI Base URL is required.": "ComfyUI Base URL wird benötigt.",
+	"ComfyUI Base URL": "ComfyUI-Basis-URL",
+	"ComfyUI Base URL is required.": "ComfyUI-Basis-URL wird benötigt.",
 	"Command": "Befehl",
 	"Concurrent Requests": "Gleichzeitige Anforderungen",
-	"Confirm": "",
+	"Confirm": "Bestätigen",
 	"Confirm Password": "Passwort bestätigen",
-	"Confirm your action": "",
+	"Confirm your action": "Bestätigen Sie Ihre Aktion.",
 	"Connections": "Verbindungen",
-	"Contact Admin for WebUI Access": "",
+	"Contact Admin for WebUI Access": "Kontaktieren Sie den Administrator für den Zugriff auf die Weboberfläche",
 	"Content": "Info",
-	"Context Length": "Context Length",
+	"Content Extraction": "",
+	"Context Length": "Kontextlänge",
 	"Continue Response": "Antwort fortsetzen",
-	"Continue with {{provider}}": "",
-	"Copied shared chat URL to clipboard!": "Geteilte Chat-URL in die Zwischenablage kopiert!",
+	"Continue with {{provider}}": "Mit {{Anbieter}} fortfahren",
+	"Copied shared chat URL to clipboard!": "Freigabelink in die Zwischenablage kopiert!",
 	"Copy": "Kopieren",
 	"Copy last code block": "Letzten Codeblock kopieren",
 	"Copy last response": "Letzte Antwort kopieren",
@@ -138,17 +139,17 @@
 	"Create a model": "Ein Modell erstellen",
 	"Create Account": "Konto erstellen",
 	"Create new key": "Neuen Schlüssel erstellen",
-	"Create new secret key": "Neuen API Schlüssel erstellen",
+	"Create new secret key": "Neuen API-Schlüssel erstellen",
 	"Created at": "Erstellt am",
 	"Created At": "Erstellt am",
-	"Created by": "",
-	"CSV Import": "",
+	"Created by": "Erstellt von",
+	"CSV Import": "CSV-Import",
 	"Current Model": "Aktuelles Modell",
 	"Current Password": "Aktuelles Passwort",
 	"Custom": "Benutzerdefiniert",
 	"Customize models for a specific purpose": "Modelle für einen bestimmten Zweck anpassen",
 	"Dark": "Dunkel",
-	"Dashboard": "",
+	"Dashboard": "Übersicht",
 	"Database": "Datenbank",
 	"December": "Dezember",
 	"Default": "Standard",
@@ -156,67 +157,68 @@
 	"Default (SentenceTransformers)": "Standard (SentenceTransformers)",
 	"Default Model": "Standardmodell",
 	"Default model updated": "Standardmodell aktualisiert",
-	"Default Prompt Suggestions": "Standard-Prompt-Vorschläge",
+	"Default Prompt Suggestions": "Prompt-Vorschläge",
 	"Default User Role": "Standardbenutzerrolle",
 	"delete": "löschen",
 	"Delete": "Löschen",
 	"Delete a model": "Ein Modell löschen",
-	"Delete All Chats": "Alle Chats löschen",
-	"Delete chat": "Chat löschen",
-	"Delete Chat": "Chat löschen",
-	"Delete chat?": "",
-	"Delete function?": "",
-	"Delete prompt?": "",
-	"delete this link": "diesen Link zu löschen",
-	"Delete tool?": "",
+	"Delete All Chats": "Alle Unterhaltungen löschen",
+	"Delete chat": "Unterhaltung löschen",
+	"Delete Chat": "Unterhaltung löschen",
+	"Delete chat?": "Unterhaltung löschen?",
+	"Delete function?": "Funktion löschen?",
+	"Delete prompt?": "Prompt löschen?",
+	"delete this link": "diesen Link löschen",
+	"Delete tool?": "Werkzeug löschen?",
 	"Delete User": "Benutzer löschen",
 	"Deleted {{deleteModelTag}}": "{{deleteModelTag}} gelöscht",
-	"Deleted {{name}}": "Gelöscht {{name}}",
+	"Deleted {{name}}": "{{name}} gelöscht",
 	"Description": "Beschreibung",
 	"Didn't fully follow instructions": "Nicht genau den Answeisungen gefolgt",
-	"Discover a function": "",
-	"Discover a model": "Entdecken Sie ein Modell",
-	"Discover a prompt": "Einen Prompt entdecken",
-	"Discover a tool": "",
-	"Discover, download, and explore custom functions": "",
-	"Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden",
-	"Discover, download, and explore custom tools": "",
-	"Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden",
+	"Discover a function": "Entdecken Sie weitere Funktionen",
+	"Discover a model": "Entdecken Sie weitere Modelle",
+	"Discover a prompt": "Entdecken Sie weitere Prompts",
+	"Discover a tool": "Entdecken Sie weitere Werkzeuge",
+	"Discover, download, and explore custom functions": "Entdecken und beziehen Sie benutzerdefinierte Funktionen",
+	"Discover, download, and explore custom prompts": "Entdecken und beziehen Sie benutzerdefinierte Prompts",
+	"Discover, download, and explore custom tools": "Entdecken und beziehen Sie benutzerdefinierte Werkzeuge",
+	"Discover, download, and explore model presets": "Entdecken und beziehen Sie benutzerdefinierte Modellvorlagen",
 	"Dismissible": "ausblendbar",
-	"Display Emoji in Call": "",
-	"Display the username instead of You in the Chat": "Den Benutzernamen anstelle von 'du' im Chat anzeigen",
+	"Display Emoji in Call": "Emojis im Anruf anzeigen",
+	"Display the username instead of You in the Chat": "Soll \"Sie\" durch Ihren Benutzernamen ersetzt werden?",
 	"Document": "Dokument",
 	"Document Settings": "Dokumenteinstellungen",
 	"Documentation": "Dokumentation",
 	"Documents": "Dokumente",
-	"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Deine Daten bleiben sicher auf Deinen lokal gehosteten Server.",
+	"does not make any external connections, and your data stays securely on your locally hosted server.": "stellt keine externen Verbindungen her, und Ihre Daten bleiben sicher auf Ihrem lokal gehosteten Server.",
 	"Don't Allow": "Nicht erlauben",
-	"Don't have an account?": "Hast du vielleicht noch kein Konto?",
-	"Don't like the style": "Dir gefällt der Style nicht",
-	"Done": "",
-	"Download": "Herunterladen",
-	"Download canceled": "Download abgebrochen",
-	"Download Database": "Datenbank herunterladen",
-	"Drop any files here to add to the conversation": "Ziehe Dateien in diesen Bereich, um sie an den Chat anzuhängen",
-	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "z.B. '30s','10m'. Gültige Zeiteinheiten sind 's', 'm', 'h'.",
+	"Don't have an account?": "Haben Sie noch kein Benutzerkonto?",
+	"Don't like the style": "schlechter Schreibstil",
+	"Done": "Erledigt",
+	"Download": "Exportieren",
+	"Download canceled": "Exportierung abgebrochen",
+	"Download Database": "Datenbank exportieren",
+	"Drop any files here to add to the conversation": "Ziehen Sie beliebige Dateien hierher, um sie der Unterhaltung hinzuzufügen",
+	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "z. B. '30s','10m'. Gültige Zeiteinheiten sind 's', 'm', 'h'.",
 	"Edit": "Bearbeiten",
 	"Edit Doc": "Dokument bearbeiten",
-	"Edit Memory": "",
+	"Edit Memory": "Erinnerungen bearbeiten",
 	"Edit User": "Benutzer bearbeiten",
 	"Email": "E-Mail",
 	"Embedding Batch Size": "Embedding Batch Größe",
 	"Embedding Model": "Embedding-Modell",
 	"Embedding Model Engine": "Embedding-Modell-Engine",
 	"Embedding model set to \"{{embedding_model}}\"": "Embedding-Modell auf \"{{embedding_model}}\" gesetzt",
-	"Enable Chat History": "Chat-Verlauf aktivieren",
+	"Enable Chat History": "Unterhaltungshistorie aktivieren",
 	"Enable Community Sharing": "Community-Freigabe aktivieren",
-	"Enable New Sign Ups": "Neue Anmeldungen aktivieren",
+	"Enable New Sign Ups": "Registrierung erlauben",
 	"Enable Web Search": "Websuche aktivieren",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Stellen Sie sicher, dass Ihre CSV-Datei 4 Spalten in dieser Reihenfolge enthält: Name, E-Mail, Passwort, Rolle.",
-	"Enter {{role}} message here": "Gib die {{role}} Nachricht hier ein",
-	"Enter a detail about yourself for your LLMs to recall": "Geben Sie einen Detail über sich selbst ein, um für Ihre LLMs zu erinnern",
-	"Enter api auth string (e.g. username:password)": "",
-	"Enter Brave Search API Key": "Geben Sie den API-Schlüssel für die Brave-Suche ein",
+	"Enter {{role}} message here": "Geben Sie die {{role}}-Nachricht hier ein",
+	"Enter a detail about yourself for your LLMs to recall": "Geben Sie ein Detail über sich selbst ein, das Ihre Sprachmodelle (LLMs) sich merken sollen",
+	"Enter api auth string (e.g. username:password)": "Geben Sie die API-Authentifizierungszeichenfolge ein (z. B. Benutzername:Passwort)",
+	"Enter Brave Search API Key": "Geben Sie den Brave Search API-Schlüssel ein",
 	"Enter Chunk Overlap": "Gib den Chunk Overlap ein",
 	"Enter Chunk Size": "Gib die Chunk Size ein",
 	"Enter Github Raw URL": "Geben Sie die Github Raw-URL ein",
@@ -226,62 +228,63 @@
 	"Enter language codes": "Geben Sie die Sprachcodes ein",
 	"Enter model tag (e.g. {{modelTag}})": "Gib den Model-Tag ein",
 	"Enter Number of Steps (e.g. 50)": "Gib die Anzahl an Schritten ein (z.B. 50)",
-	"Enter Score": "Score eingeben",
+	"Enter Score": "Punktzahl eingeben",
 	"Enter Searxng Query URL": "Geben Sie die Searxng-Abfrage-URL ein",
-	"Enter Serper API Key": "Serper-API-Schlüssel eingeben",
-	"Enter Serply API Key": "",
+	"Enter Serper API Key": "Geben Sie den Serper-API-Schlüssel ein",
+	"Enter Serply API Key": "Geben Sie den",
 	"Enter Serpstack API Key": "Geben Sie den Serpstack-API-Schlüssel ein",
 	"Enter stop sequence": "Stop-Sequenz eingeben",
-	"Enter Tavily API Key": "",
-	"Enter Top K": "Gib Top K ein",
-	"Enter URL (e.g. http://127.0.0.1:7860/)": "Gib die URL ein (z.B. http://127.0.0.1:7860/)",
-	"Enter URL (e.g. http://localhost:11434)": "Gib die URL ein (z.B. http://localhost:11434)",
-	"Enter Your Email": "E-Mail-Adresse",
-	"Enter Your Full Name": "Name",
-	"Enter Your Password": "Passwort",
-	"Enter Your Role": "Gebe deine Rolle ein",
+	"Enter Tavily API Key": "Geben Sie den Tavily-API-Schlüssel ein",
+	"Enter Tika Server URL": "",
+	"Enter Top K": "Geben Sie Top K ein",
+	"Enter URL (e.g. http://127.0.0.1:7860/)": "Geben Sie die URL ein (z. B. http://127.0.0.1:7860/)",
+	"Enter URL (e.g. http://localhost:11434)": "Geben Sie die URL ein (z. B. http://localhost:11434)",
+	"Enter Your Email": "Geben Sie Ihre E-Mail-Adresse ein",
+	"Enter Your Full Name": "Geben Sie Ihren vollständigen Namen ein",
+	"Enter Your Password": "Geben Sie Ihr Passwort ein",
+	"Enter Your Role": "Geben Sie Ihre Rolle ein",
 	"Error": "Fehler",
 	"Experimental": "Experimentell",
 	"Export": "Exportieren",
-	"Export All Chats (All Users)": "Alle Chats exportieren (alle Benutzer)",
-	"Export chat (.json)": "Chat exportieren (.json)",
-	"Export Chats": "Chats exportieren",
-	"Export Documents Mapping": "Dokumentenmapping exportieren",
-	"Export Functions": "",
-	"Export LiteLLM config.yaml": "",
+	"Export All Chats (All Users)": "Alle Unterhaltungen exportieren (alle Benutzer)",
+	"Export chat (.json)": "Unterhaltung exportieren (.json)",
+	"Export Chats": "Unterhaltungen exportieren",
+	"Export Documents Mapping": "Dokumentenzuordnung exportieren",
+	"Export Functions": "Funktionen exportieren",
+	"Export LiteLLM config.yaml": "LiteLLM-Konfiguration exportieren (config.yaml)",
 	"Export Models": "Modelle exportieren",
 	"Export Prompts": "Prompts exportieren",
-	"Export Tools": "",
-	"External Models": "",
-	"Failed to create API Key.": "API Key erstellen fehlgeschlagen",
-	"Failed to read clipboard contents": "Fehler beim Lesen des Zwischenablageninhalts",
+	"Export Tools": "Werkzeuge exportieren",
+	"External Models": "Externe Modelle",
+	"Failed to create API Key.": "Fehler beim Erstellen des API-Schlüssels.",
+	"Failed to read clipboard contents": "Fehler beim Abruf der Zwischenablage",
 	"Failed to update settings": "Fehler beim Aktualisieren der Einstellungen",
 	"February": "Februar",
-	"Feel free to add specific details": "Ergänze Details.",
-	"File": "",
-	"File Mode": "File Modus",
+	"Feel free to add specific details": "Fühlen Sie sich frei, spezifische Details hinzuzufügen",
+	"File": "Datei",
+	"File Mode": "Datei-Modus",
 	"File not found.": "Datei nicht gefunden.",
-	"Filter is now globally disabled": "",
-	"Filter is now globally enabled": "",
-	"Filters": "",
-	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint spoofing erkannt: Initialen können nicht als Avatar verwendet werden. Es wird auf das Standardprofilbild zurückgegriffen.",
-	"Fluidly stream large external response chunks": "Große externe Antwortblöcke flüssig streamen",
+	"Filter is now globally disabled": "Filter ist jetzt global deaktiviert",
+	"Filter is now globally enabled": "Filter ist jetzt global aktiviert",
+	"Filters": "Filter",
+	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerabdruck-Spoofing erkannt: Initialen können nicht als Avatar verwendet werden. Standard-Avatar wird verwendet.",
+	"Fluidly stream large external response chunks": "Nahtlose Übertragung großer externer Antwortabschnitte",
 	"Focus chat input": "Chat-Eingabe fokussieren",
 	"Followed instructions perfectly": "Anweisungen perfekt befolgt",
-	"Form": "",
-	"Format your variables using square brackets like this:": "Formatiere deine Variablen mit eckigen Klammern wie folgt:",
-	"Frequency Penalty": "Frequenz-Strafe",
-	"Function created successfully": "",
-	"Function deleted successfully": "",
-	"Function updated successfully": "",
-	"Functions": "",
-	"Functions imported successfully": "",
+	"Form": "Formular",
+	"Format your variables using square brackets like this:": "Formatieren Sie Ihre Variablen mit eckigen Klammern wie folgt:",
+	"Frequency Penalty": "Frequenzstrafe",
+	"Function created successfully": "Funktion erfolgreich erstellt",
+	"Function deleted successfully": "Funktion erfolgreich gelöscht",
+	"Function updated successfully": "Funktion erfolgreich aktualisiert",
+	"Functions": "Funktionen",
+	"Functions imported successfully": "Funktionen erfolgreich importiert",
 	"General": "Allgemein",
 	"General Settings": "Allgemeine Einstellungen",
-	"Generate Image": "",
-	"Generating search query": "Suchanfrage generieren",
+	"Generate Image": "Bild erzeugen",
+	"Generating search query": "Suchanfrage wird erstellt",
 	"Generation Info": "Generierungsinformationen",
-	"Global": "",
+	"Global": "Global",
 	"Good Response": "Gute Antwort",
 	"Google PSE API Key": "Google PSE-API-Schlüssel",
 	"Google PSE Engine Id": "Google PSE-Engine-ID",
@@ -290,25 +293,25 @@
 	"Hello, {{name}}": "Hallo, {{name}}",
 	"Help": "Hilfe",
 	"Hide": "Verbergen",
-	"Hide Model": "",
-	"How can I help you today?": "Wie kann ich dir heute helfen?",
+	"Hide Model": "Modell ausblenden",
+	"How can I help you today?": "Wie kann ich Ihnen heute helfen?",
 	"Hybrid Search": "Hybride Suche",
 	"Image Generation (Experimental)": "Bildgenerierung (experimentell)",
 	"Image Generation Engine": "Bildgenerierungs-Engine",
 	"Image Settings": "Bildeinstellungen",
 	"Images": "Bilder",
 	"Import Chats": "Chats importieren",
-	"Import Documents Mapping": "Dokumentenmapping importieren",
-	"Import Functions": "",
+	"Import Documents Mapping": "Dokumentenzuordnung importieren",
+	"Import Functions": "Funktionen importieren",
 	"Import Models": "Modelle importieren",
 	"Import Prompts": "Prompts importieren",
-	"Import Tools": "",
-	"Include `--api-auth` flag when running stable-diffusion-webui": "",
-	"Include `--api` flag when running stable-diffusion-webui": "Füge das `--api`-Flag hinzu, wenn du stable-diffusion-webui nutzt",
+	"Import Tools": "Werkzeuge importieren",
+	"Include `--api-auth` flag when running stable-diffusion-webui": "Fügen Sie beim Ausführen von stable-diffusion-webui die Option `--api-auth` hinzu",
+	"Include `--api` flag when running stable-diffusion-webui": "Fügen Sie beim Ausführen von stable-diffusion-webui die Option `--api` hinzu",
 	"Info": "Info",
 	"Input commands": "Eingabebefehle",
-	"Install from Github URL": "Installieren Sie von der Github-URL",
-	"Instant Auto-Send After Voice Transcription": "",
+	"Install from Github URL": "Installiere von der Github-URL",
+	"Instant Auto-Send After Voice Transcription": "Spracherkennung direkt absenden",
 	"Interface": "Benutzeroberfläche",
 	"Invalid Tag": "Ungültiger Tag",
 	"January": "Januar",
@@ -319,56 +322,56 @@
 	"June": "Juni",
 	"JWT Expiration": "JWT-Ablauf",
 	"JWT Token": "JWT-Token",
-	"Keep Alive": "Keep Alive",
-	"Keyboard shortcuts": "Tastenkürzel",
-	"Knowledge": "",
+	"Keep Alive": "Verbindung aufrechterhalten",
+	"Keyboard shortcuts": "Tastenkombinationen",
+	"Knowledge": "Wissen",
 	"Language": "Sprache",
 	"Last Active": "Zuletzt aktiv",
-	"Last Modified": "",
+	"Last Modified": "Zuletzt bearbeitet",
 	"Light": "Hell",
-	"Listening...": "",
+	"Listening...": "Höre zu...",
 	"LLMs can make mistakes. Verify important information.": "LLMs können Fehler machen. Überprüfe wichtige Informationen.",
-	"Local Models": "",
+	"Local Models": "Lokale Modelle",
 	"LTR": "LTR",
 	"Made by OpenWebUI Community": "Von der OpenWebUI-Community",
-	"Make sure to enclose them with": "Formatiere deine Variablen mit:",
+	"Make sure to enclose them with": "Umschließe Variablen mit",
 	"Manage": "Verwalten",
 	"Manage Models": "Modelle verwalten",
 	"Manage Ollama Models": "Ollama-Modelle verwalten",
-	"Manage Pipelines": "Verwalten von Pipelines",
-	"Manage Valves": "",
+	"Manage Pipelines": "Pipelines verwalten",
+	"Manage Valves": "Valves verwalten",
 	"March": "März",
-	"Max Tokens (num_predict)": "Max. Token (num_predict)",
-	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es können maximal 3 Modelle gleichzeitig heruntergeladen werden. Bitte versuche es später erneut.",
+	"Max Tokens (num_predict)": "Maximale Tokenanzahl (num_predict)",
+	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es können maximal 3 Modelle gleichzeitig heruntergeladen werden. Bitte versuchen Sie es später erneut.",
 	"May": "Mai",
-	"Memories accessible by LLMs will be shown here.": "Memories, die von LLMs zugänglich sind, werden hier angezeigt.",
-	"Memory": "Memory",
-	"Memory added successfully": "",
-	"Memory cleared successfully": "",
-	"Memory deleted successfully": "",
-	"Memory updated successfully": "",
-	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Nachdem Sie Ihren Link erstellt haben, werden Ihre Nachrichten nicht geteilt. Benutzer mit dem Link können den geteilten Chat sehen.",
-	"Minimum Score": "Mindestscore",
+	"Memories accessible by LLMs will be shown here.": "Erinnerungen, die für Modelle zugänglich sind, werden hier angezeigt.",
+	"Memory": "Erinnerung",
+	"Memory added successfully": "Erinnerung erfolgreich hinzugefügt",
+	"Memory cleared successfully": "Erinnerung erfolgreich gelöscht",
+	"Memory deleted successfully": "Erinnerung erfolgreich gelöscht",
+	"Memory updated successfully": "Erinnerung erfolgreich aktualisiert",
+	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Nachrichten, die Sie nach der Erstellung Ihres Links senden, werden nicht geteilt. Nutzer mit der URL können die freigegebene Unterhaltung einsehen.",
+	"Minimum Score": "Mindestpunktzahl",
 	"Mirostat": "Mirostat",
 	"Mirostat Eta": "Mirostat Eta",
 	"Mirostat Tau": "Mirostat Tau",
 	"MMMM DD, YYYY": "DD MMMM YYYY",
 	"MMMM DD, YYYY HH:mm": "DD MMMM YYYY HH:mm",
-	"MMMM DD, YYYY hh:mm:ss A": "",
+	"MMMM DD, YYYY hh:mm:ss A": "DD MMMM YYYY HH:mm A",
 	"Model '{{modelName}}' has been successfully downloaded.": "Modell '{{modelName}}' wurde erfolgreich heruntergeladen.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "Modell '{{modelTag}}' befindet sich bereits in der Warteschlange zum Herunterladen.",
 	"Model {{modelId}} not found": "Modell {{modelId}} nicht gefunden",
-	"Model {{modelName}} is not vision capable": "Das Modell {{modelName}} ist nicht sehfähig",
+	"Model {{modelName}} is not vision capable": "Das Modell {{modelName}} ist nicht für die Bildverarbeitung geeignet",
 	"Model {{name}} is now {{status}}": "Modell {{name}} ist jetzt {{status}}",
-	"Model created successfully!": "",
+	"Model created successfully!": "Modell erfolgreich erstellt!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Modell-Dateisystempfad erkannt. Modellkurzname ist für das Update erforderlich, Fortsetzung nicht möglich.",
 	"Model ID": "Modell-ID",
 	"Model not selected": "Modell nicht ausgewählt",
 	"Model Params": "Modell-Params",
-	"Model updated successfully": "",
+	"Model updated successfully": "Modell erfolgreich aktualisiert",
 	"Model Whitelisting": "Modell-Whitelisting",
 	"Model(s) Whitelisted": "Modell(e) auf der Whitelist",
-	"Modelfile Content": "Modelfile Content",
+	"Modelfile Content": "Modelfile-Inhalt",
 	"Models": "Modelle",
 	"More": "Mehr",
 	"Name": "Name",
@@ -376,59 +379,62 @@
 	"Name your model": "Benennen Sie Ihr Modell",
 	"New Chat": "Neuer Chat",
 	"New Password": "Neues Passwort",
-	"No content to speak": "",
-	"No documents found": "",
-	"No file selected": "",
+	"No content to speak": "Kein Inhalt zum Vorlesen",
+	"No documents found": "Keine Dokumente gefunden",
+	"No file selected": "Keine Datei ausgewählt",
 	"No results found": "Keine Ergebnisse gefunden",
 	"No search query generated": "Keine Suchanfrage generiert",
-	"No source available": "Keine Quelle verfügbar.",
-	"No valves to update": "",
+	"No source available": "Keine Quelle verfügbar",
+	"No valves to update": "Keine Valves zum Aktualisieren",
 	"None": "Nichts",
-	"Not factually correct": "Nicht sachlich korrekt.",
-	"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 du einen Mindestscore festlegst, wird die Suche nur Dokumente zurückgeben, deren Score größer oder gleich dem Mindestscore ist.",
-	"Notifications": "Desktop-Benachrichtigungen",
+	"Not factually correct": "Nicht sachlich korrekt",
+	"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.",
+	"Notifications": "Benachrichtigungen",
 	"November": "November",
 	"num_thread (Ollama)": "num_thread (Ollama)",
-	"OAuth ID": "",
+	"OAuth ID": "OAuth-ID",
 	"October": "Oktober",
 	"Off": "Aus",
 	"Okay, Let's Go!": "Okay, los geht's!",
-	"OLED Dark": "OLED Dunkel",
+	"OLED Dark": "OLED-Dunkel",
 	"Ollama": "Ollama",
 	"Ollama API": "Ollama-API",
 	"Ollama API disabled": "Ollama-API deaktiviert",
-	"Ollama API is disabled": "",
+	"Ollama API is disabled": "Ollama-API  ist deaktiviert.",
 	"Ollama Version": "Ollama-Version",
 	"On": "Ein",
 	"Only": "Nur",
-	"Only alphanumeric characters and hyphens are allowed in the command string.": "Nur alphanumerische Zeichen und Bindestriche sind im Befehlsstring erlaubt.",
-	"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Hoppla! Warte noch einen Moment! Die Dateien sind noch im der Verarbeitung. Bitte habe etwas Geduld und wir informieren Dich, sobald sie bereit sind.",
-	"Oops! Looks like the URL is invalid. Please double-check and try again.": "Hoppla! Es sieht so aus, als wäre die URL ungültig. Bitte überprüfe sie und versuche es nochmal.",
-	"Oops! There was an error in the previous response. Please try again or contact admin.": "",
-	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Hoppla! du verwendest eine nicht unterstützte Methode (nur Frontend). Bitte stelle die WebUI vom Backend aus bereit.",
+	"Only alphanumeric characters and hyphens are allowed in the command string.": "In der Befehlszeichenfolge sind nur alphanumerische Zeichen und Bindestriche erlaubt.",
+	"Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ups! Bitte gedulden Sie sich einen Moment! Ihre Dateien sind noch in der Verarbeitung. Wir bereiten sie sorgfältig vor. Bitte haben Sie etwas Geduld, und wir werden Sie benachrichtigen, sobald sie fertig sind.",
+	"Oops! Looks like the URL is invalid. Please double-check and try again.": "Hoppla! Es scheint, dass die URL ungültig ist. Bitte überprüfen Sie diese und versuchen Sie es erneut.",
+	"Oops! There was an error in the previous response. Please try again or contact admin.": "Hoppla! Es gab einen Fehler in der vorherigen Antwort. Bitte versuchen Sie es erneut oder kontaktieren Sie den Administrator.",
+	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Hoppla! Sie verwenden eine nicht unterstützte Methode (nur Frontend). Bitte stellen Sie die WebUI vom Backend bereit.",
 	"Open": "Öffne",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Neuen Chat öffnen",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI-API",
-	"OpenAI API Config": "OpenAI API Konfiguration",
-	"OpenAI API Key is required.": "OpenAI API Key erforderlich.",
-	"OpenAI URL/Key required.": "OpenAI URL/Key erforderlich.",
+	"OpenAI API Config": "OpenAI-API-Konfiguration",
+	"OpenAI API Key is required.": "OpenAI-API-Schlüssel erforderlich.",
+	"OpenAI URL/Key required.": "OpenAI-URL/Schlüssel erforderlich.",
 	"or": "oder",
 	"Other": "Andere",
 	"Password": "Passwort",
 	"PDF document (.pdf)": "PDF-Dokument (.pdf)",
 	"PDF Extract Images (OCR)": "Text von Bildern aus PDFs extrahieren (OCR)",
 	"pending": "ausstehend",
-	"Permission denied when accessing media devices": "",
-	"Permission denied when accessing microphone": "",
+	"Permission denied when accessing media devices": "Zugriff auf Mediengeräte verweigert",
+	"Permission denied when accessing microphone": "Zugriff auf das Mikrofon verweigert",
 	"Permission denied when accessing microphone: {{error}}": "Zugriff auf das Mikrofon verweigert: {{error}}",
 	"Personalization": "Personalisierung",
-	"Pipeline deleted successfully": "",
-	"Pipeline downloaded successfully": "",
+	"Pin": "",
+	"Pinned": "",
+	"Pipeline deleted successfully": "Pipeline erfolgreich gelöscht",
+	"Pipeline downloaded successfully": "Pipeline erfolgreich heruntergeladen",
 	"Pipelines": "Pipelines",
-	"Pipelines Not Detected": "",
-	"Pipelines Valves": "Rohrleitungen Ventile",
+	"Pipelines Not Detected": "Pipelines nicht erkannt",
+	"Pipelines Valves": "Pipeline Valves",
 	"Plain text (.txt)": "Nur Text (.txt)",
 	"Playground": "Testumgebung",
 	"Positive attitude": "Positive Einstellung",
@@ -436,232 +442,235 @@
 	"Previous 7 days": "Vorherige 7 Tage",
 	"Profile Image": "Profilbild",
 	"Prompt": "Prompt",
-	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (z.B. Erzähle mir eine interessante Tatsache über das Römische Reich.",
+	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (z. B. \"Erzähle mir eine interessante Tatsache über das Römische Reich\")",
 	"Prompt Content": "Prompt-Inhalt",
 	"Prompt suggestions": "Prompt-Vorschläge",
 	"Prompts": "Prompts",
-	"Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" von Ollama.com herunterladen",
-	"Pull a model from Ollama.com": "Ein Modell von Ollama.com abrufen",
-	"Query Params": "Abfrage Parameter",
-	"RAG Template": "RAG-Template",
+	"Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" von Ollama.com beziehen",
+	"Pull a model from Ollama.com": "Modell von Ollama.com beziehn",
+	"Query Params": "Abfrageparameter",
+	"RAG Template": "RAG-Vorlage",
 	"Read Aloud": "Vorlesen",
 	"Record voice": "Stimme aufnehmen",
-	"Redirecting you to OpenWebUI Community": "Du wirst zur OpenWebUI-Community weitergeleitet",
+	"Redirecting you to OpenWebUI Community": "Sie werden zur OpenWebUI-Community weitergeleitet",
 	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
-	"Refused when it shouldn't have": "Abgelehnt, obwohl es nicht hätte sein sollen.",
+	"Refused when it shouldn't have": "Abgelehnt, obwohl es nicht hätte abgelehnt werden sollen",
 	"Regenerate": "Neu generieren",
-	"Release Notes": "Versionshinweise",
+	"Release Notes": "Veröffentlichungshinweise",
 	"Remove": "Entfernen",
 	"Remove Model": "Modell entfernen",
 	"Rename": "Umbenennen",
-	"Repeat Last N": "Repeat Last N",
-	"Request Mode": "Request-Modus",
-	"Reranking Model": "Reranking Modell",
-	"Reranking model disabled": "Rranking Modell deaktiviert",
-	"Reranking model set to \"{{reranking_model}}\"": "Reranking Modell auf \"{{reranking_model}}\" gesetzt",
-	"Reset": "",
-	"Reset Upload Directory": "Uploadverzeichnis löschen",
+	"Repeat Last N": "Wiederhole die letzten N",
+	"Request Mode": "Anforderungsmodus",
+	"Reranking Model": "Reranking-Modell",
+	"Reranking model disabled": "Reranking-Modell deaktiviert",
+	"Reranking model set to \"{{reranking_model}}\"": "Reranking-Modell \"{{reranking_model}}\" fesgelegt",
+	"Reset": "Zurücksetzen",
+	"Reset Upload Directory": "Upload-Verzeichnis zurücksetzen",
 	"Reset Vector Storage": "Vektorspeicher zurücksetzen",
 	"Response AutoCopy to Clipboard": "Antwort automatisch in die Zwischenablage kopieren",
-	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "",
+	"Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "Benachrichtigungen können nicht aktiviert werden, da die Website-Berechtigungen abgelehnt wurden. Bitte besuchen Sie Ihre Browser-Einstellungen, um den erforderlichen Zugriff zu gewähren.",
 	"Role": "Rolle",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"RTL": "RTL",
 	"Running": "Läuft",
 	"Save": "Speichern",
-	"Save & Create": "Speichern und erstellen",
-	"Save & Update": "Speichern und aktualisieren",
-	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Das direkte Speichern von Chat-Protokollen im Browser-Speicher wird nicht mehr unterstützt. Bitte nimm dir einen Moment Zeit, um deine Chat-Protokolle herunterzuladen und zu löschen, indem du auf die Schaltfläche unten klickst. Keine Sorge, du kannst deine Chat-Protokolle problemlos über das Backend wieder importieren.",
+	"Save & Create": "Erstellen",
+	"Save & Update": "Aktualisieren",
+	"Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Das direkte Speichern von Unterhaltungen im Browser-Speicher wird nicht mehr unterstützt. Bitte nehmen Sie einen Moment Zeit, um Ihre Unterhaltungen zu exportieren und zu löschen, indem Sie auf die Schaltfläche unten klicken. Keine Sorge, Sie können Ihre Unterhaltungen problemlos über das Backend wieder importieren.",
 	"Scan": "Scannen",
 	"Scan complete!": "Scan abgeschlossen!",
-	"Scan for documents from {{path}}": "Dokumente von {{path}} scannen",
+	"Scan for documents from {{path}}": "Dokumente im {{path}} scannen",
 	"Search": "Suchen",
-	"Search a model": "Nach einem Modell suchen",
-	"Search Chats": "Chats durchsuchen",
-	"Search Documents": "Dokumente suchen",
-	"Search Functions": "",
-	"Search Models": "Modelle suchen",
-	"Search Prompts": "Prompts suchen",
-	"Search Query Generation Prompt": "",
-	"Search Query Generation Prompt Length Threshold": "",
+	"Search a model": "Modell suchen",
+	"Search Chats": "Unterhaltungen durchsuchen...",
+	"Search Documents": "Dokumente durchsuchen...",
+	"Search Functions": "Funktionen durchsuchen...",
+	"Search Models": "Modelle durchsuchen...",
+	"Search Prompts": "Prompts durchsuchen...",
+	"Search Query Generation Prompt": "Suchanfragen-Generierungs-Prompt",
+	"Search Query Generation Prompt Length Threshold": "Suchanfragen-Generierungs-Prompt-Längenschwellenwert",
 	"Search Result Count": "Anzahl der Suchergebnisse",
-	"Search Tools": "",
-	"Searched {{count}} sites_one": "Gesucht {{count}} sites_one",
-	"Searched {{count}} sites_other": "Gesucht {{count}} sites_other",
-	"Searching \"{{searchQuery}}\"": "",
+	"Search Tools": "Suchwerkzeuge",
+	"Searched {{count}} sites_one": "{{count}} Seite durchsucht",
+	"Searched {{count}} sites_other": "{{count}} Seiten durchsucht",
+	"Searching \"{{searchQuery}}\"": "Suche nach \"{{searchQuery}}\"",
 	"Searxng Query URL": "Searxng-Abfrage-URL",
 	"See readme.md for instructions": "Anleitung in readme.md anzeigen",
-	"See what's new": "Was gibt's Neues",
+	"See what's new": "Entdecken Sie die Neuigkeiten",
 	"Seed": "Seed",
 	"Select a base model": "Wählen Sie ein Basismodell",
-	"Select a engine": "Wähle eine Engine",
-	"Select a function": "",
-	"Select a mode": "Einen Modus auswählen",
-	"Select a model": "Ein Modell auswählen",
-	"Select a pipeline": "Wählen Sie eine Pipeline aus",
-	"Select a pipeline url": "Auswählen einer Pipeline-URL",
-	"Select a tool": "",
-	"Select an Ollama instance": "Eine Ollama Instanz auswählen",
-	"Select Documents": "",
+	"Select a engine": "Wählen Sie eine Engine",
+	"Select a function": "Wählen Sie eine Funktion",
+	"Select a mode": "Wählen Sie einen Modus",
+	"Select a model": "Wählen Sie ein Modell",
+	"Select a pipeline": "Wählen Sie eine Pipeline",
+	"Select a pipeline url": "Wählen Sie eine Pipeline-URL",
+	"Select a tool": "Wählen Sie ein Werkzeug",
+	"Select an Ollama instance": "Wählen Sie eine Ollama-Instanz",
+	"Select Documents": "Dokumente auswählen",
 	"Select model": "Modell auswählen",
-	"Select only one model to call": "",
-	"Selected model(s) do not support image inputs": "Ausgewählte Modelle unterstützen keine Bildeingaben",
+	"Select only one model to call": "Wählen Sie nur ein Modell zum Anrufen aus",
+	"Selected model(s) do not support image inputs": "Ihre ausgewählten Modelle unterstützen keine Bildeingaben",
 	"Send": "Senden",
 	"Send a Message": "Eine Nachricht senden",
 	"Send message": "Nachricht senden",
 	"September": "September",
 	"Serper API Key": "Serper-API-Schlüssel",
-	"Serply API Key": "",
+	"Serply API Key": "Serply-API-Schlüssel",
 	"Serpstack API Key": "Serpstack-API-Schlüssel",
 	"Server connection verified": "Serververbindung überprüft",
 	"Set as default": "Als Standard festlegen",
 	"Set Default Model": "Standardmodell festlegen",
-	"Set embedding model (e.g. {{model}})": "Eingabemodell festlegen (z.B. {{model}})",
+	"Set embedding model (e.g. {{model}})": "Einbettungsmodell festlegen (z. B. {{model}})",
 	"Set Image Size": "Bildgröße festlegen",
-	"Set reranking model (e.g. {{model}})": "Rerankingmodell festlegen (z.B. {{model}})",
-	"Set Steps": "Schritte festlegen",
+	"Set reranking model (e.g. {{model}})": "Rerankingmodell festlegen (z. B. {{model}})",
+	"Set Steps": "Schrittgröße festlegen",
 	"Set Task Model": "Aufgabenmodell festlegen",
 	"Set Voice": "Stimme festlegen",
 	"Settings": "Einstellungen",
 	"Settings saved successfully!": "Einstellungen erfolgreich gespeichert!",
-	"Settings updated successfully": "Settings updated successfully",
+	"Settings updated successfully": "Einstellungen erfolgreich aktualisiert",
 	"Share": "Teilen",
-	"Share Chat": "Chat teilen",
+	"Share Chat": "Unterhaltung teilen",
 	"Share to OpenWebUI Community": "Mit OpenWebUI Community teilen",
 	"short-summary": "kurze-zusammenfassung",
 	"Show": "Anzeigen",
 	"Show Admin Details in Account Pending Overlay": "Admin-Details im Account-Pending-Overlay anzeigen",
-	"Show Model": "",
+	"Show Model": "Modell anzeigen",
 	"Show shortcuts": "Verknüpfungen anzeigen",
-	"Show your support!": "",
-	"Showcased creativity": "Kreativität zur Schau gestellt",
+	"Show your support!": "Zeigen Sie Ihre Unterstützung!",
+	"Showcased creativity": "Kreativität gezeigt",
 	"sidebar": "Seitenleiste",
 	"Sign in": "Anmelden",
 	"Sign Out": "Abmelden",
 	"Sign up": "Registrieren",
 	"Signing in": "Anmeldung",
-	"Source": "Quellen",
+	"Source": "Quelle",
 	"Speech recognition error: {{error}}": "Spracherkennungsfehler: {{error}}",
 	"Speech-to-Text Engine": "Sprache-zu-Text-Engine",
-	"Stop Sequence": "Stop Sequence",
-	"STT Model": "",
+	"Stop Sequence": "Stop-Sequenz",
+	"STT Model": "STT-Modell",
 	"STT Settings": "STT-Einstellungen",
 	"Submit": "Senden",
-	"Subtitle (e.g. about the Roman Empire)": "Untertitel (z.B. über das Römische Reich)",
+	"Subtitle (e.g. about the Roman Empire)": "Untertitel (z. B. über das Römische Reich)",
 	"Success": "Erfolg",
 	"Successfully updated.": "Erfolgreich aktualisiert.",
 	"Suggested": "Vorgeschlagen",
 	"System": "System",
 	"System Prompt": "System-Prompt",
 	"Tags": "Tags",
-	"Tap to interrupt": "",
-	"Tavily API Key": "",
+	"Tap to interrupt": "Zum Unterbrechen tippen",
+	"Tavily API Key": "Tavily-API-Schlüssel",
 	"Tell us more:": "Erzähl uns mehr",
 	"Temperature": "Temperatur",
 	"Template": "Vorlage",
 	"Text Completion": "Textvervollständigung",
 	"Text-to-Speech Engine": "Text-zu-Sprache-Engine",
 	"Tfs Z": "Tfs Z",
-	"Thanks for your feedback!": "Danke für dein Feedback",
-	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Der Score sollte ein Wert zwischen 0,0 (0 %) und 1,0 (100 %) sein.",
+	"Thanks for your feedback!": "Danke für Ihr Feedback!",
+	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "Die Punktzahl sollte ein Wert zwischen 0,0 (0 %) und 1,0 (100 %) sein.",
 	"Theme": "Design",
-	"Thinking...": "",
-	"This action cannot be undone. Do you wish to continue?": "",
-	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dadurch werden deine wertvollen Unterhaltungen sicher in der Backend-Datenbank gespeichert. Vielen Dank!",
-	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
+	"Thinking...": "Denke nach...",
+	"This action cannot be undone. Do you wish to continue?": "Diese Aktion kann nicht rückgängig gemacht werden. Möchten Sie fortfahren?",
+	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Dies stellt sicher, dass Ihre wertvollen Unterhaltungen sicher in Ihrer Backend-Datenbank gespeichert werden. Vielen Dank!",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dies ist eine experimentelle Funktion, sie funktioniert möglicherweise nicht wie erwartet und kann jederzeit geändert werden.",
 	"This setting does not sync across browsers or devices.": "Diese Einstellung wird nicht zwischen Browsern oder Geräten synchronisiert.",
-	"This will delete": "",
-	"Thorough explanation": "Genaue Erklärung",
-	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tipp: Aktualisiere mehrere Variablen nacheinander, indem du nach jeder Aktualisierung die Tabulatortaste im Chat-Eingabefeld drückst.",
+	"This will delete": "Dies löscht",
+	"Thorough explanation": "Ausführliche Erklärung",
+	"Tika": "",
+	"Tika Server URL required.": "",
+	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tipp: Aktualisieren Sie mehrere Variablenfelder nacheinander, indem Sie nach jedem Ersetzen die Tabulatortaste im Eingabefeld der Unterhaltung drücken.",
 	"Title": "Titel",
-	"Title (e.g. Tell me a fun fact)": "Titel (z.B. Erzähle mir eine lustige Tatsache",
-	"Title Auto-Generation": "Automatische Titelgenerierung",
+	"Title (e.g. Tell me a fun fact)": "Titel (z. B. Erzähl mir einen lustigen Fakt)",
+	"Title Auto-Generation": "Automatische Titelerstellung",
 	"Title cannot be an empty string.": "Titel darf nicht leer sein.",
-	"Title Generation Prompt": "Prompt für Titelgenerierung",
+	"Title Generation Prompt": "Titelerstellung-Prompt",
 	"to": "für",
-	"To access the available model names for downloading,": "Um auf die verfügbaren Modellnamen zum Herunterladen zuzugreifen,",
-	"To access the GGUF models available for downloading,": "Um auf die verfügbaren GGUF Modelle zum Herunterladen zuzugreifen",
-	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
-	"To add documents here, upload them to the \"Documents\" workspace first.": "",
-	"to chat input.": "to chat input.",
-	"To select filters here, add them to the \"Functions\" workspace first.": "",
-	"To select toolkits here, add them to the \"Tools\" workspace first.": "",
+	"To access the available model names for downloading,": "Um auf die verfügbaren Modellnamen zuzugreifen,",
+	"To access the GGUF models available for downloading,": "Um auf die verfügbaren GGUF-Modelle zuzugreifen,",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Um auf das WebUI zugreifen zu könnrn, wenden Sie sich bitte an einen Administrator. Administratoren können den Benutzerstatus über das Admin-Panel verwalten.",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "Um Dokumente hinzuzufügen, laden Sie sie zuerst im Arbeitsbereich „Dokumente“ hoch.",
+	"to chat input.": "zum Eingabefeld der Unterhaltung.",
+	"To select filters here, add them to the \"Functions\" workspace first.": "Um Filter auszuwählen, fügen Sie diese zuerst dem Arbeitsbereich „Funktionen“ hinzu.",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "Um Toolkits auszuwählen, fügen Sie sie zuerst zum Arbeitsbereich „Werkzeuge“ hinzu.",
 	"Today": "Heute",
 	"Toggle settings": "Einstellungen umschalten",
 	"Toggle sidebar": "Seitenleiste umschalten",
-	"Tokens To Keep On Context Refresh (num_keep)": "",
-	"Tool created successfully": "",
-	"Tool deleted successfully": "",
-	"Tool imported successfully": "",
-	"Tool updated successfully": "",
-	"Tools": "",
+	"Tokens To Keep On Context Refresh (num_keep)": "Beizubehaltende Tokens bei Kontextaktualisierung (num_keep)",
+	"Tool created successfully": "Werkzeug erfolgreich erstellt",
+	"Tool deleted successfully": "Werkzeug erfolgreich gelöscht",
+	"Tool imported successfully": "Werkzeug erfolgreich importiert",
+	"Tool updated successfully": "Werkzeug erfolgreich aktualisiert",
+	"Tools": "Werkzeuge",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "Probleme beim Zugriff auf Ollama?",
-	"TTS Model": "",
+	"TTS Model": "TTS-Modell",
 	"TTS Settings": "TTS-Einstellungen",
-	"TTS Voice": "",
+	"TTS Voice": "TTS-Stimme",
 	"Type": "Art",
 	"Type Hugging Face Resolve (Download) URL": "Gib die Hugging Face Resolve (Download) URL ein",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ups! Es gab ein Problem bei der Verbindung mit {{provider}}.",
-	"UI": "",
-	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
-	"Update": "",
-	"Update and Copy Link": "Erneuern und kopieren",
+	"UI": "Oberfläche",
+	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Unbekannter Dateityp '{{file_type}}'. Der Datei-Upload wird trotzdem fortgesetzt.",
+	"Unpin": "",
+	"Update": "Aktualisieren",
+	"Update and Copy Link": "Aktualisieren und Link kopieren",
 	"Update password": "Passwort aktualisieren",
-	"Updated at": "",
-	"Upload": "",
-	"Upload a GGUF model": "GGUF Model hochladen",
-	"Upload Files": "Dateien hochladen",
-	"Upload Pipeline": "",
-	"Upload Progress": "Upload Progress",
-	"URL Mode": "URL Modus",
-	"Use '#' in the prompt input to load and select your documents.": "Verwende '#' in der Prompt-Eingabe, um deine Dokumente zu laden und auszuwählen.",
+	"Updated at": "Aktualisiert am",
+	"Upload": "Hochladen",
+	"Upload a GGUF model": "GGUF-Model hochladen",
+	"Upload Files": "Datei(en) hochladen",
+	"Upload Pipeline": "Pipeline hochladen",
+	"Upload Progress": "Hochladefortschritt",
+	"URL Mode": "URL-Modus",
+	"Use '#' in the prompt input to load and select your documents.": "Verwenden Sie '#' in der Eingabeaufforderung, um Ihre Dokumente zu laden und auszuwählen.",
 	"Use Gravatar": "Gravatar verwenden",
 	"Use Initials": "Initialen verwenden",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "Benutzer",
-	"User location successfully retrieved.": "",
+	"User location successfully retrieved.": "Benutzerstandort erfolgreich ermittelt.",
 	"User Permissions": "Benutzerberechtigungen",
 	"Users": "Benutzer",
-	"Utilize": "Nutze die",
+	"Utilize": "Verwende",
 	"Valid time units:": "Gültige Zeiteinheiten:",
-	"Valves": "",
-	"Valves updated": "",
-	"Valves updated successfully": "",
+	"Valves": "Valves",
+	"Valves updated": "Valves aktualisiert",
+	"Valves updated successfully": "Valves erfolgreich aktualisiert",
 	"variable": "Variable",
 	"variable to have them replaced with clipboard content.": "Variable, um den Inhalt der Zwischenablage beim Nutzen des Prompts zu ersetzen.",
 	"Version": "Version",
-	"Voice": "",
+	"Voice": "Stimme",
 	"Warning": "Warnung",
-	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warnung: Wenn du dein Einbettungsmodell aktualisierst oder änderst, musst du alle Dokumente erneut importieren.",
+	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Warnung: Wenn Sie das Einbettungsmodell aktualisieren oder ändern, müssen Sie alle Dokumente erneut importieren.",
 	"Web": "Web",
-	"Web API": "",
+	"Web API": "Web-API",
 	"Web Loader Settings": "Web Loader Einstellungen",
 	"Web Params": "Web Parameter",
 	"Web Search": "Websuche",
-	"Web Search Engine": "Web-Suchmaschine",
+	"Web Search Engine": "Suchmaschine",
 	"Webhook URL": "Webhook URL",
 	"WebUI Settings": "WebUI-Einstellungen",
 	"WebUI will make requests to": "Wenn aktiviert sendet WebUI externe Anfragen an",
-	"What’s New in": "Was gibt's Neues in",
-	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Wenn die Historie ausgeschaltet ist, werden neue Chats nicht in deiner Historie auf deine Geräte angezeigt.",
-	"Whisper (Local)": "",
-	"Widescreen Mode": "Widescreen Modus",
+	"What’s New in": "Neuigkeiten von",
+	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Wenn der Verlauf deaktiviert ist, werden neue Unterhaltungen in diesem Browser nicht im Verlauf Ihrer anderen Geräte erscheinen.",
+	"Whisper (Local)": "Whisper (lokal)",
+	"Widescreen Mode": "Breitbildmodus",
 	"Workspace": "Arbeitsbereich",
-	"Write a prompt suggestion (e.g. Who are you?)": "Gebe einen Prompt-Vorschlag ein (z.B. Wer bist du?)",
+	"Write a prompt suggestion (e.g. Who are you?)": "Schreiben Sie einen Promptvorschlag (z. B. Wer sind Sie?)",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Schreibe eine kurze Zusammenfassung in 50 Wörtern, die [Thema oder Schlüsselwort] zusammenfasst.",
 	"Yesterday": "Gestern",
-	"You": "Du",
-	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Du kannst deine Interaktionen mit LLMs personalisieren, indem du Erinnerungen durch den 'Verwalten'-Button unten hinzufügst, um sie hilfreicher und auf dich zugeschnitten zu machen.",
-	"You cannot clone a base model": "Sie können ein Basismodell nicht klonen",
+	"You": "Sie",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Personalisieren Sie Interaktionen mit LLMs, indem Sie über die Schaltfläche \"Verwalten\" Erinnerungen hinzufügen.",
+	"You cannot clone a base model": "Sie können Basismodelle nicht klonen",
 	"You have no archived conversations.": "Du hast keine archivierten Unterhaltungen.",
-	"You have shared this chat": "Du hast diesen Chat",
+	"You have shared this chat": "Sie haben diese Unterhaltung geteilt",
 	"You're a helpful assistant.": "Du bist ein hilfreicher Assistent.",
-	"You're now logged in.": "Du bist nun eingeloggt.",
-	"Your account status is currently pending activation.": "",
+	"You're now logged in.": "Sie sind jetzt eingeloggt.",
+	"Your account status is currently pending activation.": "Ihr Kontostatus ist derzeit ausstehend und wartet auf Aktivierung.",
 	"Youtube": "YouTube",
 	"Youtube Loader Settings": "YouTube-Ladeeinstellungen"
 }

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

@@ -126,6 +126,7 @@
 	"Connections": "Connections",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Content",
+	"Content Extraction": "",
 	"Context Length": "Context Length",
 	"Continue Response": "",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "Enable New Bark Ups",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "",
 	"Enter {{role}} message here": "Enter {{role}} bork here",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Enter stop bark",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Enter Top Wow",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Enter URL (e.g. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -409,6 +412,7 @@
 	"Open": "Open",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Open new bark",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}",
 	"Personalization": "Personalization",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -575,6 +581,8 @@
 	"This setting does not sync across browsers or devices.": "This setting does not sync across browsers or devices. Very not sync.",
 	"This will delete": "",
 	"Thorough explanation": "",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement. Much tip!",
 	"Title": "Title very title",
 	"Title (e.g. Tell me a fun fact)": "",
@@ -609,6 +617,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! There was an issue connecting to {{provider}}. Much uh-oh!",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "",
 	"Update password": "Update password much change",

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

@@ -126,6 +126,7 @@
 	"Connections": "",
 	"Contact Admin for WebUI Access": "",
 	"Content": "",
+	"Content Extraction": "",
 	"Context Length": "",
 	"Continue Response": "",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "",
 	"Enter {{role}} message here": "",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -409,6 +412,7 @@
 	"Open": "",
 	"Open AI (Dall-E)": "",
 	"Open new chat": "",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "",
 	"OpenAI API": "",
 	"OpenAI API Config": "",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "",
 	"Personalization": "",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "",
 	"This will delete": "",
 	"Thorough explanation": "",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "",
 	"Title": "",
 	"Title (e.g. Tell me a fun fact)": "",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "",
 	"Update password": "",

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

@@ -126,6 +126,7 @@
 	"Connections": "",
 	"Contact Admin for WebUI Access": "",
 	"Content": "",
+	"Content Extraction": "",
 	"Context Length": "",
 	"Continue Response": "",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "",
 	"Enter {{role}} message here": "",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -409,6 +412,7 @@
 	"Open": "",
 	"Open AI (Dall-E)": "",
 	"Open new chat": "",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "",
 	"OpenAI API": "",
 	"OpenAI API Config": "",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "",
 	"Personalization": "",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "",
 	"This will delete": "",
 	"Thorough explanation": "",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "",
 	"Title": "",
 	"Title (e.g. Tell me a fun fact)": "",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "",
 	"Update password": "",

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

@@ -126,6 +126,7 @@
 	"Connections": "Conexiones",
 	"Contact Admin for WebUI Access": "Contacta el administrador para obtener acceso al WebUI",
 	"Content": "Contenido",
+	"Content Extraction": "",
 	"Context Length": "Longitud del contexto",
 	"Continue Response": "Continuar Respuesta",
 	"Continue with {{provider}}": "Continuar con {{provider}}",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Habilitar el uso compartido de la comunidad",
 	"Enable New Sign Ups": "Habilitar Nuevos Registros",
 	"Enable Web Search": "Habilitar la búsqueda web",
+	"Engine": "",
 	"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": "Ingrese el mensaje {{role}} aquí",
 	"Enter a detail about yourself for your LLMs to recall": "Ingrese un detalle sobre usted para que sus LLMs recuerden",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Ingrese la clave API de Serpstack",
 	"Enter stop sequence": "Ingrese la secuencia de parada",
 	"Enter Tavily API Key": "Ingrese la clave API de Tavily",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Ingrese el Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ingrese la URL (p.ej., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Ingrese la URL (p.ej., http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Abrir",
 	"Open AI (Dall-E)": "Abrir AI (Dall-E)",
 	"Open new chat": "Abrir nuevo chat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API Config",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Permiso denegado al acceder a la micrófono",
 	"Permission denied when accessing microphone: {{error}}": "Permiso denegado al acceder al micrófono: {{error}}",
 	"Personalization": "Personalización",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Pipeline borrada exitosamente",
 	"Pipeline downloaded successfully": "Pipeline descargada exitosamente",
 	"Pipelines": "Pipelines",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Esta configuración no se sincroniza entre navegadores o dispositivos.",
 	"This will delete": "Esto eliminará",
 	"Thorough explanation": "Explicación exhaustiva",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consejo: Actualice múltiples variables consecutivamente presionando la tecla tab en la entrada del chat después de cada reemplazo.",
 	"Title": "Título",
 	"Title (e.g. Tell me a fun fact)": "Título (por ejemplo, cuéntame una curiosidad)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "¡Uh oh! Hubo un problema al conectarse a {{provider}}.",
 	"UI": "UI",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Tipo de archivo desconocido '{{file_type}}'. Procediendo con la carga del archivo de todos modos.",
+	"Unpin": "",
 	"Update": "Actualizar",
 	"Update and Copy Link": "Actualizar y copiar enlace",
 	"Update password": "Actualizar contraseña",

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

@@ -126,6 +126,7 @@
 	"Connections": "ارتباطات",
 	"Contact Admin for WebUI Access": "",
 	"Content": "محتوا",
+	"Content Extraction": "",
 	"Context Length": "طول زمینه",
 	"Continue Response": "ادامه پاسخ",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "فعالسازی اشتراک انجمن",
 	"Enable New Sign Ups": "فعال کردن ثبت نام\u200cهای جدید",
 	"Enable Web Search": "فعالسازی جستجوی وب",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "اطمینان حاصل کنید که فایل CSV شما شامل چهار ستون در این ترتیب است: نام، ایمیل، رمز عبور، نقش.",
 	"Enter {{role}} message here": "پیام {{role}} را اینجا وارد کنید",
 	"Enter a detail about yourself for your LLMs to recall": "برای ذخیره سازی اطلاعات خود، یک توضیح کوتاه درباره خود را وارد کنید",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "کلید API Serpstack را وارد کنید",
 	"Enter stop sequence": "توالی توقف را وارد کنید",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "مقدار Top K را وارد کنید",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "مقدار URL را وارد کنید (مثال http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "مقدار URL را وارد کنید (مثال http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "باز",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "باز کردن گپ جدید",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API Config",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "هنگام دسترسی به میکروفون، اجازه داده نشد: {{error}}",
 	"Personalization": "شخصی سازی",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "خط لوله",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "این تنظیم در مرورگرها یا دستگاه\u200cها همگام\u200cسازی نمی\u200cشود.",
 	"This will delete": "",
 	"Thorough explanation": "توضیح کامل",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "با فشردن کلید Tab در ورودی چت پس از هر بار تعویض، چندین متغیر را به صورت متوالی به روزرسانی کنید.",
 	"Title": "عنوان",
 	"Title (e.g. Tell me a fun fact)": "عنوان (برای مثال: به من بگوید چیزی که دوست دارید)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "اوه اوه! مشکلی در اتصال به {{provider}} وجود داشت.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "به روزرسانی و کپی لینک",
 	"Update password": "به روزرسانی رمزعبور",

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

@@ -126,6 +126,7 @@
 	"Connections": "Yhteydet",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Sisältö",
+	"Content Extraction": "",
 	"Context Length": "Kontekstin pituus",
 	"Continue Response": "Jatka vastausta",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Ota yhteisön jakaminen käyttöön",
 	"Enable New Sign Ups": "Salli uudet rekisteröitymiset",
 	"Enable Web Search": "Ota verkkohaku käyttöön",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Varmista, että CSV-tiedostossasi on 4 saraketta seuraavassa järjestyksessä: Nimi, Sähköposti, Salasana, Rooli.",
 	"Enter {{role}} message here": "Kirjoita {{role}} viesti tähän",
 	"Enter a detail about yourself for your LLMs to recall": "Kirjoita tieto itseestäsi LLM:ien muistamiseksi",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Anna Serpstack API -avain",
 	"Enter stop sequence": "Syötä lopetussekvenssi",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Syötä Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Syötä URL (esim. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Syötä URL (esim. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Avaa",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Avaa uusi keskustelu",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API -asetukset",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Mikrofonin käyttöoikeus evätty: {{error}}",
 	"Personalization": "Henkilökohtaisuus",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Putkistot",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Tämä asetus ei synkronoidu selainten tai laitteiden välillä.",
 	"This will delete": "",
 	"Thorough explanation": "Perusteellinen selitys",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Vinkki: Päivitä useita muuttujapaikkoja peräkkäin painamalla tabulaattoria keskustelusyötteessä jokaisen korvauksen jälkeen.",
 	"Title": "Otsikko",
 	"Title (e.g. Tell me a fun fact)": "Otsikko (esim. Kerro hauska fakta)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Voi ei! Yhteysongelma {{provider}}:n kanssa.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Päivitä ja kopioi linkki",
 	"Update password": "Päivitä salasana",

+ 8 - 1
src/lib/i18n/locales/fr-CA/translation.json

@@ -126,6 +126,7 @@
 	"Connections": "Connexions",
 	"Contact Admin for WebUI Access": "Contacter l'administrateur pour l'accès à l'interface Web",
 	"Content": "Contenu",
+	"Content Extraction": "",
 	"Context Length": "Longueur du contexte",
 	"Continue Response": "Continuer la réponse",
 	"Continue with {{provider}}": "Continuer avec {{provider}}",
@@ -211,7 +212,8 @@
 	"Enable Chat History": "Activer l'historique de conversation",
 	"Enable Community Sharing": "Activer le partage communautaire",
 	"Enable New Sign Ups": "Activer les nouvelles inscriptions",
-	"Enable Web Search": "Activer la recherche web",
+	"Enable Web Search": "Activer la recherche sur le Web",
+	"Engine": "Moteur",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Vérifiez que votre fichier CSV comprenne les 4 colonnes dans cet ordre : Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Entrez le message {{role}} ici",
 	"Enter a detail about yourself for your LLMs to recall": "Saisissez un détail sur vous-même que vos LLMs pourront se rappeler",
@@ -409,6 +411,7 @@
 	"Open": "Ouvrez",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Ouvrir une nouvelle discussion",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Configuration de l'API OpenAI",
@@ -424,6 +427,8 @@
 	"Permission denied when accessing microphone": "Autorisation refusée lors de l'accès au micro",
 	"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
 	"Personalization": "Personnalisation",
+	"Pin": "Épingler",
+	"Pinned": "Épinglé",
 	"Pipeline deleted successfully": "Le pipeline a été supprimé avec succès",
 	"Pipeline downloaded successfully": "Le pipeline a été téléchargé avec succès",
 	"Pipelines": "Pipelines",
@@ -574,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Ce paramètre ne se synchronise pas entre les navigateurs ou les appareils.",
 	"This will delete": "Cela supprimera",
 	"Thorough explanation": "Explication approfondie",
+	"Tika": "Tika",
+	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Conseil : mettez à jour plusieurs emplacements de variables consécutivement en appuyant sur la touche Tab dans l’entrée de chat après chaque remplacement.",
 	"Title": "Titre",
 	"Title (e.g. Tell me a fun fact)": "Titre (par ex. raconte-moi un fait amusant)",

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

@@ -126,6 +126,7 @@
 	"Connections": "Connexions",
 	"Contact Admin for WebUI Access": "Contacter l'administrateur pour l'accès à l'interface Web",
 	"Content": "Contenu",
+	"Content Extraction": "",
 	"Context Length": "Longueur du contexte",
 	"Continue Response": "Continuer la réponse",
 	"Continue with {{provider}}": "Continuer avec {{provider}}",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Activer le partage communautaire",
 	"Enable New Sign Ups": "Activer les nouvelles inscriptions",
 	"Enable Web Search": "Activer la recherche web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Vérifiez que votre fichier CSV comprenne les 4 colonnes dans cet ordre : Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Entrez le message {{role}} ici",
 	"Enter a detail about yourself for your LLMs to recall": "Saisissez un détail sur vous-même que vos LLMs pourront se rappeler",
@@ -409,6 +411,7 @@
 	"Open": "Ouvrez",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Ouvrir une nouvelle discussion",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "La version Open WebUI (v{{OPEN_WEBUI_VERSION}}) est inférieure à la version requise (v{{REQUIRED_VERSION}})",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Configuration de l'API OpenAI",
@@ -424,6 +427,8 @@
 	"Permission denied when accessing microphone": "Autorisation refusée lors de l'accès au micro",
 	"Permission denied when accessing microphone: {{error}}": "Permission refusée lors de l'accès au microphone : {{error}}",
 	"Personalization": "Personnalisation",
+	"Pin": "Épingler",
+	"Pinned": "Épinglé",
 	"Pipeline deleted successfully": "Le pipeline a été supprimé avec succès",
 	"Pipeline downloaded successfully": "Le pipeline a été téléchargé avec succès",
 	"Pipelines": "Pipelines",
@@ -572,6 +577,8 @@
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Cela garantit que vos conversations précieuses soient sauvegardées en toute sécurité dans votre base de données backend. Merci !",
 	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Il s'agit d'une fonctionnalité expérimentale, elle peut ne pas fonctionner comme prévu et est sujette à modification à tout moment.",
 	"This setting does not sync across browsers or devices.": "Ce paramètre ne se synchronise pas entre les navigateurs ou les appareils.",
+	"Tika": "Tika",
+	"Tika Server URL required.": "URL du serveur Tika requise.",
 	"This will delete": "Cela supprimera",
 	"Thorough explanation": "Explication approfondie",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Conseil : mettez à jour plusieurs emplacements de variables consécutivement en appuyant sur la touche Tab dans l’entrée de chat après chaque remplacement.",

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

@@ -126,6 +126,7 @@
 	"Connections": "חיבורים",
 	"Contact Admin for WebUI Access": "",
 	"Content": "תוכן",
+	"Content Extraction": "",
 	"Context Length": "אורך הקשר",
 	"Continue Response": "המשך תגובה",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "הפיכת שיתוף קהילה לזמין",
 	"Enable New Sign Ups": "אפשר הרשמות חדשות",
 	"Enable Web Search": "הפיכת חיפוש באינטרנט לזמין",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ודא שקובץ ה-CSV שלך כולל 4 עמודות בסדר הבא: שם, דוא\"ל, סיסמה, תפקיד.",
 	"Enter {{role}} message here": "הזן הודעת {{role}} כאן",
 	"Enter a detail about yourself for your LLMs to recall": "הזן פרטים על עצמך כדי שLLMs יזכור",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "הזן מפתח API של Serpstack",
 	"Enter stop sequence": "הזן רצף עצירה",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "הזן Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "הזן כתובת URL (למשל http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "הזן כתובת URL (למשל http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "פתח",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "פתח צ'אט חדש",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API של OpenAI",
 	"OpenAI API Config": "תצורת API של OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "ההרשאה נדחתה בעת גישה למיקרופון: {{error}}",
 	"Personalization": "תאור",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "צינורות",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "הגדרה זו אינה מסתנכרנת בין דפדפנים או מכשירים.",
 	"This will delete": "",
 	"Thorough explanation": "תיאור מפורט",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "טיפ: עדכן חריצים משתנים מרובים ברציפות על-ידי לחיצה על מקש Tab בקלט הצ'אט לאחר כל החלפה.",
 	"Title": "שם",
 	"Title (e.g. Tell me a fun fact)": "שם (לדוגמה: תרגום)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "או-הו! אירעה בעיה בהתחברות ל- {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "עדכן ושכפל קישור",
 	"Update password": "עדכן סיסמה",

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

@@ -126,6 +126,7 @@
 	"Connections": "सम्बन्ध",
 	"Contact Admin for WebUI Access": "",
 	"Content": "सामग्री",
+	"Content Extraction": "",
 	"Context Length": "प्रसंग की लंबाई",
 	"Continue Response": "प्रतिक्रिया जारी रखें",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "समुदाय साझाकरण सक्षम करें",
 	"Enable New Sign Ups": "नए साइन अप सक्रिय करें",
 	"Enable Web Search": "वेब खोज सक्षम करें",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "सुनिश्चित करें कि आपकी CSV फ़ाइल में इस क्रम में 4 कॉलम शामिल हैं: नाम, ईमेल, पासवर्ड, भूमिका।",
 	"Enter {{role}} message here": "यहां {{role}} संदेश दर्ज करें",
 	"Enter a detail about yourself for your LLMs to recall": "अपने एलएलएम को याद करने के लिए अपने बारे में एक विवरण दर्ज करें",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "सर्पस्टैक एपीआई कुंजी दर्ज करें",
 	"Enter stop sequence": "स्टॉप अनुक्रम दर्ज करें",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "शीर्ष K दर्ज करें",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "यूआरएल दर्ज करें (उदा. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "यूआरएल दर्ज करें (उदा. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "खोलें",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "नई चैट खोलें",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API कॉन्फिग",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "माइक्रोफ़ोन तक पहुँचने पर अनुमति अस्वीकृत: {{error}}",
 	"Personalization": "पेरसनलाइज़मेंट",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "पाइपलाइनों",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "यह सेटिंग सभी ब्राउज़रों या डिवाइसों में समन्वयित नहीं होती है",
 	"This will delete": "",
 	"Thorough explanation": "विस्तृत व्याख्या",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "टिप: प्रत्येक प्रतिस्थापन के बाद चैट इनपुट में टैब कुंजी दबाकर लगातार कई वैरिएबल स्लॉट अपडेट करें।",
 	"Title": "शीर्षक",
 	"Title (e.g. Tell me a fun fact)": "शीर्षक (उदा. मुझे एक मज़ेदार तथ्य बताएं)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "उह ओह! {{provider}} से कनेक्ट करने में एक समस्या थी।",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "अपडेट करें और लिंक कॉपी करें",
 	"Update password": "पासवर्ड अपडेट करें",

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

@@ -126,6 +126,7 @@
 	"Connections": "Povezivanja",
 	"Contact Admin for WebUI Access": "Kontaktirajte admina za WebUI pristup",
 	"Content": "Sadržaj",
+	"Content Extraction": "",
 	"Context Length": "Dužina konteksta",
 	"Continue Response": "Nastavi odgovor",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Omogući zajedničko korištenje zajednice",
 	"Enable New Sign Ups": "Omogući nove prijave",
 	"Enable Web Search": "Omogući pretraživanje weba",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Provjerite da vaša CSV datoteka uključuje 4 stupca u ovom redoslijedu: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Unesite {{role}} poruku ovdje",
 	"Enter a detail about yourself for your LLMs to recall": "Unesite pojedinosti o sebi da bi učitali memoriju u LLM",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Unesite Serpstack API ključ",
 	"Enter stop sequence": "Unesite sekvencu zaustavljanja",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Unesite Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Unesite URL (npr. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Unesite URL (npr. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Otvoreno",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Otvorite novi razgovor",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API konfiguracija",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Dopuštenje je odbijeno prilikom pristupa mikrofonu",
 	"Permission denied when accessing microphone: {{error}}": "Pristup mikrofonu odbijen: {{error}}",
 	"Personalization": "Prilagodba",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Cjevovodi",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Ova postavka se ne sinkronizira između preglednika ili uređaja.",
 	"This will delete": "",
 	"Thorough explanation": "Detaljno objašnjenje",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Savjet: Ažurirajte više mjesta za varijable uzastopno pritiskom na tipku tab u unosu razgovora nakon svake zamjene.",
 	"Title": "Naslov",
 	"Title (e.g. Tell me a fun fact)": "Naslov (npr. Reci mi zanimljivost)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Pojavio se problem s povezivanjem na {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Ažuriraj i kopiraj vezu",
 	"Update password": "Ažuriraj lozinku",

+ 17 - 8
src/lib/i18n/locales/id-ID/translation.json

@@ -5,9 +5,9 @@
 	"(e.g. `sh webui.sh --api`)": "(contoh: `sh webui.sh --api`)",
 	"(latest)": "(terbaru)",
 	"{{ models }}": "{{ models }}",
-	"{{ owner }}: You cannot delete a base model": "{{ pemilik }}: Anda tidak dapat menghapus model dasar",
+	"{{ owner }}: You cannot delete a base model": "{{ owner }}: Anda tidak dapat menghapus model dasar",
 	"{{modelName}} is thinking...": "{{modelName}} sedang berpikir...",
-	"{{user}}'s Chats": "Obrolan {{pengguna}}",
+	"{{user}}'s Chats": "Obrolan {{user}}",
 	"{{webUIName}} Backend Required": "{{webUIName}} Diperlukan Backend",
 	"A task model is used when performing tasks such as generating titles for chats and web search queries": "Model tugas digunakan saat melakukan tugas seperti membuat judul untuk obrolan dan kueri penelusuran web",
 	"a user": "seorang pengguna",
@@ -126,6 +126,7 @@
 	"Connections": "Koneksi",
 	"Contact Admin for WebUI Access": "Hubungi Admin untuk Akses WebUI",
 	"Content": "Konten",
+	"Content Extraction": "",
 	"Context Length": "Panjang Konteks",
 	"Continue Response": "Lanjutkan Tanggapan",
 	"Continue with {{provider}}": "Lanjutkan dengan {{penyedia}}",
@@ -171,7 +172,7 @@
 	"Delete tool?": "Hapus alat?",
 	"Delete User": "Menghapus Pengguna",
 	"Deleted {{deleteModelTag}}": "Menghapus {{deleteModelTag}}",
-	"Deleted {{name}}": "Menghapus {{nama}}",
+	"Deleted {{name}}": "Menghapus {{name}}",
 	"Description": "Deskripsi",
 	"Didn't fully follow instructions": "Tidak sepenuhnya mengikuti instruksi",
 	"Discover a function": "Menemukan sebuah fungsi",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Aktifkan Berbagi Komunitas",
 	"Enable New Sign Ups": "Aktifkan Pendaftaran Baru",
 	"Enable Web Search": "Aktifkan Pencarian Web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Pastikan file CSV Anda menyertakan 4 kolom dengan urutan sebagai berikut: Nama, Email, Kata Sandi, Peran.",
 	"Enter {{role}} message here": "Masukkan pesan {{role}} di sini",
 	"Enter a detail about yourself for your LLMs to recall": "Masukkan detail tentang diri Anda untuk diingat oleh LLM Anda",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Masukkan Kunci API Serpstack",
 	"Enter stop sequence": "Masukkan urutan berhenti",
 	"Enter Tavily API Key": "Masukkan Kunci API Tavily",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Masukkan Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Masukkan URL (mis. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Masukkan URL (mis. http://localhost:11434)",
@@ -287,7 +290,7 @@
 	"Google PSE Engine Id": "Id Mesin Google PSE",
 	"h:mm a": "h:mm a",
 	"has no conversations.": "tidak memiliki percakapan.",
-	"Hello, {{name}}": "Halo, {{nama}}",
+	"Hello, {{name}}": "Halo, {{name}}",
 	"Help": "Bantuan",
 	"Hide": "Sembunyikan",
 	"Hide Model": "Sembunyikan Model",
@@ -359,7 +362,7 @@
 	"Model '{{modelTag}}' is already in queue for downloading.": "Model '{{modelTag}}' sudah berada dalam antrean untuk diunduh.",
 	"Model {{modelId}} not found": "Model {{modelId}} tidak ditemukan",
 	"Model {{modelName}} is not vision capable": "Model {{modelName}} tidak dapat dilihat",
-	"Model {{name}} is now {{status}}": "Model {{nama}} sekarang menjadi {{status}}",
+	"Model {{name}} is now {{status}}": "Model {{name}} sekarang menjadi {{status}}",
 	"Model created successfully!": "Model berhasil dibuat!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Jalur sistem berkas model terdeteksi. Nama pendek model diperlukan untuk pembaruan, tidak dapat dilanjutkan.",
 	"Model ID": "ID Model",
@@ -409,6 +412,7 @@
 	"Open": "Buka",
 	"Open AI (Dall-E)": "Buka AI (Dall-E)",
 	"Open new chat": "Buka obrolan baru",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Konfigurasi API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Izin ditolak saat mengakses mikrofon",
 	"Permission denied when accessing microphone: {{error}}": "Izin ditolak saat mengakses mikrofon: {{error}}",
 	"Personalization": "Personalisasi",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Pipeline berhasil dihapus",
 	"Pipeline downloaded successfully": "Saluran pipa berhasil diunduh",
 	"Pipelines": "Saluran pipa",
@@ -487,8 +493,8 @@
 	"Search Query Generation Prompt Length Threshold": "Ambang Batas Panjang Permintaan Pembuatan Kueri Pencarian",
 	"Search Result Count": "Jumlah Hasil Pencarian",
 	"Search Tools": "Alat Pencarian",
-	"Searched {{count}} sites_one": "Mencari {{hitung}} situs_satu",
-	"Searched {{count}} sites_other": "Mencari {{hitung}} situs_lain",
+	"Searched {{count}} sites_one": "Mencari {{count}} situs_satu",
+	"Searched {{count}} sites_other": "Mencari {{count}} situs_lain",
 	"Searching \"{{searchQuery}}\"": "Mencari \"{{searchQuery}}\"",
 	"Searxng Query URL": "URL Kueri Pencarian Searxng",
 	"See readme.md for instructions": "Lihat readme.md untuk instruksi",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Pengaturan ini tidak disinkronkan di seluruh browser atau perangkat.",
 	"This will delete": "Ini akan menghapus",
 	"Thorough explanation": "Penjelasan menyeluruh",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Perbarui beberapa slot variabel secara berurutan dengan menekan tombol tab di input obrolan setelah setiap penggantian.",
 	"Title": "Judul",
 	"Title (e.g. Tell me a fun fact)": "Judul (misalnya, Ceritakan sebuah fakta menarik)",
@@ -604,9 +612,10 @@
 	"TTS Voice": "Suara TTS",
 	"Type": "Ketik",
 	"Type Hugging Face Resolve (Download) URL": "Ketik Hugging Face Resolve (Unduh) URL",
-	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Ada masalah saat menyambung ke {{penyedia}}.",
+	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Ada masalah saat menyambung ke {{provider}}.",
 	"UI": "UI",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Jenis file tidak dikenal '{{file_type}}'. Tetap lanjutkan dengan mengunggah file.",
+	"Unpin": "",
 	"Update": "Memperbarui",
 	"Update and Copy Link": "Perbarui dan Salin Tautan",
 	"Update password": "Perbarui kata sandi",

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

@@ -126,6 +126,7 @@
 	"Connections": "Connessioni",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Contenuto",
+	"Content Extraction": "",
 	"Context Length": "Lunghezza contesto",
 	"Continue Response": "Continua risposta",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Abilita la condivisione della community",
 	"Enable New Sign Ups": "Abilita nuove iscrizioni",
 	"Enable Web Search": "Abilita ricerca Web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assicurati che il tuo file CSV includa 4 colonne in questo ordine: Nome, Email, Password, Ruolo.",
 	"Enter {{role}} message here": "Inserisci il messaggio per {{role}} qui",
 	"Enter a detail about yourself for your LLMs to recall": "Inserisci un dettaglio su di te per che i LLM possano ricordare",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Inserisci la chiave API Serpstack",
 	"Enter stop sequence": "Inserisci la sequenza di arresto",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Inserisci Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Inserisci URL (ad esempio http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Inserisci URL (ad esempio http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Apri",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Apri nuova chat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Configurazione API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Autorizzazione negata durante l'accesso al microfono: {{error}}",
 	"Personalization": "Personalizzazione",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Condutture",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Questa impostazione non si sincronizza tra browser o dispositivi.",
 	"This will delete": "",
 	"Thorough explanation": "Spiegazione dettagliata",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Suggerimento: aggiorna più slot di variabili consecutivamente premendo il tasto tab nell'input della chat dopo ogni sostituzione.",
 	"Title": "Titolo",
 	"Title (e.g. Tell me a fun fact)": "Titolo (ad esempio Dimmi un fatto divertente)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Si è verificato un problema durante la connessione a {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Aggiorna e copia link",
 	"Update password": "Aggiorna password",

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

@@ -126,6 +126,7 @@
 	"Connections": "接続",
 	"Contact Admin for WebUI Access": "",
 	"Content": "コンテンツ",
+	"Content Extraction": "",
 	"Context Length": "コンテキストの長さ",
 	"Continue Response": "続きの応答",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "コミュニティ共有の有効化",
 	"Enable New Sign Ups": "新規登録を有効化",
 	"Enable Web Search": "Web 検索を有効にする",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSVファイルに4つの列が含まれていることを確認してください: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "{{role}} メッセージをここに入力してください",
 	"Enter a detail about yourself for your LLMs to recall": "LLM が記憶するために、自分についての詳細を入力してください",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Serpstack APIキーの入力",
 	"Enter stop sequence": "ストップシーケンスを入力してください",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "トップ K を入力してください",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL を入力してください (例: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL を入力してください (例: http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "開く",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "新しいチャットを開く",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API 設定",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "マイクへのアクセス時に権限が拒否されました: {{error}}",
 	"Personalization": "個人化",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "パイプライン",
@@ -572,6 +578,8 @@
 	"This setting does not sync across browsers or devices.": "この設定は、ブラウザやデバイス間で同期されません。",
 	"This will delete": "",
 	"Thorough explanation": "詳細な説明",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ヒント: 各置換後にチャット入力で Tab キーを押すことで、複数の変数スロットを連続して更新できます。",
 	"Title": "タイトル",
 	"Title (e.g. Tell me a fun fact)": "タイトル (例: 楽しい事を教えて)",
@@ -606,6 +614,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "おっと! {{provider}} への接続に問題が発生しました。",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "リンクの更新とコピー",
 	"Update password": "パスワードを更新",

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

@@ -126,6 +126,7 @@
 	"Connections": "კავშირები",
 	"Contact Admin for WebUI Access": "",
 	"Content": "კონტენტი",
+	"Content Extraction": "",
 	"Context Length": "კონტექსტის სიგრძე",
 	"Continue Response": "პასუხის გაგრძელება",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "საზოგადოების გაზიარების ჩართვა",
 	"Enable New Sign Ups": "ახალი რეგისტრაციების ჩართვა",
 	"Enable Web Search": "ვებ ძიების ჩართვა",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "გთხოვთ, უზრუნველყოთ, რომთქვევის CSV-ფაილი შეიცავს 4 ველი, ჩაწერილი ორივე ველი უდრის პირველი ველით.",
 	"Enter {{role}} message here": "შეიყვანე {{role}} შეტყობინება აქ",
 	"Enter a detail about yourself for your LLMs to recall": "შეიყვანე დეტალი ჩემთათვის, რომ ჩვენი LLMs-ს შეიძლოს აღაქვს",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "შეიყვანეთ Serpstack API Key",
 	"Enter stop sequence": "შეიყვანეთ ტოპ თანმიმდევრობა",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "შეიყვანეთ Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "შეიყვანეთ მისამართი (მაგალითად http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "შეიყვანეთ მისამართი (მაგალითად http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "ღია",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "ახალი მიმოწერის გახსნა",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API პარამეტრები",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "ნებართვა უარყოფილია მიკროფონზე წვდომისას: {{error}}",
 	"Personalization": "პერსონალიზაცია",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "მილსადენები",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "ეს პარამეტრი არ სინქრონიზდება ბრაუზერებსა და მოწყობილობებში",
 	"This will delete": "",
 	"Thorough explanation": "ვრცლად აღწერა",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "რჩევა: განაახლეთ რამდენიმე ცვლადი სლოტი თანმიმდევრულად, ყოველი ჩანაცვლების შემდეგ ჩატის ღილაკზე დაჭერით.",
 	"Title": "სათაური",
 	"Title (e.g. Tell me a fun fact)": "სათაური (მაგ. გაიხსნე რაღაც ხარისხი)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "{{provider}}-თან დაკავშირების პრობლემა წარმოიშვა.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "განახლება და ბმულის კოპირება",
 	"Update password": "პაროლის განახლება",

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

@@ -126,6 +126,7 @@
 	"Connections": "연결",
 	"Contact Admin for WebUI Access": "WebUI 접속을 위해서는 관리자에게 연락 필요",
 	"Content": "내용",
+	"Content Extraction": "",
 	"Context Length": "내용 길이",
 	"Continue Response": "대화 계속",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "커뮤니티 공유 활성화",
 	"Enable New Sign Ups": "새 회원가입 활성화",
 	"Enable Web Search": "웹 검색 활성화",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV 파일에 이름, 이메일, 비밀번호, 역할 4개의 컬럼이 순서대로 포함되어 있는지 확인하세요.",
 	"Enter {{role}} message here": "여기에 {{role}} 메시지 입력",
 	"Enter a detail about yourself for your LLMs to recall": "자신에 대한 세부사항을 입력하여 LLM들이 기억할 수 있도록 하세요.",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Serpstack API 키 입력",
 	"Enter stop sequence": "중지 시퀀스 입력",
 	"Enter Tavily API Key": "Tavily API 키 입력",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Top K 입력",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL 입력(예: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL 입력(예: http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "열기",
 	"Open AI (Dall-E)": "OpenAI(Dall-E)",
 	"Open new chat": "새 채팅 열기",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API 설정",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "마이크 액세스가 거부되었습니다.",
 	"Permission denied when accessing microphone: {{error}}": "마이크 액세스가 거부되었습니다: {{error}}",
 	"Personalization": "개인화",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "파이프라인",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "이 설정은 브라우저 또는 장치 간에 동기화되지 않습니다.",
 	"This will delete": "이것은 다음을 삭제합니다.",
 	"Thorough explanation": "완전한 설명",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "팁: 각 대체 후 채팅 입력에서 탭 키를 눌러 여러 개의 변수 슬롯을 연속적으로 업데이트하세요.",
 	"Title": "제목",
 	"Title (e.g. Tell me a fun fact)": "제목 (예: 재미있는 사실을 알려주세요)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "앗! {{provider}}에 연결하는 데 문제가 있었습니다.",
 	"UI": "UI",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "업데이트",
 	"Update and Copy Link": "링크 업데이트 및 복사",
 	"Update password": "비밀번호 업데이트",

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

@@ -126,6 +126,7 @@
 	"Connections": "Ryšiai",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Turinys",
+	"Content Extraction": "",
 	"Context Length": "Konteksto ilgis",
 	"Continue Response": "Tęsti atsakymą",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "Aktyvuoti naujas registracijas",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Įsitikinkite, kad CSV failas turi 4 kolonas šiuo eiliškumu: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Įveskite {{role}} žinutę čia",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "Įveskite pabaigos sekvenciją",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Įveskite Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Įveskite nuorodą (pvz. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Įveskite nuorododą (pvz. http://localhost:11434",
@@ -409,6 +412,7 @@
 	"Open": "Atverti",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Atverti naują pokalbį",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "Open AI API nustatymai",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Leidimas naudoti mikrofoną atmestas: {{error}}",
 	"Personalization": "",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -575,6 +581,8 @@
 	"This setting does not sync across browsers or devices.": "Šis parametras nesisinchronizuoja su skirtingomis naršyklėmis ir įrankiais.",
 	"This will delete": "",
 	"Thorough explanation": "Platus paaiškinimas",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Jei norite pakeisti keletą kintamųjų vieną po kitos, spauskite Tab",
 	"Title": "Pavadinimas",
 	"Title (e.g. Tell me a fun fact)": "Pavadinimas",
@@ -609,6 +617,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "O ne! Prisijungiant prie {{provider}} kilo problema.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Atnaujinti ir kopijuoti nuorodą",
 	"Update password": "Atnaujinti slaptažodį",

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

@@ -126,6 +126,7 @@
 	"Connections": "Tilkoblinger",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Innhold",
+	"Content Extraction": "",
 	"Context Length": "Kontekstlengde",
 	"Continue Response": "Fortsett svar",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Aktiver deling i fellesskap",
 	"Enable New Sign Ups": "Aktiver nye registreringer",
 	"Enable Web Search": "Aktiver websøk",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Sørg for at CSV-filen din inkluderer 4 kolonner i denne rekkefølgen: Navn, E-post, Passord, Rolle.",
 	"Enter {{role}} message here": "Skriv inn {{role}} melding her",
 	"Enter a detail about yourself for your LLMs to recall": "Skriv inn en detalj om deg selv som LLM-ene dine kan huske",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Skriv inn Serpstack API-nøkkel",
 	"Enter stop sequence": "Skriv inn stoppsekvens",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Skriv inn Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Skriv inn URL (f.eks. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Skriv inn URL (f.eks. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Åpne",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Åpne ny chat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API-konfigurasjon",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Tillatelse nektet ved tilgang til mikrofon: {{error}}",
 	"Personalization": "Personalisering",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Pipelines",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Denne innstillingen synkroniseres ikke mellom nettlesere eller enheter.",
 	"This will delete": "",
 	"Thorough explanation": "Grundig forklaring",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Oppdater flere variabelplasser etter hverandre ved å trykke på tab-tasten i chatinputen etter hver erstatning.",
 	"Title": "Tittel",
 	"Title (e.g. Tell me a fun fact)": "Tittel (f.eks. Fortell meg en morsom fakta)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Oops! Det oppsto et problem med tilkoblingen til {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Oppdater og kopier lenke",
 	"Update password": "Oppdater passord",

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

@@ -126,6 +126,7 @@
 	"Connections": "Verbindingen",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Inhoud",
+	"Content Extraction": "",
 	"Context Length": "Context Lengte",
 	"Continue Response": "Doorgaan met Antwoord",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Delen via de community inschakelen",
 	"Enable New Sign Ups": "Schakel Nieuwe Registraties in",
 	"Enable Web Search": "Zoeken op het web inschakelen",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Zorg ervoor dat uw CSV-bestand de volgende vier kolommen in deze volgorde bevat: Naam, E-mail, Wachtwoord, Rol.",
 	"Enter {{role}} message here": "Voeg {{role}} bericht hier toe",
 	"Enter a detail about yourself for your LLMs to recall": "Voer een detail over jezelf in voor je LLMs om het her te onthouden",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Voer de Serpstack API-sleutel in",
 	"Enter stop sequence": "Zet stop sequentie",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Voeg Top K toe",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Zet URL (Bijv. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Zet URL (Bijv. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Open",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Open nieuwe chat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API Config",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Toestemming geweigerd bij toegang tot microfoon: {{error}}",
 	"Personalization": "Personalisatie",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Pijpleidingen",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Deze instelling wordt niet gesynchroniseerd tussen browsers of apparaten.",
 	"This will delete": "",
 	"Thorough explanation": "Gevorderde uitleg",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tip: Werk meerdere variabele slots achtereenvolgens bij door op de tab-toets te drukken in de chat input na elke vervanging.",
 	"Title": "Titel",
 	"Title (e.g. Tell me a fun fact)": "Titel (bv. Vertel me een leuke gebeurtenis)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Er was een probleem met verbinden met {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Update en Kopieer Link",
 	"Update password": "Wijzig wachtwoord",

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

@@ -126,6 +126,7 @@
 	"Connections": "ਕਨੈਕਸ਼ਨ",
 	"Contact Admin for WebUI Access": "",
 	"Content": "ਸਮੱਗਰੀ",
+	"Content Extraction": "",
 	"Context Length": "ਸੰਦਰਭ ਲੰਬਾਈ",
 	"Continue Response": "ਜਵਾਬ ਜਾਰੀ ਰੱਖੋ",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "ਕਮਿਊਨਿਟੀ ਸ਼ੇਅਰਿੰਗ ਨੂੰ ਸਮਰੱਥ ਕਰੋ",
 	"Enable New Sign Ups": "ਨਵੇਂ ਸਾਈਨ ਅਪ ਯੋਗ ਕਰੋ",
 	"Enable Web Search": "ਵੈੱਬ ਖੋਜ ਨੂੰ ਸਮਰੱਥ ਕਰੋ",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ਸੁਨਿਸ਼ਚਿਤ ਕਰੋ ਕਿ ਤੁਹਾਡੀ CSV ਫਾਈਲ ਵਿੱਚ ਇਸ ਕ੍ਰਮ ਵਿੱਚ 4 ਕਾਲਮ ਹਨ: ਨਾਮ, ਈਮੇਲ, ਪਾਸਵਰਡ, ਭੂਮਿਕਾ।",
 	"Enter {{role}} message here": "{{role}} ਸੁਨੇਹਾ ਇੱਥੇ ਦਰਜ ਕਰੋ",
 	"Enter a detail about yourself for your LLMs to recall": "ਤੁਹਾਡੇ LLMs ਨੂੰ ਸੁਨੇਹਾ ਕਰਨ ਲਈ ਸੁਨੇਹਾ ਇੱਥੇ ਦਰਜ ਕਰੋ",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Serpstack API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ",
 	"Enter stop sequence": "ਰੋਕਣ ਦਾ ਕ੍ਰਮ ਦਰਜ ਕਰੋ",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "ਸਿਖਰ K ਦਰਜ ਕਰੋ",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "ਖੋਲ੍ਹੋ",
 	"Open AI (Dall-E)": "ਓਪਨ ਏਆਈ (ਡਾਲ-ਈ)",
 	"Open new chat": "ਨਵੀਂ ਗੱਲਬਾਤ ਖੋਲ੍ਹੋ",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "ਓਪਨਏਆਈ",
 	"OpenAI API": "ਓਪਨਏਆਈ API",
 	"OpenAI API Config": "ਓਪਨਏਆਈ API ਕਨਫਿਗ",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚਣ ਸਮੇਂ ਆਗਿਆ ਰੱਦ ਕੀਤੀ ਗਈ: {{error}}",
 	"Personalization": "ਪਰਸੋਨਲਿਸ਼ਮ",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "ਪਾਈਪਲਾਈਨਾਂ",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "ਇਹ ਸੈਟਿੰਗ ਬ੍ਰਾਊਜ਼ਰ ਜਾਂ ਡਿਵਾਈਸਾਂ ਵਿੱਚ ਸਿੰਕ ਨਹੀਂ ਹੁੰਦੀ।",
 	"This will delete": "",
 	"Thorough explanation": "ਵਿਸਥਾਰ ਨਾਲ ਵਿਆਖਿਆ",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "ਸਲਾਹ: ਹਰ ਬਦਲਾਅ ਦੇ ਬਾਅਦ ਗੱਲਬਾਤ ਇਨਪੁਟ ਵਿੱਚ ਟੈਬ ਕੀ ਦਬਾ ਕੇ ਲਗਾਤਾਰ ਕਈ ਵੈਰੀਏਬਲ ਸਲਾਟਾਂ ਨੂੰ ਅੱਪਡੇਟ ਕਰੋ।",
 	"Title": "ਸਿਰਲੇਖ",
 	"Title (e.g. Tell me a fun fact)": "ਸਿਰਲੇਖ (ਉਦਾਹਰਣ ਲਈ ਮੈਨੂੰ ਇੱਕ ਮਜ਼ੇਦਾਰ ਤੱਥ ਦੱਸੋ)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "ਓਹੋ! {{provider}} ਨਾਲ ਕਨੈਕਟ ਕਰਨ ਵਿੱਚ ਸਮੱਸਿਆ ਆਈ।",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "ਅੱਪਡੇਟ ਕਰੋ ਅਤੇ ਲਿੰਕ ਕਾਪੀ ਕਰੋ",
 	"Update password": "ਪਾਸਵਰਡ ਅੱਪਡੇਟ ਕਰੋ",

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

@@ -126,6 +126,7 @@
 	"Connections": "Połączenia",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Zawartość",
+	"Content Extraction": "",
 	"Context Length": "Długość kontekstu",
 	"Continue Response": "Kontynuuj odpowiedź",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Włączanie udostępniania społecznościowego",
 	"Enable New Sign Ups": "Włącz nowe rejestracje",
 	"Enable Web Search": "Włączanie wyszukiwania w Internecie",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Upewnij się, że twój plik CSV zawiera 4 kolumny w następującym porządku: Nazwa, Email, Hasło, Rola.",
 	"Enter {{role}} message here": "Wprowadź wiadomość {{role}} tutaj",
 	"Enter a detail about yourself for your LLMs to recall": "Wprowadź szczegóły o sobie, aby LLMs mogli pamiętać",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Wprowadź klucz API Serpstack",
 	"Enter stop sequence": "Wprowadź sekwencję zatrzymania",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Wprowadź Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Wprowadź adres URL (np. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Wprowadź adres URL (np. http://localhost:11434/)",
@@ -409,6 +412,7 @@
 	"Open": "Otwórz",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Otwórz nowy czat",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "Konfiguracja OpenAI API",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Odmowa dostępu do mikrofonu: {{error}}",
 	"Personalization": "Personalizacja",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Rurociągów",
@@ -575,6 +581,8 @@
 	"This setting does not sync across browsers or devices.": "To ustawienie nie synchronizuje się między przeglądarkami ani urządzeniami.",
 	"This will delete": "",
 	"Thorough explanation": "Dokładne wyjaśnienie",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Porada: Aktualizuj wiele zmiennych kolejno, naciskając klawisz tabulatora w polu wprowadzania czatu po każdej zmianie.",
 	"Title": "Tytuł",
 	"Title (e.g. Tell me a fun fact)": "Tytuł (np. Powiedz mi jakiś zabawny fakt)",
@@ -609,6 +617,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "O nie! Wystąpił problem z połączeniem z {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Uaktualnij i skopiuj link",
 	"Update password": "Aktualizacja hasła",

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

@@ -126,6 +126,7 @@
 	"Connections": "Conexões",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Conteúdo",
+	"Content Extraction": "",
 	"Context Length": "Comprimento do Contexto",
 	"Continue Response": "Continuar resposta",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Habilitar o compartilhamento da comunidade",
 	"Enable New Sign Ups": "Ativar Novas Inscrições",
 	"Enable Web Search": "Habilitar a Pesquisa na Web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Garanta que seu arquivo CSV inclua 4 colunas nesta ordem: Nome, E-mail, Senha, Função.",
 	"Enter {{role}} message here": "Digite a mensagem de {{role}} aqui",
 	"Enter a detail about yourself for your LLMs to recall": "Digite um detalhe sobre você para que seus LLMs possam lembrar",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Digite a chave da API Serpstack",
 	"Enter stop sequence": "Digite a sequência de parada",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Digite o Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Digite a URL (por exemplo, http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Abrir",
 	"Open AI (Dall-E)": "OpenAI (Dall-E)",
 	"Open new chat": "Abrir novo bate-papo",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Configuração da API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}",
 	"Personalization": "Personalização",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Pipelines",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Esta configuração não sincroniza entre navegadores ou dispositivos.",
 	"This will delete": "",
 	"Thorough explanation": "Explicação Completa",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada de bate-papo após cada substituição.",
 	"Title": "Título",
 	"Title (e.g. Tell me a fun fact)": "Título (ex.: Dê-me um fatídico fatídico)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Opa! Houve um problema ao conectar-se a {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Atualizar e Copiar Link",
 	"Update password": "Atualizar senha",

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

@@ -126,6 +126,7 @@
 	"Connections": "Conexões",
 	"Contact Admin for WebUI Access": "Contatar Admin para acesso ao WebUI",
 	"Content": "Conteúdo",
+	"Content Extraction": "",
 	"Context Length": "Comprimento do Contexto",
 	"Continue Response": "Continuar resposta",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Active a Partilha da Comunidade",
 	"Enable New Sign Ups": "Ativar Novas Inscrições",
 	"Enable Web Search": "Ativar pesquisa na Web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Confirme que o seu ficheiro CSV inclui 4 colunas nesta ordem: Nome, E-mail, Senha, Função.",
 	"Enter {{role}} message here": "Escreva a mensagem de {{role}} aqui",
 	"Enter a detail about yourself for your LLMs to recall": "Escreva um detalhe sobre você para que os seus LLMs possam lembrar-se",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Escreva a chave da API Serpstack",
 	"Enter stop sequence": "Escreva a sequência de paragem",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Escreva o Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Escreva o URL (por exemplo, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Escreva o URL (por exemplo, http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Abrir",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Abrir nova conversa",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Configuração da API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "A permissão foi negada ao aceder ao microfone",
 	"Permission denied when accessing microphone: {{error}}": "A permissão foi negada ao aceder o microfone: {{error}}",
 	"Personalization": "Personalização",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Condutas",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Esta configuração não sincroniza entre navegadores ou dispositivos.",
 	"This will delete": "",
 	"Thorough explanation": "Explicação Minuciosa",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Dica: Atualize vários slots de variáveis consecutivamente pressionando a tecla Tab na entrada da conversa após cada substituição.",
 	"Title": "Título",
 	"Title (e.g. Tell me a fun fact)": "Título (ex.: Diz-me um facto divertido)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Uh-oh! Houve um problema ao conectar a {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Atualizar e Copiar Link",
 	"Update password": "Atualizar senha",

+ 9 - 0
src/lib/i18n/locales/ru-RU/translation.json

@@ -126,6 +126,7 @@
 	"Connections": "Соединение",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Содержание",
+	"Content Extraction": "",
 	"Context Length": "Длина контексту",
 	"Continue Response": "Продолжить ответ",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Включить общий доступ к сообществу",
 	"Enable New Sign Ups": "Разрешить новые регистрации",
 	"Enable Web Search": "Включить поиск в Интернете",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Убедитесь, что ваш CSV-файл включает в себя 4 столбца в следующем порядке: Имя, Электронная почта, Пароль, Роль.",
 	"Enter {{role}} message here": "Введите сообщение {{role}} здесь",
 	"Enter a detail about yourself for your LLMs to recall": "Введите детали о себе, чтобы LLMs могли запомнить",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Введите ключ API Serpstack",
 	"Enter stop sequence": "Введите последовательность остановки",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Введите Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введите URL-адрес (например, http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Введите URL-адрес (например, http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Открыть",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Открыть новый чат",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "Open AI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Конфигурация API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Отказано в доступе к микрофону: {{error}}",
 	"Personalization": "Персонализация",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Трубопроводов",
@@ -575,6 +581,8 @@
 	"This setting does not sync across browsers or devices.": "Эта настройка не синхронизируется между браузерами или устройствами.",
 	"This will delete": "",
 	"Thorough explanation": "Повнимательнее",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Совет: Обновляйте несколько переменных подряд, нажимая клавишу Tab в поле ввода чата после каждой замены.",
 	"Title": "Заголовок",
 	"Title (e.g. Tell me a fun fact)": "Заголовок (например. Расскажи мне интересную факт)",
@@ -609,6 +617,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Упс! Возникла проблема подключения к {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Обновить и скопировать ссылку",
 	"Update password": "Обновить пароль",

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

@@ -126,6 +126,7 @@
 	"Connections": "Везе",
 	"Contact Admin for WebUI Access": "",
 	"Content": "Садржај",
+	"Content Extraction": "",
 	"Context Length": "Дужина контекста",
 	"Continue Response": "Настави одговор",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Омогући дељење заједнице",
 	"Enable New Sign Ups": "Омогући нове пријаве",
 	"Enable Web Search": "Омогући Wеб претрагу",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Уверите се да ваша CSV датотека укључује 4 колоне у овом редоследу: Име, Е-пошта, Лозинка, Улога.",
 	"Enter {{role}} message here": "Унесите {{role}} поруку овде",
 	"Enter a detail about yourself for your LLMs to recall": "Унесите детаље за себе да ће LLMs преузимати",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Унесите Серпстацк АПИ кључ",
 	"Enter stop sequence": "Унесите секвенцу заустављања",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Унесите Топ К",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Унесите адресу (нпр. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Унесите адресу (нпр. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Отвори",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Покрени ново ћаскање",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "Подешавање OpenAI API-ја",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "Приступ микрофону је одбијен: {{error}}",
 	"Personalization": "Прилагођавање",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Цевоводи",
@@ -574,6 +580,8 @@
 	"This setting does not sync across browsers or devices.": "Ово подешавање се не усклађује преко прегледача или уређаја.",
 	"This will delete": "",
 	"Thorough explanation": "Детаљно објашњење",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Савет: ажурирајте више променљивих слотова узастопно притиском на тастер Таб у уносу ћаскања након сваке замене.",
 	"Title": "Наслов",
 	"Title (e.g. Tell me a fun fact)": "Наслов (нпр. „реци ми занимљивост“)",
@@ -608,6 +616,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Упс! Дошло је до проблема при повезивању са {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Ажурирај и копирај везу",
 	"Update password": "Ажурирај лозинку",

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

@@ -126,6 +126,7 @@
 	"Connections": "Anslutningar",
 	"Contact Admin for WebUI Access": "Kontakta administratören för att få åtkomst till WebUI",
 	"Content": "Innehåll",
+	"Content Extraction": "",
 	"Context Length": "Kontextlängd",
 	"Continue Response": "Fortsätt svar",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Aktivera community-delning",
 	"Enable New Sign Ups": "Aktivera nya registreringar",
 	"Enable Web Search": "Aktivera webbsökning",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Se till att din CSV-fil innehåller fyra kolumner i denna ordning: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Skriv {{role}} meddelande här",
 	"Enter a detail about yourself for your LLMs to recall": "Skriv en detalj om dig själv för att dina LLMs ska komma ihåg",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Ange Serpstack API-nyckel",
 	"Enter stop sequence": "Ange stoppsekvens",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Ange Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Ange URL (t.ex. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Ange URL (t.ex. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Öppna",
 	"Open AI (Dall-E)": "Öppna AI (Dall-E)",
 	"Open new chat": "Öppna ny chatt",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API-konfig",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Nekad behörighet vid åtkomst till mikrofon",
 	"Permission denied when accessing microphone: {{error}}": "Tillstånd nekades vid åtkomst till mikrofon: {{error}}",
 	"Personalization": "Personalisering",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "Rörledningar",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Denna inställning synkroniseras inte mellan webbläsare eller enheter.",
 	"This will delete": "",
 	"Thorough explanation": "Djupare förklaring",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Tips: Uppdatera fler variabler genom att trycka på tabb-tangenten i chattinmatningen efter varje ersättning.",
 	"Title": "Titel",
 	"Title (e.g. Tell me a fun fact)": "Titel (t.ex. Berätta en kuriosa)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Oj då! Det uppstod ett problem med anslutningen till {{provider}}.",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "Uppdatera och kopiera länk",
 	"Update password": "Uppdatera lösenord",

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

@@ -126,6 +126,7 @@
 	"Connections": "",
 	"Contact Admin for WebUI Access": "",
 	"Content": "",
+	"Content Extraction": "",
 	"Context Length": "",
 	"Continue Response": "",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "",
 	"Enable New Sign Ups": "",
 	"Enable Web Search": "",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "",
 	"Enter {{role}} message here": "",
 	"Enter a detail about yourself for your LLMs to recall": "",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "",
 	"Enter stop sequence": "",
 	"Enter Tavily API Key": "",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "",
 	"Enter URL (e.g. http://localhost:11434)": "",
@@ -409,6 +412,7 @@
 	"Open": "",
 	"Open AI (Dall-E)": "",
 	"Open new chat": "",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "",
 	"OpenAI API": "",
 	"OpenAI API Config": "",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "",
 	"Permission denied when accessing microphone: {{error}}": "",
 	"Personalization": "",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "",
 	"This will delete": "",
 	"Thorough explanation": "",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "",
 	"Title": "",
 	"Title (e.g. Tell me a fun fact)": "",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "",
 	"UI": "",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "",
 	"Update and Copy Link": "",
 	"Update password": "",

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

@@ -126,6 +126,7 @@
 	"Connections": "Bağlantılar",
 	"Contact Admin for WebUI Access": "WebUI Erişimi için Yöneticiyle İletişime Geçin",
 	"Content": "İçerik",
+	"Content Extraction": "",
 	"Context Length": "Bağlam Uzunluğu",
 	"Continue Response": "Yanıta Devam Et",
 	"Continue with {{provider}}": "{{provider}} ile devam et",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Topluluk Paylaşımını Etkinleştir",
 	"Enable New Sign Ups": "Yeni Kayıtları Etkinleştir",
 	"Enable Web Search": "Web Aramasını Etkinleştir",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV dosyanızın şu sırayla 4 sütun içerdiğinden emin olun: İsim, E-posta, Şifre, Rol.",
 	"Enter {{role}} message here": "Buraya {{role}} mesajını girin",
 	"Enter a detail about yourself for your LLMs to recall": "LLM'lerinizin hatırlaması için kendiniz hakkında bir bilgi girin",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Serpstack API Anahtarını Girin",
 	"Enter stop sequence": "Durdurma dizisini girin",
 	"Enter Tavily API Key": "Tavily API Anahtarını Girin",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Top K'yı girin",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "URL'yi Girin (örn. http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "URL'yi Girin (e.g. http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Aç",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Yeni sohbet aç",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API Konfigürasyonu",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Mikrofona erişim izni reddedildi",
 	"Permission denied when accessing microphone: {{error}}": "Mikrofona erişim izni reddedildi: {{error}}",
 	"Personalization": "Kişiselleştirme",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Pipeline başarıyla silindi",
 	"Pipeline downloaded successfully": "Pipeline başarıyla güncellendi",
 	"Pipelines": "Pipelinelar",
@@ -573,6 +579,8 @@
 	"This setting does not sync across browsers or devices.": "Bu ayar tarayıcılar veya cihazlar arasında senkronize edilmez.",
 	"This will delete": "Bu silinecek",
 	"Thorough explanation": "Kapsamlı açıklama",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "İpucu: Her değiştirmeden sonra sohbet girişinde tab tuşuna basarak birden fazla değişken yuvasını art arda güncelleyin.",
 	"Title": "Başlık",
 	"Title (e.g. Tell me a fun fact)": "Başlık (e.g. Bana ilginç bir bilgi ver)",
@@ -607,6 +615,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ah! {{provider}}'a bağlanırken bir sorun oluştu.",
 	"UI": "UI",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Bilinmeyen dosya türü '{{file_type}}'. Yine de dosya yükleme işlemine devam ediliyor.",
+	"Unpin": "",
 	"Update": "Güncelle",
 	"Update and Copy Link": "Güncelle ve Bağlantıyı Kopyala",
 	"Update password": "Parolayı Güncelle",

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

@@ -126,6 +126,7 @@
 	"Connections": "З'єднання",
 	"Contact Admin for WebUI Access": "Зверніться до адміна для отримання доступу до WebUI",
 	"Content": "Зміст",
+	"Content Extraction": "",
 	"Context Length": "Довжина контексту",
 	"Continue Response": "Продовжити відповідь",
 	"Continue with {{provider}}": "Продовжити з {{provider}}",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Увімкнути спільний доступ",
 	"Enable New Sign Ups": "Дозволити нові реєстрації",
 	"Enable Web Search": "Увімкнути веб-пошук",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Переконайтеся, що ваш CSV-файл містить 4 колонки в такому порядку: Ім'я, Email, Пароль, Роль.",
 	"Enter {{role}} message here": "Введіть повідомлення {{role}} тут",
 	"Enter a detail about yourself for your LLMs to recall": "Введіть відомості про себе для запам'ятовування вашими LLM.",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Введіть ключ API Serpstack",
 	"Enter stop sequence": "Введіть символ зупинки",
 	"Enter Tavily API Key": "Введіть ключ API Tavily",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Введіть Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Введіть URL-адресу (напр., http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Введіть URL-адресу (напр., http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Відкрити",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Відкрити новий чат",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "Конфігурація OpenAI API",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Відмовлено у доступі до мікрофона",
 	"Permission denied when accessing microphone: {{error}}": "Доступ до мікрофона заборонено: {{error}}",
 	"Personalization": "Персоналізація",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Конвеєр успішно видалено",
 	"Pipeline downloaded successfully": "Конвеєр успішно завантажено",
 	"Pipelines": "Конвеєри",
@@ -575,6 +581,8 @@
 	"This setting does not sync across browsers or devices.": "Це налаштування не синхронізується між браузерами або пристроями.",
 	"This will delete": "Це призведе до видалення",
 	"Thorough explanation": "Детальне пояснення",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Порада: Оновіть кілька слотів змінних послідовно, натискаючи клавішу табуляції у вікні чату після кожної заміни.",
 	"Title": "Заголовок",
 	"Title (e.g. Tell me a fun fact)": "Заголовок (напр., Розкажіть мені цікавий факт)",
@@ -609,6 +617,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ой! Виникла проблема при підключенні до {{provider}}.",
 	"UI": "Користувацький інтерфейс",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "Невідомий тип файлу '{{file_type}}'. Завантаження файлу все одно продовжується.",
+	"Unpin": "",
 	"Update": "Оновлення",
 	"Update and Copy Link": "Оновлення та копіювання посилання",
 	"Update password": "Оновити пароль",

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

@@ -126,6 +126,7 @@
 	"Connections": "Kết nối",
 	"Contact Admin for WebUI Access": "Liên hệ với Quản trị viên để được cấp quyền truy cập",
 	"Content": "Nội dung",
+	"Content Extraction": "",
 	"Context Length": "Độ dài ngữ cảnh (Context Length)",
 	"Continue Response": "Tiếp tục trả lời",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "Kích hoạt Chia sẻ Cộng đồng",
 	"Enable New Sign Ups": "Cho phép đăng ký mới",
 	"Enable Web Search": "Kích hoạt tìm kiếm Web",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Đảm bảo tệp CSV của bạn bao gồm 4 cột theo thứ tự sau: Name, Email, Password, Role.",
 	"Enter {{role}} message here": "Nhập yêu cầu của {{role}} ở đây",
 	"Enter a detail about yourself for your LLMs to recall": "Nhập chi tiết về bản thân của bạn để LLMs có thể nhớ",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "Nhập Serpstack API Key",
 	"Enter stop sequence": "Nhập stop sequence",
 	"Enter Tavily API Key": "Nhập Tavily API Key",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "Nhập Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "Nhập URL (vd: http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "Nhập URL (vd: http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "Mở",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "Mở nội dung chat mới",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "API OpenAI",
 	"OpenAI API Config": "Cấu hình API OpenAI",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "Quyền truy cập micrô bị từ chối",
 	"Permission denied when accessing microphone: {{error}}": "Quyền truy cập micrô bị từ chối: {{error}}",
 	"Personalization": "Cá nhân hóa",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "",
@@ -572,6 +578,8 @@
 	"This setting does not sync across browsers or devices.": "Cài đặt này không đồng bộ hóa trên các trình duyệt hoặc thiết bị.",
 	"This will delete": "Chat này sẽ bị xóa",
 	"Thorough explanation": "Giải thích kỹ lưỡng",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Mẹo: Cập nhật nhiều khe biến liên tiếp bằng cách nhấn phím tab trong đầu vào trò chuyện sau mỗi việc thay thế.",
 	"Title": "Tiêu đề",
 	"Title (e.g. Tell me a fun fact)": "Tiêu đề (ví dụ: Hãy kể cho tôi một sự thật thú vị về...)",
@@ -606,6 +614,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "Ồ! Đã xảy ra sự cố khi kết nối với {{provider}}.",
 	"UI": "Giao diện",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
+	"Unpin": "",
 	"Update": "Cập nhật",
 	"Update and Copy Link": "Cập nhật và sao chép link",
 	"Update password": "Cập nhật mật khẩu",

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

@@ -126,6 +126,7 @@
 	"Connections": "外部连接",
 	"Contact Admin for WebUI Access": "请联系管理员以获取访问权限",
 	"Content": "内容",
+	"Content Extraction": "",
 	"Context Length": "上下文长度",
 	"Continue Response": "继续生成",
 	"Continue with {{provider}}": "使用 {{provider}} 继续",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "启用分享至社区",
 	"Enable New Sign Ups": "允许新用户注册",
 	"Enable Web Search": "启用网络搜索",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "确保您的 CSV 文件按以下顺序包含 4 列: 姓名、电子邮箱、密码、角色。",
 	"Enter {{role}} message here": "在此处输入 {{role}} 信息",
 	"Enter a detail about yourself for your LLMs to recall": "输入一个关于你自己的详细信息,方便你的大语言模型记住这些内容",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "输入 Serpstack API 密钥",
 	"Enter stop sequence": "输入停止序列 (Stop Sequence)",
 	"Enter Tavily API Key": "输入 Tavily API 密钥",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "输入 Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "输入地址 (例如:http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "输入地址 (例如:http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "打开",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "打开新对话",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API 配置",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "申请麦克风权限被拒绝",
 	"Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}",
 	"Personalization": "个性化",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "Pipeline 删除成功",
 	"Pipeline downloaded successfully": "Pipeline 下载成功",
 	"Pipelines": "Pipeline",
@@ -572,6 +578,8 @@
 	"This setting does not sync across browsers or devices.": "此设置不会在浏览器或设备之间同步。",
 	"This will delete": "这将删除",
 	"Thorough explanation": "解释较为详细",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "提示:在每次替换后,在对话输入中按 Tab 键可以连续更新多个变量。",
 	"Title": "标题",
 	"Title (e.g. Tell me a fun fact)": "标题(例如 给我讲一个有趣的事实)",
@@ -606,6 +614,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "糟糕!连接到 {{provider}} 时出现问题。",
 	"UI": "界面",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "未知文件类型“{{file_type}}”,将无视继续上传文件。",
+	"Unpin": "",
 	"Update": "更新",
 	"Update and Copy Link": "更新和复制链接",
 	"Update password": "更新密码",

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

@@ -126,6 +126,7 @@
 	"Connections": "連線",
 	"Contact Admin for WebUI Access": "聯絡管理員以取得 WebUI 存取權",
 	"Content": "內容",
+	"Content Extraction": "",
 	"Context Length": "上下文長度",
 	"Continue Response": "繼續回答",
 	"Continue with {{provider}}": "",
@@ -212,6 +213,7 @@
 	"Enable Community Sharing": "啟用社群分享",
 	"Enable New Sign Ups": "允許註冊新帳號",
 	"Enable Web Search": "啟用網頁搜尋",
+	"Engine": "",
 	"Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "請確保您的 CSV 檔案包含這四個欄位,並按照此順序:名稱、電子郵件、密碼、角色。",
 	"Enter {{role}} message here": "在這裡輸入 {{role}} 訊息",
 	"Enter a detail about yourself for your LLMs to recall": "輸入 LLM 記憶的詳細內容",
@@ -233,6 +235,7 @@
 	"Enter Serpstack API Key": "輸入 Serpstack API 金鑰",
 	"Enter stop sequence": "輸入停止序列",
 	"Enter Tavily API Key": "輸入 Tavily API 金鑰",
+	"Enter Tika Server URL": "",
 	"Enter Top K": "輸入 Top K",
 	"Enter URL (e.g. http://127.0.0.1:7860/)": "輸入 URL(例如 http://127.0.0.1:7860/)",
 	"Enter URL (e.g. http://localhost:11434)": "輸入 URL(例如 http://localhost:11434)",
@@ -409,6 +412,7 @@
 	"Open": "開啟",
 	"Open AI (Dall-E)": "Open AI (Dall-E)",
 	"Open new chat": "開啟新聊天",
+	"Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "",
 	"OpenAI": "OpenAI",
 	"OpenAI API": "OpenAI API",
 	"OpenAI API Config": "OpenAI API 設定",
@@ -424,6 +428,8 @@
 	"Permission denied when accessing microphone": "存取麥克風時被拒絕權限",
 	"Permission denied when accessing microphone: {{error}}": "存取麥克風時被拒絕權限:{{error}}",
 	"Personalization": "個人化",
+	"Pin": "",
+	"Pinned": "",
 	"Pipeline deleted successfully": "",
 	"Pipeline downloaded successfully": "",
 	"Pipelines": "管線",
@@ -572,6 +578,8 @@
 	"This setting does not sync across browsers or devices.": "此設定不會在瀏覽器或裝置間同步。",
 	"This will delete": "",
 	"Thorough explanation": "詳細說明",
+	"Tika": "",
+	"Tika Server URL required.": "",
 	"Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "提示:透過在每次替換後在聊天輸入框中按 Tab 鍵連續更新多個變數。",
 	"Title": "標題",
 	"Title (e.g. Tell me a fun fact)": "標題(例如:告訴我一個有趣的事)",
@@ -606,6 +614,7 @@
 	"Uh-oh! There was an issue connecting to {{provider}}.": "哎呀!連線到 {{provider}} 時出現問題。",
 	"UI": "使用者界面",
 	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "未知的檔案類型 '{{file_type}}'。但仍會繼續上傳。",
+	"Unpin": "",
 	"Update": "更新",
 	"Update and Copy Link": "更新並複製連結",
 	"Update password": "更新密碼",

+ 1 - 0
src/lib/stores/index.ts

@@ -22,6 +22,7 @@ export const theme = writable('system');
 export const chatId = writable('');
 
 export const chats = writable([]);
+export const pinnedChats = writable([]);
 export const tags = writable([]);
 
 export const models: Writable<Model[]> = writable([]);

+ 18 - 0
src/routes/(app)/workspace/functions/create/+page.svelte

@@ -7,6 +7,8 @@
 	import { createNewFunction, getFunctions } from '$lib/apis/functions';
 	import FunctionEditor from '$lib/components/workspace/Functions/FunctionEditor.svelte';
 	import { getModels } from '$lib/apis';
+	import { compareVersion, extractFrontmatter } from '$lib/utils';
+	import { WEBUI_VERSION } from '$lib/constants';
 
 	const i18n = getContext('i18n');
 
@@ -16,6 +18,22 @@
 
 	const saveHandler = async (data) => {
 		console.log(data);
+
+		const manifest = extractFrontmatter(data.content);
+		if (compareVersion(manifest?.required_open_webui_version ?? '0.0.0', WEBUI_VERSION)) {
+			console.log('Version is lower than required');
+			toast.error(
+				$i18n.t(
+					'Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})',
+					{
+						OPEN_WEBUI_VERSION: WEBUI_VERSION,
+						REQUIRED_VERSION: manifest?.required_open_webui_version ?? '0.0.0'
+					}
+				)
+			);
+			return;
+		}
+
 		const res = await createNewFunction(localStorage.token, {
 			id: data.id,
 			name: data.name,

+ 18 - 0
src/routes/(app)/workspace/functions/edit/+page.svelte

@@ -10,6 +10,8 @@
 	import FunctionEditor from '$lib/components/workspace/Functions/FunctionEditor.svelte';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import { getModels } from '$lib/apis';
+	import { compareVersion, extractFrontmatter } from '$lib/utils';
+	import { WEBUI_VERSION } from '$lib/constants';
 
 	const i18n = getContext('i18n');
 
@@ -17,6 +19,22 @@
 
 	const saveHandler = async (data) => {
 		console.log(data);
+
+		const manifest = extractFrontmatter(data.content);
+		if (compareVersion(manifest?.required_open_webui_version ?? '0.0.0', WEBUI_VERSION)) {
+			console.log('Version is lower than required');
+			toast.error(
+				$i18n.t(
+					'Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})',
+					{
+						OPEN_WEBUI_VERSION: WEBUI_VERSION,
+						REQUIRED_VERSION: manifest?.required_open_webui_version ?? '0.0.0'
+					}
+				)
+			);
+			return;
+		}
+
 		const res = await updateFunctionById(localStorage.token, func.id, {
 			id: data.id,
 			name: data.name,

+ 18 - 0
src/routes/(app)/workspace/tools/create/+page.svelte

@@ -2,7 +2,9 @@
 	import { goto } from '$app/navigation';
 	import { createNewTool, getTools } from '$lib/apis/tools';
 	import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
+	import { WEBUI_VERSION } from '$lib/constants';
 	import { tools } from '$lib/stores';
+	import { compareVersion, extractFrontmatter } from '$lib/utils';
 	import { onMount, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
 
@@ -14,6 +16,22 @@
 
 	const saveHandler = async (data) => {
 		console.log(data);
+
+		const manifest = extractFrontmatter(data.content);
+		if (compareVersion(manifest?.required_open_webui_version ?? '0.0.0', WEBUI_VERSION)) {
+			console.log('Version is lower than required');
+			toast.error(
+				$i18n.t(
+					'Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})',
+					{
+						OPEN_WEBUI_VERSION: WEBUI_VERSION,
+						REQUIRED_VERSION: manifest?.required_open_webui_version ?? '0.0.0'
+					}
+				)
+			);
+			return;
+		}
+
 		const res = await createNewTool(localStorage.token, {
 			id: data.id,
 			name: data.name,

+ 18 - 0
src/routes/(app)/workspace/tools/edit/+page.svelte

@@ -4,7 +4,9 @@
 	import { getToolById, getTools, updateToolById } from '$lib/apis/tools';
 	import Spinner from '$lib/components/common/Spinner.svelte';
 	import ToolkitEditor from '$lib/components/workspace/Tools/ToolkitEditor.svelte';
+	import { WEBUI_VERSION } from '$lib/constants';
 	import { tools } from '$lib/stores';
+	import { compareVersion, extractFrontmatter } from '$lib/utils';
 	import { onMount, getContext } from 'svelte';
 	import { toast } from 'svelte-sonner';
 
@@ -14,6 +16,22 @@
 
 	const saveHandler = async (data) => {
 		console.log(data);
+
+		const manifest = extractFrontmatter(data.content);
+		if (compareVersion(manifest?.required_open_webui_version ?? '0.0.0', WEBUI_VERSION)) {
+			console.log('Version is lower than required');
+			toast.error(
+				$i18n.t(
+					'Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})',
+					{
+						OPEN_WEBUI_VERSION: WEBUI_VERSION,
+						REQUIRED_VERSION: manifest?.required_open_webui_version ?? '0.0.0'
+					}
+				)
+			);
+			return;
+		}
+
 		const res = await updateToolById(localStorage.token, tool.id, {
 			id: data.id,
 			name: data.name,