Browse Source

Merge branch 'refs/heads/dev' into feat/sqlalchemy-instead-of-peewee

# Conflicts:
#	backend/apps/webui/models/functions.py
#	backend/apps/webui/routers/chats.py
Jonathan Rohde 10 tháng trước cách đây
mục cha
commit
df47c496d3
62 tập tin đã thay đổi với 698 bổ sung322 xóa
  1. 30 0
      CHANGELOG.md
  2. 4 4
      backend/apps/images/main.py
  3. 2 2
      backend/apps/openai/main.py
  4. 10 10
      backend/apps/rag/main.py
  5. 49 0
      backend/apps/webui/internal/migrations/018_add_function_is_global.py
  6. 13 0
      backend/apps/webui/models/functions.py
  7. 2 0
      backend/apps/webui/routers/auths.py
  8. 22 25
      backend/apps/webui/routers/chats.py
  9. 2 2
      backend/apps/webui/routers/configs.py
  10. 4 4
      backend/apps/webui/routers/documents.py
  11. 27 0
      backend/apps/webui/routers/functions.py
  12. 3 3
      backend/apps/webui/routers/prompts.py
  13. 19 10
      backend/main.py
  14. 2 2
      package-lock.json
  15. 1 1
      package.json
  16. 32 0
      src/lib/apis/functions/index.ts
  17. 4 1
      src/lib/components/admin/Settings/Connections.svelte
  18. 33 28
      src/lib/components/chat/Messages/ResponseMessage.svelte
  19. 1 1
      src/lib/components/common/SensitiveInput.svelte
  20. 19 0
      src/lib/components/icons/GlobeAlt.svelte
  21. 33 8
      src/lib/components/workspace/Functions.svelte
  22. 24 3
      src/lib/components/workspace/Functions/FunctionMenu.svelte
  23. 3 0
      src/lib/i18n/locales/ar-BH/translation.json
  24. 3 0
      src/lib/i18n/locales/bg-BG/translation.json
  25. 3 0
      src/lib/i18n/locales/bn-BD/translation.json
  26. 3 0
      src/lib/i18n/locales/ca-ES/translation.json
  27. 3 0
      src/lib/i18n/locales/ceb-PH/translation.json
  28. 3 0
      src/lib/i18n/locales/de-DE/translation.json
  29. 3 0
      src/lib/i18n/locales/dg-DG/translation.json
  30. 3 0
      src/lib/i18n/locales/en-GB/translation.json
  31. 3 0
      src/lib/i18n/locales/en-US/translation.json
  32. 149 146
      src/lib/i18n/locales/es-ES/translation.json
  33. 3 0
      src/lib/i18n/locales/fa-IR/translation.json
  34. 3 0
      src/lib/i18n/locales/fi-FI/translation.json
  35. 3 0
      src/lib/i18n/locales/fr-CA/translation.json
  36. 3 0
      src/lib/i18n/locales/fr-FR/translation.json
  37. 3 0
      src/lib/i18n/locales/he-IL/translation.json
  38. 3 0
      src/lib/i18n/locales/hi-IN/translation.json
  39. 3 0
      src/lib/i18n/locales/hr-HR/translation.json
  40. 3 0
      src/lib/i18n/locales/it-IT/translation.json
  41. 3 0
      src/lib/i18n/locales/ja-JP/translation.json
  42. 3 0
      src/lib/i18n/locales/ka-GE/translation.json
  43. 3 0
      src/lib/i18n/locales/ko-KR/translation.json
  44. 3 0
      src/lib/i18n/locales/lt-LT/translation.json
  45. 3 0
      src/lib/i18n/locales/nb-NO/translation.json
  46. 3 0
      src/lib/i18n/locales/nl-NL/translation.json
  47. 3 0
      src/lib/i18n/locales/pa-IN/translation.json
  48. 3 0
      src/lib/i18n/locales/pl-PL/translation.json
  49. 3 0
      src/lib/i18n/locales/pt-BR/translation.json
  50. 3 0
      src/lib/i18n/locales/pt-PT/translation.json
  51. 3 0
      src/lib/i18n/locales/ru-RU/translation.json
  52. 3 0
      src/lib/i18n/locales/sr-RS/translation.json
  53. 3 0
      src/lib/i18n/locales/sv-SE/translation.json
  54. 3 0
      src/lib/i18n/locales/tk-TW/translation.json
  55. 3 0
      src/lib/i18n/locales/tr-TR/translation.json
  56. 3 0
      src/lib/i18n/locales/uk-UA/translation.json
  57. 3 0
      src/lib/i18n/locales/vi-VN/translation.json
  58. 54 51
      src/lib/i18n/locales/zh-CN/translation.json
  59. 3 0
      src/lib/i18n/locales/zh-TW/translation.json
  60. 16 10
      src/routes/(app)/workspace/functions/create/+page.svelte
  61. 22 1
      src/routes/(app)/workspace/models/create/+page.svelte
  62. 16 10
      src/routes/(app)/workspace/tools/create/+page.svelte

+ 30 - 0
CHANGELOG.md

@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
 
+## [0.3.6] - 2024-06-27
+
+### Added
+
+- **✨ "Functions" Feature**: You can now utilize "Functions" like filters (middleware) and pipe (model) functions directly within the WebUI. While largely compatible with Pipelines, these native functions can be executed easily within Open WebUI. Example use cases for filter functions include usage monitoring, real-time translation, moderation, and automemory. For pipe functions, the scope ranges from Cohere and Anthropic integration directly within Open WebUI, enabling "Valves" for per-user OpenAI API key usage, and much more. If you encounter issues, SAFE_MODE has been introduced.
+- **📁 Files API**: Compatible with OpenAI, this feature allows for custom Retrieval-Augmented Generation (RAG) in conjunction with the Filter Function. More examples will be shared on our community platform and official documentation website.
+- **🛠️ Tool Enhancements**: Tools now support citations and "Valves". Documentation will be available shortly.
+- **🔗 Iframe Support via Files API**: Enables rendering HTML directly into your chat interface using functions and tools. Use cases include playing games like DOOM and Snake, displaying a weather applet, and implementing Anthropic "artifacts"-like features. Stay tuned for updates on our community platform and documentation.
+- **🔒 Experimental OAuth Support**: New experimental OAuth support. Check our documentation for more details.
+- **🖼️ Custom Background Support**: Set a custom background from Settings > Interface to personalize your experience.
+- **🔑 AUTOMATIC1111_API_AUTH Support**: Enhanced security for the AUTOMATIC1111 API.
+- **🎨 Code Highlight Optimization**: Improved code highlighting features.
+- **🎙️ Voice Interruption Feature**: Reintroduced and now toggleable from Settings > Interface.
+- **💤 Wakelock API**: Now in use to prevent screen dimming during important tasks.
+- **🔐 API Key Privacy**: All API keys are now hidden by default for better security.
+- **🔍 New Web Search Provider**: Added jina_search as a new option.
+- **🌐 Enhanced Internationalization (i18n)**: Improved Korean translation and updated Chinese and Ukrainian translations.
+
+### Fixed
+
+- **🔧 Conversation Mode Issue**: Fixed the issue where Conversation Mode remained active after being removed from settings.
+- **📏 Scroll Button Obstruction**: Resolved the issue where the scrollToBottom button container obstructed clicks on buttons beneath it.
+
+### Changed
+
+- **⏲️ AIOHTTP_CLIENT_TIMEOUT**: Now set to 'None' by default for improved configuration flexibility.
+- **📞 Voice Call Enhancements**: Improved by skipping code blocks and expressions during calls.
+- **🚫 Error Message Handling**: Disabled the continuation of operations with error messages.
+- **🗂️ Playground Relocation**: Moved the Playground from the workspace to the user menu for better user experience.
+
 ## [0.3.5] - 2024-06-16
 ## [0.3.5] - 2024-06-16
 
 
 ### Added
 ### Added

+ 4 - 4
backend/apps/images/main.py

@@ -16,7 +16,7 @@ from faster_whisper import WhisperModel
 
 
 from constants import ERROR_MESSAGES
 from constants import ERROR_MESSAGES
 from utils.utils import (
 from utils.utils import (
-    get_current_user,
+    get_verified_user,
     get_admin_user,
     get_admin_user,
 )
 )
 
 
@@ -258,7 +258,7 @@ async def update_image_size(
 
 
 
 
 @app.get("/models")
 @app.get("/models")
-def get_models(user=Depends(get_current_user)):
+def get_models(user=Depends(get_verified_user)):
     try:
     try:
         if app.state.config.ENGINE == "openai":
         if app.state.config.ENGINE == "openai":
             return [
             return [
@@ -347,7 +347,7 @@ def set_model_handler(model: str):
 @app.post("/models/default/update")
 @app.post("/models/default/update")
 def update_default_model(
 def update_default_model(
     form_data: UpdateModelForm,
     form_data: UpdateModelForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     return set_model_handler(form_data.model)
     return set_model_handler(form_data.model)
 
 
@@ -424,7 +424,7 @@ def save_url_image(url):
 @app.post("/generations")
 @app.post("/generations")
 def generate_image(
 def generate_image(
     form_data: GenerateImageForm,
     form_data: GenerateImageForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     width, height = tuple(map(int, app.state.config.IMAGE_SIZE.split("x")))
     width, height = tuple(map(int, app.state.config.IMAGE_SIZE.split("x")))
 
 

+ 2 - 2
backend/apps/openai/main.py

@@ -16,7 +16,7 @@ from apps.webui.models.users import Users
 from constants import ERROR_MESSAGES
 from constants import ERROR_MESSAGES
 from utils.utils import (
 from utils.utils import (
     decode_token,
     decode_token,
-    get_current_user,
+    get_verified_user,
     get_verified_user,
     get_verified_user,
     get_admin_user,
     get_admin_user,
 )
 )
@@ -296,7 +296,7 @@ async def get_all_models(raw: bool = False):
 
 
 @app.get("/models")
 @app.get("/models")
 @app.get("/models/{url_idx}")
 @app.get("/models/{url_idx}")
-async def get_models(url_idx: Optional[int] = None, user=Depends(get_current_user)):
+async def get_models(url_idx: Optional[int] = None, user=Depends(get_verified_user)):
     if url_idx == None:
     if url_idx == None:
         models = await get_all_models()
         models = await get_all_models()
         if app.state.config.ENABLE_MODEL_FILTER:
         if app.state.config.ENABLE_MODEL_FILTER:

+ 10 - 10
backend/apps/rag/main.py

@@ -85,7 +85,7 @@ from utils.misc import (
     sanitize_filename,
     sanitize_filename,
     extract_folders_after_data_docs,
     extract_folders_after_data_docs,
 )
 )
-from utils.utils import get_current_user, get_admin_user
+from utils.utils import get_verified_user, get_admin_user
 
 
 from config import (
 from config import (
     AppConfig,
     AppConfig,
@@ -529,7 +529,7 @@ async def update_rag_config(form_data: ConfigUpdateForm, user=Depends(get_admin_
 
 
 
 
 @app.get("/template")
 @app.get("/template")
-async def get_rag_template(user=Depends(get_current_user)):
+async def get_rag_template(user=Depends(get_verified_user)):
     return {
     return {
         "status": True,
         "status": True,
         "template": app.state.config.RAG_TEMPLATE,
         "template": app.state.config.RAG_TEMPLATE,
@@ -586,7 +586,7 @@ class QueryDocForm(BaseModel):
 @app.post("/query/doc")
 @app.post("/query/doc")
 def query_doc_handler(
 def query_doc_handler(
     form_data: QueryDocForm,
     form_data: QueryDocForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     try:
     try:
         if app.state.config.ENABLE_RAG_HYBRID_SEARCH:
         if app.state.config.ENABLE_RAG_HYBRID_SEARCH:
@@ -626,7 +626,7 @@ class QueryCollectionsForm(BaseModel):
 @app.post("/query/collection")
 @app.post("/query/collection")
 def query_collection_handler(
 def query_collection_handler(
     form_data: QueryCollectionsForm,
     form_data: QueryCollectionsForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     try:
     try:
         if app.state.config.ENABLE_RAG_HYBRID_SEARCH:
         if app.state.config.ENABLE_RAG_HYBRID_SEARCH:
@@ -657,7 +657,7 @@ def query_collection_handler(
 
 
 
 
 @app.post("/youtube")
 @app.post("/youtube")
-def store_youtube_video(form_data: UrlForm, user=Depends(get_current_user)):
+def store_youtube_video(form_data: UrlForm, user=Depends(get_verified_user)):
     try:
     try:
         loader = YoutubeLoader.from_youtube_url(
         loader = YoutubeLoader.from_youtube_url(
             form_data.url,
             form_data.url,
@@ -686,7 +686,7 @@ def store_youtube_video(form_data: UrlForm, user=Depends(get_current_user)):
 
 
 
 
 @app.post("/web")
 @app.post("/web")
-def store_web(form_data: UrlForm, user=Depends(get_current_user)):
+def store_web(form_data: UrlForm, user=Depends(get_verified_user)):
     # "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm"
     # "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm"
     try:
     try:
         loader = get_web_loader(
         loader = get_web_loader(
@@ -864,7 +864,7 @@ def search_web(engine: str, query: str) -> list[SearchResult]:
 
 
 
 
 @app.post("/web/search")
 @app.post("/web/search")
-def store_web_search(form_data: SearchForm, user=Depends(get_current_user)):
+def store_web_search(form_data: SearchForm, user=Depends(get_verified_user)):
     try:
     try:
         logging.info(
         logging.info(
             f"trying to web search with {app.state.config.RAG_WEB_SEARCH_ENGINE, form_data.query}"
             f"trying to web search with {app.state.config.RAG_WEB_SEARCH_ENGINE, form_data.query}"
@@ -1084,7 +1084,7 @@ def get_loader(filename: str, file_content_type: str, file_path: str):
 def store_doc(
 def store_doc(
     collection_name: Optional[str] = Form(None),
     collection_name: Optional[str] = Form(None),
     file: UploadFile = File(...),
     file: UploadFile = File(...),
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     # "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm"
     # "https://www.gutenberg.org/files/1727/1727-h/1727-h.htm"
 
 
@@ -1145,7 +1145,7 @@ class ProcessDocForm(BaseModel):
 @app.post("/process/doc")
 @app.post("/process/doc")
 def process_doc(
 def process_doc(
     form_data: ProcessDocForm,
     form_data: ProcessDocForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     try:
     try:
         file = Files.get_file_by_id(form_data.file_id)
         file = Files.get_file_by_id(form_data.file_id)
@@ -1200,7 +1200,7 @@ class TextRAGForm(BaseModel):
 @app.post("/text")
 @app.post("/text")
 def store_text(
 def store_text(
     form_data: TextRAGForm,
     form_data: TextRAGForm,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
 
 
     collection_name = form_data.collection_name
     collection_name = form_data.collection_name

+ 49 - 0
backend/apps/webui/internal/migrations/018_add_function_is_global.py

@@ -0,0 +1,49 @@
+"""Peewee migrations -- 017_add_user_oauth_sub.py.
+
+Some examples (model - class or model name)::
+
+    > Model = migrator.orm['table_name']            # Return model in current state by name
+    > Model = migrator.ModelClass                   # Return model in current state by name
+
+    > migrator.sql(sql)                             # Run custom SQL
+    > migrator.run(func, *args, **kwargs)           # Run python function with the given args
+    > migrator.create_model(Model)                  # Create a model (could be used as decorator)
+    > migrator.remove_model(model, cascade=True)    # Remove a model
+    > migrator.add_fields(model, **fields)          # Add fields to a model
+    > migrator.change_fields(model, **fields)       # Change fields
+    > migrator.remove_fields(model, *field_names, cascade=True)
+    > migrator.rename_field(model, old_field_name, new_field_name)
+    > migrator.rename_table(model, new_table_name)
+    > migrator.add_index(model, *col_names, unique=False)
+    > migrator.add_not_null(model, *field_names)
+    > migrator.add_default(model, field_name, default)
+    > migrator.add_constraint(model, name, sql)
+    > migrator.drop_index(model, *col_names)
+    > migrator.drop_not_null(model, *field_names)
+    > migrator.drop_constraints(model, *constraints)
+
+"""
+
+from contextlib import suppress
+
+import peewee as pw
+from peewee_migrate import Migrator
+
+
+with suppress(ImportError):
+    import playhouse.postgres_ext as pw_pext
+
+
+def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your migrations here."""
+
+    migrator.add_fields(
+        "function",
+        is_global=pw.BooleanField(default=False),
+    )
+
+
+def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
+    """Write your rollback migrations here."""
+
+    migrator.remove_fields("function", "is_global")

+ 13 - 0
backend/apps/webui/models/functions.py

@@ -33,6 +33,7 @@ class Function(Base):
     meta = Column(JSONField)
     meta = Column(JSONField)
     valves = Column(JSONField)
     valves = Column(JSONField)
     is_active = Column(Boolean)
     is_active = Column(Boolean)
+    is_global = Column(Boolean)
     updated_at = Column(BigInteger)
     updated_at = Column(BigInteger)
     created_at = Column(BigInteger)
     created_at = Column(BigInteger)
 
 
@@ -50,6 +51,7 @@ class FunctionModel(BaseModel):
     content: str
     content: str
     meta: FunctionMeta
     meta: FunctionMeta
     is_active: bool = False
     is_active: bool = False
+    is_global: bool = False
     updated_at: int  # timestamp in epoch
     updated_at: int  # timestamp in epoch
     created_at: int  # timestamp in epoch
     created_at: int  # timestamp in epoch
 
 
@@ -68,6 +70,7 @@ class FunctionResponse(BaseModel):
     name: str
     name: str
     meta: FunctionMeta
     meta: FunctionMeta
     is_active: bool
     is_active: bool
+    is_global: bool
     updated_at: int  # timestamp in epoch
     updated_at: int  # timestamp in epoch
     created_at: int  # timestamp in epoch
     created_at: int  # timestamp in epoch
 
 
@@ -146,6 +149,16 @@ class FunctionsTable:
                 for function in Session.query(Function).filter_by(type=type).all()
                 for function in Session.query(Function).filter_by(type=type).all()
             ]
             ]
 
 
+    def get_global_filter_functions(self) -> List[FunctionModel]:
+        return [
+            FunctionModel(**model_to_dict(function))
+            for function in Function.select().where(
+                Function.type == "filter",
+                Function.is_active == True,
+                Function.is_global == True,
+            )
+        ]
+
     def get_function_valves_by_id(self, id: str) -> Optional[dict]:
     def get_function_valves_by_id(self, id: str) -> Optional[dict]:
         try:
         try:
             function = Session.get(Function, id)
             function = Session.get(Function, id)

+ 2 - 0
backend/apps/webui/routers/auths.py

@@ -136,6 +136,7 @@ async def signin(request: Request, response: Response, form_data: SigninForm):
         if not Users.get_user_by_email(trusted_email.lower()):
         if not Users.get_user_by_email(trusted_email.lower()):
             await signup(
             await signup(
                 request,
                 request,
+                response,
                 SignupForm(
                 SignupForm(
                     email=trusted_email, password=str(uuid.uuid4()), name=trusted_name
                     email=trusted_email, password=str(uuid.uuid4()), name=trusted_name
                 ),
                 ),
@@ -153,6 +154,7 @@ async def signin(request: Request, response: Response, form_data: SigninForm):
 
 
             await signup(
             await signup(
                 request,
                 request,
+                response,
                 SignupForm(email=admin_email, password=admin_password, name="User"),
                 SignupForm(email=admin_email, password=admin_password, name="User"),
             )
             )
 
 

+ 22 - 25
backend/apps/webui/routers/chats.py

@@ -1,8 +1,7 @@
 from fastapi import Depends, Request, HTTPException, status
 from fastapi import Depends, Request, HTTPException, status
 from datetime import datetime, timedelta
 from datetime import datetime, timedelta
 from typing import List, Union, Optional
 from typing import List, Union, Optional
-
-from utils.utils import get_current_user, get_admin_user
+from utils.utils import get_verified_user, get_admin_user
 from fastapi import APIRouter
 from fastapi import APIRouter
 from pydantic import BaseModel
 from pydantic import BaseModel
 import json
 import json
@@ -44,7 +43,7 @@ router = APIRouter()
 @router.get("/", response_model=List[ChatTitleIdResponse])
 @router.get("/", response_model=List[ChatTitleIdResponse])
 @router.get("/list", response_model=List[ChatTitleIdResponse])
 @router.get("/list", response_model=List[ChatTitleIdResponse])
 async def get_session_user_chat_list(
 async def get_session_user_chat_list(
-    user=Depends(get_current_user), skip: int = 0, limit: int = 50
+    user=Depends(get_verified_user), skip: int = 0, limit: int = 50
 ):
 ):
     return Chats.get_chat_list_by_user_id(user.id, skip, limit)
     return Chats.get_chat_list_by_user_id(user.id, skip, limit)
 
 
@@ -55,7 +54,7 @@ async def get_session_user_chat_list(
 
 
 
 
 @router.delete("/", response_model=bool)
 @router.delete("/", response_model=bool)
-async def delete_all_user_chats(request: Request, user=Depends(get_current_user)):
+async def delete_all_user_chats(request: Request, user=Depends(get_verified_user)):
 
 
     if (
     if (
         user.role == "user"
         user.role == "user"
@@ -93,7 +92,7 @@ async def get_user_chat_list_by_user_id(
 
 
 
 
 @router.post("/new", response_model=Optional[ChatResponse])
 @router.post("/new", response_model=Optional[ChatResponse])
-async def create_new_chat(form_data: ChatForm, user=Depends(get_current_user)):
+async def create_new_chat(form_data: ChatForm, user=Depends(get_verified_user)):
     try:
     try:
         chat = Chats.insert_new_chat(user.id, form_data)
         chat = Chats.insert_new_chat(user.id, form_data)
         return ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
         return ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
@@ -110,7 +109,7 @@ async def create_new_chat(form_data: ChatForm, user=Depends(get_current_user)):
 
 
 
 
 @router.get("/all", response_model=List[ChatResponse])
 @router.get("/all", response_model=List[ChatResponse])
-async def get_user_chats(user=Depends(get_current_user)):
+async def get_user_chats(user=Depends(get_verified_user)):
     return [
     return [
         ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
         ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
         for chat in Chats.get_chats_by_user_id(user.id)
         for chat in Chats.get_chats_by_user_id(user.id)
@@ -123,7 +122,7 @@ async def get_user_chats(user=Depends(get_current_user)):
 
 
 
 
 @router.get("/all/archived", response_model=List[ChatResponse])
 @router.get("/all/archived", response_model=List[ChatResponse])
-async def get_user_archived_chats(user=Depends(get_current_user)):
+async def get_user_archived_chats(user=Depends(get_verified_user)):
     return [
     return [
         ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
         ChatResponse(**{**chat.model_dump(), "chat": json.loads(chat.chat)})
         for chat in Chats.get_archived_chats_by_user_id(user.id)
         for chat in Chats.get_archived_chats_by_user_id(user.id)
@@ -155,7 +154,7 @@ async def get_all_user_chats_in_db(user=Depends(get_admin_user)):
 
 
 @router.get("/archived", response_model=List[ChatTitleIdResponse])
 @router.get("/archived", response_model=List[ChatTitleIdResponse])
 async def get_archived_session_user_chat_list(
 async def get_archived_session_user_chat_list(
-    user=Depends(get_current_user), skip: int = 0, limit: int = 50
+    user=Depends(get_verified_user), skip: int = 0, limit: int = 50
 ):
 ):
     return Chats.get_archived_chat_list_by_user_id(user.id, skip, limit)
     return Chats.get_archived_chat_list_by_user_id(user.id, skip, limit)
 
 
@@ -166,7 +165,7 @@ async def get_archived_session_user_chat_list(
 
 
 
 
 @router.post("/archive/all", response_model=bool)
 @router.post("/archive/all", response_model=bool)
-async def archive_all_chats(user=Depends(get_current_user)):
+async def archive_all_chats(user=Depends(get_verified_user)):
     return Chats.archive_all_chats_by_user_id(user.id)
     return Chats.archive_all_chats_by_user_id(user.id)
 
 
 
 
@@ -176,7 +175,7 @@ async def archive_all_chats(user=Depends(get_current_user)):
 
 
 
 
 @router.get("/share/{share_id}", response_model=Optional[ChatResponse])
 @router.get("/share/{share_id}", response_model=Optional[ChatResponse])
-async def get_shared_chat_by_id(share_id: str, user=Depends(get_current_user)):
+async def get_shared_chat_by_id(share_id: str, user=Depends(get_verified_user)):
     if user.role == "pending":
     if user.role == "pending":
         raise HTTPException(
         raise HTTPException(
             status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND
             status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND
@@ -208,7 +207,7 @@ class TagNameForm(BaseModel):
 
 
 @router.post("/tags", response_model=List[ChatTitleIdResponse])
 @router.post("/tags", response_model=List[ChatTitleIdResponse])
 async def get_user_chat_list_by_tag_name(
 async def get_user_chat_list_by_tag_name(
-    form_data: TagNameForm, user=Depends(get_current_user)
+    form_data: TagNameForm, user=Depends(get_verified_user)
 ):
 ):
 
 
     print(form_data)
     print(form_data)
@@ -233,7 +232,7 @@ async def get_user_chat_list_by_tag_name(
 
 
 
 
 @router.get("/tags/all", response_model=List[TagModel])
 @router.get("/tags/all", response_model=List[TagModel])
-async def get_all_tags(user=Depends(get_current_user)):
+async def get_all_tags(user=Depends(get_verified_user)):
     try:
     try:
         tags = Tags.get_tags_by_user_id(user.id)
         tags = Tags.get_tags_by_user_id(user.id)
         return tags
         return tags
@@ -250,7 +249,7 @@ async def get_all_tags(user=Depends(get_current_user)):
 
 
 
 
 @router.get("/{id}", response_model=Optional[ChatResponse])
 @router.get("/{id}", response_model=Optional[ChatResponse])
-async def get_chat_by_id(id: str, user=Depends(get_current_user)):
+async def get_chat_by_id(id: str, user=Depends(get_verified_user)):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
 
 
     if chat:
     if chat:
@@ -268,7 +267,7 @@ async def get_chat_by_id(id: str, user=Depends(get_current_user)):
 
 
 @router.post("/{id}", response_model=Optional[ChatResponse])
 @router.post("/{id}", response_model=Optional[ChatResponse])
 async def update_chat_by_id(
 async def update_chat_by_id(
-    id: str, form_data: ChatForm, user=Depends(get_current_user)
+    id: str, form_data: ChatForm, user=Depends(get_verified_user)
 ):
 ):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     if chat:
     if chat:
@@ -289,7 +288,7 @@ async def update_chat_by_id(
 
 
 
 
 @router.delete("/{id}", response_model=bool)
 @router.delete("/{id}", response_model=bool)
-async def delete_chat_by_id(request: Request, id: str, user=Depends(get_current_user)):
+async def delete_chat_by_id(request: Request, id: str, user=Depends(get_verified_user)):
 
 
     if user.role == "admin":
     if user.role == "admin":
         result = Chats.delete_chat_by_id(id)
         result = Chats.delete_chat_by_id(id)
@@ -311,7 +310,7 @@ async def delete_chat_by_id(request: Request, id: str, user=Depends(get_current_
 
 
 
 
 @router.get("/{id}/clone", response_model=Optional[ChatResponse])
 @router.get("/{id}/clone", response_model=Optional[ChatResponse])
-async def clone_chat_by_id(id: str, user=Depends(get_current_user)):
+async def clone_chat_by_id(id: str, user=Depends(get_verified_user)):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     if chat:
     if chat:
 
 
@@ -337,7 +336,7 @@ async def clone_chat_by_id(id: str, user=Depends(get_current_user)):
 
 
 
 
 @router.get("/{id}/archive", response_model=Optional[ChatResponse])
 @router.get("/{id}/archive", response_model=Optional[ChatResponse])
-async def archive_chat_by_id(id: str, user=Depends(get_current_user)):
+async def archive_chat_by_id(id: str, user=Depends(get_verified_user)):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     if chat:
     if chat:
         chat = Chats.toggle_chat_archive_by_id(id)
         chat = Chats.toggle_chat_archive_by_id(id)
@@ -354,7 +353,7 @@ async def archive_chat_by_id(id: str, user=Depends(get_current_user)):
 
 
 
 
 @router.post("/{id}/share", response_model=Optional[ChatResponse])
 @router.post("/{id}/share", response_model=Optional[ChatResponse])
-async def share_chat_by_id(id: str, user=Depends(get_current_user)):
+async def share_chat_by_id(id: str, user=Depends(get_verified_user)):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     if chat:
     if chat:
         if chat.share_id:
         if chat.share_id:
@@ -386,7 +385,7 @@ async def share_chat_by_id(id: str, user=Depends(get_current_user)):
 
 
 
 
 @router.delete("/{id}/share", response_model=Optional[bool])
 @router.delete("/{id}/share", response_model=Optional[bool])
-async def delete_shared_chat_by_id(id: str, user=Depends(get_current_user)):
+async def delete_shared_chat_by_id(id: str, user=Depends(get_verified_user)):
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     chat = Chats.get_chat_by_id_and_user_id(id, user.id)
     if chat:
     if chat:
         if not chat.share_id:
         if not chat.share_id:
@@ -409,7 +408,7 @@ async def delete_shared_chat_by_id(id: str, user=Depends(get_current_user)):
 
 
 
 
 @router.get("/{id}/tags", response_model=List[TagModel])
 @router.get("/{id}/tags", response_model=List[TagModel])
-async def get_chat_tags_by_id(id: str, user=Depends(get_current_user)):
+async def get_chat_tags_by_id(id: str, user=Depends(get_verified_user)):
     tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
     tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
 
 
     if tags != None:
     if tags != None:
@@ -427,7 +426,7 @@ async def get_chat_tags_by_id(id: str, user=Depends(get_current_user)):
 
 
 @router.post("/{id}/tags", response_model=Optional[ChatIdTagModel])
 @router.post("/{id}/tags", response_model=Optional[ChatIdTagModel])
 async def add_chat_tag_by_id(
 async def add_chat_tag_by_id(
-    id: str, form_data: ChatIdTagForm, user=Depends(get_current_user)
+    id: str, form_data: ChatIdTagForm, user=Depends(get_verified_user)
 ):
 ):
     tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
     tags = Tags.get_tags_by_chat_id_and_user_id(id, user.id)
 
 
@@ -454,9 +453,7 @@ async def add_chat_tag_by_id(
 
 
 @router.delete("/{id}/tags", response_model=Optional[bool])
 @router.delete("/{id}/tags", response_model=Optional[bool])
 async def delete_chat_tag_by_id(
 async def delete_chat_tag_by_id(
-    id: str,
-    form_data: ChatIdTagForm,
-    user=Depends(get_current_user),
+    id: str, form_data: ChatIdTagForm, user=Depends(get_verified_user)
 ):
 ):
     result = Tags.delete_tag_by_tag_name_and_chat_id_and_user_id(
     result = Tags.delete_tag_by_tag_name_and_chat_id_and_user_id(
         form_data.tag_name, id, user.id
         form_data.tag_name, id, user.id
@@ -476,7 +473,7 @@ async def delete_chat_tag_by_id(
 
 
 
 
 @router.delete("/{id}/tags/all", response_model=Optional[bool])
 @router.delete("/{id}/tags/all", response_model=Optional[bool])
-async def delete_all_chat_tags_by_id(id: str, user=Depends(get_current_user)):
+async def delete_all_chat_tags_by_id(id: str, user=Depends(get_verified_user)):
     result = Tags.delete_tags_by_chat_id_and_user_id(id, user.id)
     result = Tags.delete_tags_by_chat_id_and_user_id(id, user.id)
 
 
     if result:
     if result:

+ 2 - 2
backend/apps/webui/routers/configs.py

@@ -14,7 +14,7 @@ from apps.webui.models.users import Users
 
 
 from utils.utils import (
 from utils.utils import (
     get_password_hash,
     get_password_hash,
-    get_current_user,
+    get_verified_user,
     get_admin_user,
     get_admin_user,
     create_token,
     create_token,
 )
 )
@@ -84,6 +84,6 @@ async def set_banners(
 @router.get("/banners", response_model=List[BannerModel])
 @router.get("/banners", response_model=List[BannerModel])
 async def get_banners(
 async def get_banners(
     request: Request,
     request: Request,
-    user=Depends(get_current_user),
+    user=Depends(get_verified_user),
 ):
 ):
     return request.app.state.config.BANNERS
     return request.app.state.config.BANNERS

+ 4 - 4
backend/apps/webui/routers/documents.py

@@ -14,7 +14,7 @@ from apps.webui.models.documents import (
     DocumentResponse,
     DocumentResponse,
 )
 )
 
 
-from utils.utils import get_current_user, get_admin_user
+from utils.utils import get_verified_user, get_admin_user
 from constants import ERROR_MESSAGES
 from constants import ERROR_MESSAGES
 
 
 router = APIRouter()
 router = APIRouter()
@@ -25,7 +25,7 @@ router = APIRouter()
 
 
 
 
 @router.get("/", response_model=List[DocumentResponse])
 @router.get("/", response_model=List[DocumentResponse])
-async def get_documents(user=Depends(get_current_user)):
+async def get_documents(user=Depends(get_verified_user)):
     docs = [
     docs = [
         DocumentResponse(
         DocumentResponse(
             **{
             **{
@@ -74,7 +74,7 @@ async def create_new_doc(form_data: DocumentForm, user=Depends(get_admin_user)):
 
 
 
 
 @router.get("/doc", response_model=Optional[DocumentResponse])
 @router.get("/doc", response_model=Optional[DocumentResponse])
-async def get_doc_by_name(name: str, user=Depends(get_current_user)):
+async def get_doc_by_name(name: str, user=Depends(get_verified_user)):
     doc = Documents.get_doc_by_name(name)
     doc = Documents.get_doc_by_name(name)
 
 
     if doc:
     if doc:
@@ -106,7 +106,7 @@ class TagDocumentForm(BaseModel):
 
 
 
 
 @router.post("/doc/tags", response_model=Optional[DocumentResponse])
 @router.post("/doc/tags", response_model=Optional[DocumentResponse])
-async def tag_doc_by_name(form_data: TagDocumentForm, user=Depends(get_current_user)):
+async def tag_doc_by_name(form_data: TagDocumentForm, user=Depends(get_verified_user)):
     doc = Documents.update_doc_content_by_name(form_data.name, {"tags": form_data.tags})
     doc = Documents.update_doc_content_by_name(form_data.name, {"tags": form_data.tags})
 
 
     if doc:
     if doc:

+ 27 - 0
backend/apps/webui/routers/functions.py

@@ -147,6 +147,33 @@ async def toggle_function_by_id(id: str, user=Depends(get_admin_user)):
         )
         )
 
 
 
 
+############################
+# ToggleGlobalById
+############################
+
+
+@router.post("/id/{id}/toggle/global", response_model=Optional[FunctionModel])
+async def toggle_global_by_id(id: str, user=Depends(get_admin_user)):
+    function = Functions.get_function_by_id(id)
+    if function:
+        function = Functions.update_function_by_id(
+            id, {"is_global": not function.is_global}
+        )
+
+        if function:
+            return function
+        else:
+            raise HTTPException(
+                status_code=status.HTTP_400_BAD_REQUEST,
+                detail=ERROR_MESSAGES.DEFAULT("Error updating function"),
+            )
+    else:
+        raise HTTPException(
+            status_code=status.HTTP_401_UNAUTHORIZED,
+            detail=ERROR_MESSAGES.NOT_FOUND,
+        )
+
+
 ############################
 ############################
 # UpdateFunctionById
 # UpdateFunctionById
 ############################
 ############################

+ 3 - 3
backend/apps/webui/routers/prompts.py

@@ -8,7 +8,7 @@ import json
 
 
 from apps.webui.models.prompts import Prompts, PromptForm, PromptModel
 from apps.webui.models.prompts import Prompts, PromptForm, PromptModel
 
 
-from utils.utils import get_current_user, get_admin_user
+from utils.utils import get_verified_user, get_admin_user
 from constants import ERROR_MESSAGES
 from constants import ERROR_MESSAGES
 
 
 router = APIRouter()
 router = APIRouter()
@@ -19,7 +19,7 @@ router = APIRouter()
 
 
 
 
 @router.get("/", response_model=List[PromptModel])
 @router.get("/", response_model=List[PromptModel])
-async def get_prompts(user=Depends(get_current_user)):
+async def get_prompts(user=Depends(get_verified_user)):
     return Prompts.get_prompts()
     return Prompts.get_prompts()
 
 
 
 
@@ -52,7 +52,7 @@ async def create_new_prompt(form_data: PromptForm, user=Depends(get_admin_user))
 
 
 
 
 @router.get("/command/{command}", response_model=Optional[PromptModel])
 @router.get("/command/{command}", response_model=Optional[PromptModel])
-async def get_prompt_by_command(command: str, user=Depends(get_current_user)):
+async def get_prompt_by_command(command: str, user=Depends(get_verified_user)):
     prompt = Prompts.get_prompt_by_command(f"/{command}")
     prompt = Prompts.get_prompt_by_command(f"/{command}")
 
 
     if prompt:
     if prompt:

+ 19 - 10
backend/main.py

@@ -433,15 +433,21 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware):
                 return 0
                 return 0
 
 
             filter_ids = [
             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
                 function.id
                 for function in Functions.get_functions_by_type(
                 for function in Functions.get_functions_by_type(
                     "filter", active_only=True
                     "filter", active_only=True
                 )
                 )
             ]
             ]
-            # Check if the model has any filters
-            if "info" in model and "meta" in model["info"]:
-                filter_ids.extend(model["info"]["meta"].get("filterIds", []))
-                filter_ids = list(set(filter_ids))
+            filter_ids = [
+                filter_id for filter_id in filter_ids if filter_id in enabled_filter_ids
+            ]
 
 
             filter_ids.sort(key=get_priority)
             filter_ids.sort(key=get_priority)
             for filter_id in filter_ids:
             for filter_id in filter_ids:
@@ -939,7 +945,6 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u
         )
         )
 
 
     model = app.state.MODELS[model_id]
     model = app.state.MODELS[model_id]
-    print(model)
 
 
     pipe = model.get("pipe")
     pipe = model.get("pipe")
     if pipe:
     if pipe:
@@ -1030,15 +1035,19 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
             return (function.valves if function.valves else {}).get("priority", 0)
             return (function.valves if function.valves else {}).get("priority", 0)
         return 0
         return 0
 
 
-    filter_ids = [
-        function.id
-        for function in Functions.get_functions_by_type("filter", active_only=True)
-    ]
-    # Check if the model has any filters
+    filter_ids = [function.id for function in Functions.get_global_filter_functions()]
     if "info" in model and "meta" in model["info"]:
     if "info" in model and "meta" in model["info"]:
         filter_ids.extend(model["info"]["meta"].get("filterIds", []))
         filter_ids.extend(model["info"]["meta"].get("filterIds", []))
         filter_ids = list(set(filter_ids))
         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
+    ]
+
     # Sort filter_ids by priority, using the get_priority function
     # Sort filter_ids by priority, using the get_priority function
     filter_ids.sort(key=get_priority)
     filter_ids.sort(key=get_priority)
 
 

+ 2 - 2
package-lock.json

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

+ 1 - 1
package.json

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

+ 32 - 0
src/lib/apis/functions/index.ts

@@ -224,6 +224,38 @@ export const toggleFunctionById = async (token: string, id: string) => {
 	return res;
 	return res;
 };
 };
 
 
+export const toggleGlobalById = async (token: string, id: string) => {
+	let error = null;
+
+	const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/toggle/global`, {
+		method: 'POST',
+		headers: {
+			Accept: 'application/json',
+			'Content-Type': 'application/json',
+			authorization: `Bearer ${token}`
+		}
+	})
+		.then(async (res) => {
+			if (!res.ok) throw await res.json();
+			return res.json();
+		})
+		.then((json) => {
+			return json;
+		})
+		.catch((err) => {
+			error = err.detail;
+
+			console.log(err);
+			return null;
+		});
+
+	if (error) {
+		throw error;
+	}
+
+	return res;
+};
+
 export const getFunctionValvesById = async (token: string, id: string) => {
 export const getFunctionValvesById = async (token: string, id: string) => {
 	let error = null;
 	let error = null;
 
 

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

@@ -230,7 +230,10 @@
 										{/if}
 										{/if}
 									</div>
 									</div>
 
 
-									<SensitiveInput placeholder={$i18n.t('API Key')} value={OPENAI_API_KEYS[idx]} />
+									<SensitiveInput
+										placeholder={$i18n.t('API Key')}
+										bind:value={OPENAI_API_KEYS[idx]}
+									/>
 									<div class="self-center flex items-center">
 									<div class="self-center flex items-center">
 										{#if idx === 0}
 										{#if idx === 0}
 											<button
 											<button

+ 33 - 28
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -234,35 +234,40 @@
 
 
 					console.log(sentences);
 					console.log(sentences);
 
 
-					sentencesAudio = sentences.reduce((a, e, i, arr) => {
-						a[i] = null;
-						return a;
-					}, {});
-
-					let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
-
-					for (const [idx, sentence] of sentences.entries()) {
-						const res = await synthesizeOpenAISpeech(
-							localStorage.token,
-							$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
-							sentence
-						).catch((error) => {
-							toast.error(error);
-
-							speaking = null;
-							loadingSpeech = false;
-
-							return null;
-						});
-
-						if (res) {
-							const blob = await res.blob();
-							const blobUrl = URL.createObjectURL(blob);
-							const audio = new Audio(blobUrl);
-							sentencesAudio[idx] = audio;
-							loadingSpeech = false;
-							lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+					if (sentences.length > 0) {
+						sentencesAudio = sentences.reduce((a, e, i, arr) => {
+							a[i] = null;
+							return a;
+						}, {});
+
+						let lastPlayedAudioPromise = Promise.resolve(); // Initialize a promise that resolves immediately
+
+						for (const [idx, sentence] of sentences.entries()) {
+							const res = await synthesizeOpenAISpeech(
+								localStorage.token,
+								$settings?.audio?.tts?.voice ?? $config?.audio?.tts?.voice,
+								sentence
+							).catch((error) => {
+								toast.error(error);
+
+								speaking = null;
+								loadingSpeech = false;
+
+								return null;
+							});
+
+							if (res) {
+								const blob = await res.blob();
+								const blobUrl = URL.createObjectURL(blob);
+								const audio = new Audio(blobUrl);
+								sentencesAudio[idx] = audio;
+								loadingSpeech = false;
+								lastPlayedAudioPromise = lastPlayedAudioPromise.then(() => playAudio(idx));
+							}
 						}
 						}
+					} else {
+						speaking = null;
+						loadingSpeech = false;
 					}
 					}
 				} else {
 				} else {
 					let voices = [];
 					let voices = [];

+ 1 - 1
src/lib/components/common/SensitiveInput.svelte

@@ -1,5 +1,5 @@
 <script lang="ts">
 <script lang="ts">
-	export let value: string;
+	export let value: string = '';
 	export let placeholder = '';
 	export let placeholder = '';
 	export let readOnly = false;
 	export let readOnly = false;
 	export let outerClassName = 'flex flex-1';
 	export let outerClassName = 'flex flex-1';

+ 19 - 0
src/lib/components/icons/GlobeAlt.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="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418"
+	/>
+</svg>

+ 33 - 8
src/lib/components/workspace/Functions.svelte

@@ -14,7 +14,8 @@
 		exportFunctions,
 		exportFunctions,
 		getFunctionById,
 		getFunctionById,
 		getFunctions,
 		getFunctions,
-		toggleFunctionById
+		toggleFunctionById,
+		toggleGlobalById
 	} from '$lib/apis/functions';
 	} from '$lib/apis/functions';
 
 
 	import ArrowDownTray from '../icons/ArrowDownTray.svelte';
 	import ArrowDownTray from '../icons/ArrowDownTray.svelte';
@@ -113,6 +114,22 @@
 			models.set(await getModels(localStorage.token));
 			models.set(await getModels(localStorage.token));
 		}
 		}
 	};
 	};
+
+	const toggleGlobalHandler = async (func) => {
+		const res = await toggleGlobalById(localStorage.token, func.id).catch((error) => {
+			toast.error(error);
+		});
+
+		if (res) {
+			if (func.is_global) {
+				toast.success($i18n.t('Filter is now globally enabled'));
+			} else {
+				toast.success($i18n.t('Filter is now globally disabled'));
+			}
+
+			functions.set(await getFunctions(localStorage.token));
+		}
+	};
 </script>
 </script>
 
 
 <svelte:head>
 <svelte:head>
@@ -259,6 +276,7 @@
 				</Tooltip>
 				</Tooltip>
 
 
 				<FunctionMenu
 				<FunctionMenu
+					{func}
 					editHandler={() => {
 					editHandler={() => {
 						goto(`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`);
 						goto(`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`);
 					}}
 					}}
@@ -275,6 +293,11 @@
 						selectedFunction = func;
 						selectedFunction = func;
 						showDeleteConfirm = true;
 						showDeleteConfirm = true;
 					}}
 					}}
+					toggleGlobalHandler={() => {
+						if (func.type === 'filter') {
+							toggleGlobalHandler(func);
+						}
+					}}
 					onClose={() => {}}
 					onClose={() => {}}
 				>
 				>
 					<button
 					<button
@@ -286,13 +309,15 @@
 				</FunctionMenu>
 				</FunctionMenu>
 
 
 				<div class=" self-center mx-1">
 				<div class=" self-center mx-1">
-					<Switch
-						bind:state={func.is_active}
-						on:change={async (e) => {
-							toggleFunctionById(localStorage.token, func.id);
-							models.set(await getModels(localStorage.token));
-						}}
-					/>
+					<Tooltip content={func.is_active ? 'Enabled' : 'Disabled'}>
+						<Switch
+							bind:state={func.is_active}
+							on:change={async (e) => {
+								toggleFunctionById(localStorage.token, func.id);
+								models.set(await getModels(localStorage.token));
+							}}
+						/>
+					</Tooltip>
 				</div>
 				</div>
 			</div>
 			</div>
 		</div>
 		</div>

+ 24 - 3
src/lib/components/workspace/Functions/FunctionMenu.svelte

@@ -5,21 +5,24 @@
 
 
 	import Dropdown from '$lib/components/common/Dropdown.svelte';
 	import Dropdown from '$lib/components/common/Dropdown.svelte';
 	import GarbageBin from '$lib/components/icons/GarbageBin.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 Tooltip from '$lib/components/common/Tooltip.svelte';
-	import Tags from '$lib/components/chat/Tags.svelte';
 	import Share from '$lib/components/icons/Share.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 DocumentDuplicate from '$lib/components/icons/DocumentDuplicate.svelte';
 	import ArrowDownTray from '$lib/components/icons/ArrowDownTray.svelte';
 	import ArrowDownTray from '$lib/components/icons/ArrowDownTray.svelte';
+	import Switch from '$lib/components/common/Switch.svelte';
+	import GlobeAlt from '$lib/components/icons/GlobeAlt.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
+	export let func;
+
 	export let editHandler: Function;
 	export let editHandler: Function;
 	export let shareHandler: Function;
 	export let shareHandler: Function;
 	export let cloneHandler: Function;
 	export let cloneHandler: Function;
 	export let exportHandler: Function;
 	export let exportHandler: Function;
 	export let deleteHandler: Function;
 	export let deleteHandler: Function;
+	export let toggleGlobalHandler: Function;
+
 	export let onClose: Function;
 	export let onClose: Function;
 
 
 	let show = false;
 	let show = false;
@@ -45,6 +48,24 @@
 			align="start"
 			align="start"
 			transition={flyAndScale}
 			transition={flyAndScale}
 		>
 		>
+			{#if func.type === 'filter'}
+				<div
+					class="flex gap-2 justify-between items-center px-3 py-2 text-sm font-medium cursor-pointerrounded-md"
+				>
+					<div class="flex gap-2 items-center">
+						<GlobeAlt />
+
+						<div class="flex items-center">{$i18n.t('Global')}</div>
+					</div>
+
+					<div>
+						<Switch on:change={toggleGlobalHandler} bind:state={func.is_global} />
+					</div>
+				</div>
+
+				<hr class="border-gray-100 dark:border-gray-800 my-1" />
+			{/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"
 				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={() => {
 				on:click={() => {

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "وضع الملف",
 	"File Mode": "وضع الملف",
 	"File not found.": "لم يتم العثور على الملف.",
 	"File not found.": "لم يتم العثور على الملف.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "تم اكتشاف انتحال بصمة الإصبع: غير قادر على استخدام الأحرف الأولى كصورة رمزية. الافتراضي لصورة الملف الشخصي الافتراضية.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "تم اكتشاف انتحال بصمة الإصبع: غير قادر على استخدام الأحرف الأولى كصورة رمزية. الافتراضي لصورة الملف الشخصي الافتراضية.",
 	"Fluidly stream large external response chunks": "دفق قطع الاستجابة الخارجية الكبيرة بسلاسة",
 	"Fluidly stream large external response chunks": "دفق قطع الاستجابة الخارجية الكبيرة بسلاسة",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "إنشاء استعلام بحث",
 	"Generating search query": "إنشاء استعلام بحث",
 	"Generation Info": "معلومات الجيل",
 	"Generation Info": "معلومات الجيل",
+	"Global": "",
 	"Good Response": "استجابة جيدة",
 	"Good Response": "استجابة جيدة",
 	"Google PSE API Key": "مفتاح واجهة برمجة تطبيقات PSE من Google",
 	"Google PSE API Key": "مفتاح واجهة برمجة تطبيقات PSE من Google",
 	"Google PSE Engine Id": "معرف محرك PSE من Google",
 	"Google PSE Engine Id": "معرف محرك PSE من Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Файл Мод",
 	"File Mode": "Файл Мод",
 	"File not found.": "Файл не е намерен.",
 	"File not found.": "Файл не е намерен.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Потвърждаване на отпечатък: Не може да се използва инициализационна буква като аватар. Потребителят се връща към стандартна аватарка.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Потвърждаване на отпечатък: Не може да се използва инициализационна буква като аватар. Потребителят се връща към стандартна аватарка.",
 	"Fluidly stream large external response chunks": "Плавно предаване на големи части от външен отговор",
 	"Fluidly stream large external response chunks": "Плавно предаване на големи части от външен отговор",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Генериране на заявка за търсене",
 	"Generating search query": "Генериране на заявка за търсене",
 	"Generation Info": "Информация за Генерация",
 	"Generation Info": "Информация за Генерация",
+	"Global": "",
 	"Good Response": "Добра отговор",
 	"Good Response": "Добра отговор",
 	"Google PSE API Key": "Google PSE API ключ",
 	"Google PSE API Key": "Google PSE API ключ",
 	"Google PSE Engine Id": "Идентификатор на двигателя на Google PSE",
 	"Google PSE Engine Id": "Идентификатор на двигателя на Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "ফাইল মোড",
 	"File Mode": "ফাইল মোড",
 	"File not found.": "ফাইল পাওয়া যায়নি",
 	"File not found.": "ফাইল পাওয়া যায়নি",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "ফিঙ্গারপ্রিন্ট স্পুফিং ধরা পড়েছে: অ্যাভাটার হিসেবে নামের আদ্যক্ষর ব্যবহার করা যাচ্ছে না। ডিফল্ট প্রোফাইল পিকচারে ফিরিয়ে নেয়া হচ্ছে।",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "ফিঙ্গারপ্রিন্ট স্পুফিং ধরা পড়েছে: অ্যাভাটার হিসেবে নামের আদ্যক্ষর ব্যবহার করা যাচ্ছে না। ডিফল্ট প্রোফাইল পিকচারে ফিরিয়ে নেয়া হচ্ছে।",
 	"Fluidly stream large external response chunks": "বড় এক্সটার্নাল রেসপন্স চাঙ্কগুলো মসৃণভাবে প্রবাহিত করুন",
 	"Fluidly stream large external response chunks": "বড় এক্সটার্নাল রেসপন্স চাঙ্কগুলো মসৃণভাবে প্রবাহিত করুন",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "অনুসন্ধান ক্যোয়ারী তৈরি করা হচ্ছে",
 	"Generating search query": "অনুসন্ধান ক্যোয়ারী তৈরি করা হচ্ছে",
 	"Generation Info": "জেনারেশন ইনফো",
 	"Generation Info": "জেনারেশন ইনফো",
+	"Global": "",
 	"Good Response": "ভালো সাড়া",
 	"Good Response": "ভালো সাড়া",
 	"Google PSE API Key": "গুগল পিএসই এপিআই কী",
 	"Google PSE API Key": "গুগল পিএসই এপিআই কী",
 	"Google PSE Engine Id": "গুগল পিএসই ইঞ্জিন আইডি",
 	"Google PSE Engine Id": "গুগল পিএসই ইঞ্জিন আইডি",

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

@@ -261,6 +261,8 @@
 	"File": "Arxiu",
 	"File": "Arxiu",
 	"File Mode": "Mode d'arxiu",
 	"File Mode": "Mode d'arxiu",
 	"File not found.": "No s'ha trobat l'arxiu.",
 	"File not found.": "No s'ha trobat l'arxiu.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "Filtres",
 	"Filters": "Filtres",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "S'ha detectat la suplantació d'identitat de l'empremta digital: no es poden utilitzar les inicials com a avatar. S'estableix la imatge de perfil predeterminada.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "S'ha detectat la suplantació d'identitat de l'empremta digital: no es poden utilitzar les inicials com a avatar. S'estableix la imatge de perfil predeterminada.",
 	"Fluidly stream large external response chunks": "Transmetre amb fluïdesa grans trossos de resposta externa",
 	"Fluidly stream large external response chunks": "Transmetre amb fluïdesa grans trossos de resposta externa",
@@ -279,6 +281,7 @@
 	"Generate Image": "Generar imatge",
 	"Generate Image": "Generar imatge",
 	"Generating search query": "Generant consulta",
 	"Generating search query": "Generant consulta",
 	"Generation Info": "Informació sobre la generació",
 	"Generation Info": "Informació sobre la generació",
+	"Global": "",
 	"Good Response": "Bona resposta",
 	"Good Response": "Bona resposta",
 	"Google PSE API Key": "Clau API PSE de Google",
 	"Google PSE API Key": "Clau API PSE de Google",
 	"Google PSE Engine Id": "Identificador del motor PSE de Google",
 	"Google PSE Engine Id": "Identificador del motor PSE de Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "File mode",
 	"File Mode": "File mode",
 	"File not found.": "Wala makit-an ang file.",
 	"File not found.": "Wala makit-an ang file.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fluidly stream large external response chunks": "Hapsay nga paghatud sa daghang mga tipik sa eksternal nga mga tubag",
 	"Fluidly stream large external response chunks": "Hapsay nga paghatud sa daghang mga tipik sa eksternal nga mga tubag",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "",
 	"Generation Info": "",
+	"Global": "",
 	"Good Response": "",
 	"Good Response": "",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "File Modus",
 	"File Mode": "File Modus",
 	"File not found.": "Datei nicht gefunden.",
 	"File not found.": "Datei nicht gefunden.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"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.",
 	"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",
 	"Fluidly stream large external response chunks": "Große externe Antwortblöcke flüssig streamen",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Suchanfrage generieren",
 	"Generating search query": "Suchanfrage generieren",
 	"Generation Info": "Generierungsinformationen",
 	"Generation Info": "Generierungsinformationen",
+	"Global": "",
 	"Good Response": "Gute Antwort",
 	"Good Response": "Gute Antwort",
 	"Google PSE API Key": "Google PSE-API-Schlüssel",
 	"Google PSE API Key": "Google PSE-API-Schlüssel",
 	"Google PSE Engine Id": "Google PSE-Engine-ID",
 	"Google PSE Engine Id": "Google PSE-Engine-ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Bark Mode",
 	"File Mode": "Bark Mode",
 	"File not found.": "Bark not found.",
 	"File not found.": "Bark not found.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint dogeing: Unable to use initials as avatar. Defaulting to default doge image.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint dogeing: Unable to use initials as avatar. Defaulting to default doge image.",
 	"Fluidly stream large external response chunks": "Fluidly wow big chunks",
 	"Fluidly stream large external response chunks": "Fluidly wow big chunks",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "",
 	"Generation Info": "",
+	"Global": "",
 	"Good Response": "",
 	"Good Response": "",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "",
 	"File Mode": "",
 	"File not found.": "",
 	"File not found.": "",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fluidly stream large external response chunks": "",
 	"Fluidly stream large external response chunks": "",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "",
 	"Generation Info": "",
+	"Global": "",
 	"Good Response": "",
 	"Good Response": "",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "",
 	"File Mode": "",
 	"File not found.": "",
 	"File not found.": "",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fluidly stream large external response chunks": "",
 	"Fluidly stream large external response chunks": "",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "",
 	"Generation Info": "",
+	"Global": "",
 	"Good Response": "",
 	"Good Response": "",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -4,7 +4,7 @@
 	"(e.g. `sh webui.sh --api --api-auth username_password`)": "",
 	"(e.g. `sh webui.sh --api --api-auth username_password`)": "",
 	"(e.g. `sh webui.sh --api`)": "(p.ej. `sh webui.sh --api`)",
 	"(e.g. `sh webui.sh --api`)": "(p.ej. `sh webui.sh --api`)",
 	"(latest)": "(latest)",
 	"(latest)": "(latest)",
-	"{{ models }}": "{{ modelos }}",
+	"{{ models }}": "{{ models }}",
 	"{{ owner }}: You cannot delete a base model": "{{ owner }}: No se puede eliminar un modelo base",
 	"{{ owner }}: You cannot delete a base model": "{{ owner }}: No se puede eliminar un modelo base",
 	"{{modelName}} is thinking...": "{{modelName}} está pensando...",
 	"{{modelName}} is thinking...": "{{modelName}} está pensando...",
 	"{{user}}'s Chats": "{{user}}'s Chats",
 	"{{user}}'s Chats": "{{user}}'s Chats",
@@ -13,9 +13,9 @@
 	"a user": "un usuario",
 	"a user": "un usuario",
 	"About": "Sobre nosotros",
 	"About": "Sobre nosotros",
 	"Account": "Cuenta",
 	"Account": "Cuenta",
-	"Account Activation Pending": "",
+	"Account Activation Pending": "Activación de cuenta pendiente",
 	"Accurate information": "Información precisa",
 	"Accurate information": "Información precisa",
-	"Active Users": "",
+	"Active Users": "Usuarios activos",
 	"Add": "Agregar",
 	"Add": "Agregar",
 	"Add a model id": "Adición de un identificador de modelo",
 	"Add a model id": "Adición de un identificador de modelo",
 	"Add a short description about what this model does": "Agregue una breve descripción sobre lo que hace este modelo",
 	"Add a short description about what this model does": "Agregue una breve descripción sobre lo que hace este modelo",
@@ -31,10 +31,10 @@
 	"Add User": "Agregar Usuario",
 	"Add User": "Agregar Usuario",
 	"Adjusting these settings will apply changes universally to all users.": "Ajustar estas opciones aplicará los cambios universalmente a todos los usuarios.",
 	"Adjusting these settings will apply changes universally to all users.": "Ajustar estas opciones aplicará los cambios universalmente a todos los usuarios.",
 	"admin": "admin",
 	"admin": "admin",
-	"Admin": "",
+	"Admin": "Admin",
 	"Admin Panel": "Panel de Administración",
 	"Admin Panel": "Panel de Administración",
 	"Admin Settings": "Configuración de Administrador",
 	"Admin Settings": "Configuración de Administrador",
-	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "",
+	"Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Admins tienen acceso a todas las herramientas en todo momento; los usuarios necesitan herramientas asignadas por modelo en el espacio de trabajo.",
 	"Advanced Parameters": "Parámetros Avanzados",
 	"Advanced Parameters": "Parámetros Avanzados",
 	"Advanced Params": "Parámetros avanzados",
 	"Advanced Params": "Parámetros avanzados",
 	"all": "todo",
 	"all": "todo",
@@ -42,9 +42,9 @@
 	"All Users": "Todos los Usuarios",
 	"All Users": "Todos los Usuarios",
 	"Allow": "Permitir",
 	"Allow": "Permitir",
 	"Allow Chat Deletion": "Permitir Borrar Chats",
 	"Allow Chat Deletion": "Permitir Borrar Chats",
-	"Allow non-local voices": "",
-	"Allow User Location": "",
-	"Allow Voice Interruption in Call": "",
+	"Allow non-local voices": "Permitir voces no locales",
+	"Allow User Location": "Permitir Ubicación del Usuario",
+	"Allow Voice Interruption in Call": "Permitir interrupción de voz en llamada",
 	"alphanumeric characters and hyphens": "caracteres alfanuméricos y guiones",
 	"alphanumeric characters and hyphens": "caracteres alfanuméricos y guiones",
 	"Already have an account?": "¿Ya tienes una cuenta?",
 	"Already have an account?": "¿Ya tienes una cuenta?",
 	"an assistant": "un asistente",
 	"an assistant": "un asistente",
@@ -63,7 +63,7 @@
 	"Attach file": "Adjuntar archivo",
 	"Attach file": "Adjuntar archivo",
 	"Attention to detail": "Detalle preciso",
 	"Attention to detail": "Detalle preciso",
 	"Audio": "Audio",
 	"Audio": "Audio",
-	"Audio settings updated successfully": "",
+	"Audio settings updated successfully": "Opciones de audio actualizadas correctamente",
 	"August": "Agosto",
 	"August": "Agosto",
 	"Auto-playback response": "Respuesta de reproducción automática",
 	"Auto-playback response": "Respuesta de reproducción automática",
 	"AUTOMATIC1111 Api Auth String": "",
 	"AUTOMATIC1111 Api Auth String": "",
@@ -74,19 +74,19 @@
 	"Bad Response": "Respuesta incorrecta",
 	"Bad Response": "Respuesta incorrecta",
 	"Banners": "Banners",
 	"Banners": "Banners",
 	"Base Model (From)": "Modelo base (desde)",
 	"Base Model (From)": "Modelo base (desde)",
-	"Batch Size (num_batch)": "",
+	"Batch Size (num_batch)": "Tamaño del Batch (num_batch)",
 	"before": "antes",
 	"before": "antes",
 	"Being lazy": "Ser perezoso",
 	"Being lazy": "Ser perezoso",
 	"Brave Search API Key": "Clave de API de Brave Search",
 	"Brave Search API Key": "Clave de API de Brave Search",
 	"Bypass SSL verification for Websites": "Desactivar la verificación SSL para sitios web",
 	"Bypass SSL verification for Websites": "Desactivar la verificación SSL para sitios web",
-	"Call": "",
-	"Call feature is not supported when using Web STT engine": "",
-	"Camera": "",
+	"Call": "Llamada",
+	"Call feature is not supported when using Web STT engine": "La funcionalidad de llamada no puede usarse junto con el motor de STT Web",
+	"Camera": "Cámara",
 	"Cancel": "Cancelar",
 	"Cancel": "Cancelar",
 	"Capabilities": "Capacidades",
 	"Capabilities": "Capacidades",
 	"Change Password": "Cambia la Contraseña",
 	"Change Password": "Cambia la Contraseña",
 	"Chat": "Chat",
 	"Chat": "Chat",
-	"Chat Background Image": "",
+	"Chat Background Image": "Imágen de fondo del Chat",
 	"Chat Bubble UI": "Burbuja de chat UI",
 	"Chat Bubble UI": "Burbuja de chat UI",
 	"Chat direction": "Dirección del Chat",
 	"Chat direction": "Dirección del Chat",
 	"Chat History": "Historial del Chat",
 	"Chat History": "Historial del Chat",
@@ -100,35 +100,35 @@
 	"Chunk Params": "Parámetros de fragmentos",
 	"Chunk Params": "Parámetros de fragmentos",
 	"Chunk Size": "Tamaño de fragmentos",
 	"Chunk Size": "Tamaño de fragmentos",
 	"Citation": "Cita",
 	"Citation": "Cita",
-	"Clear memory": "",
+	"Clear memory": "Liberar memoria",
 	"Click here for help.": "Presiona aquí para obtener ayuda.",
 	"Click here for help.": "Presiona aquí para obtener ayuda.",
 	"Click here to": "Presiona aquí para",
 	"Click here to": "Presiona aquí para",
-	"Click here to download user import template file.": "",
+	"Click here to download user import template file.": "Presiona aquí para descargar el archivo de plantilla de importación de usuario.",
 	"Click here to select": "Presiona aquí para seleccionar",
 	"Click here to select": "Presiona aquí para seleccionar",
 	"Click here to select a csv file.": "Presiona aquí para seleccionar un archivo csv.",
 	"Click here to select a csv file.": "Presiona aquí para seleccionar un archivo csv.",
-	"Click here to select a py file.": "",
+	"Click here to select a py file.": "Presiona aquí para seleccionar un archivo py.",
 	"Click here to select documents.": "Presiona aquí para seleccionar documentos",
 	"Click here to select documents.": "Presiona aquí para seleccionar documentos",
 	"click here.": "Presiona aquí.",
 	"click here.": "Presiona aquí.",
 	"Click on the user role button to change a user's role.": "Presiona en el botón de roles del usuario para cambiar su rol.",
 	"Click on the user role button to change a user's role.": "Presiona en el botón de roles del usuario para cambiar su rol.",
-	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "",
-	"Clone": "Clon",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Permisos de escritura del portapapeles denegados. Por favor, comprueba las configuraciones de tu navegador para otorgar el acceso necesario.",
+	"Clone": "Clonar",
 	"Close": "Cerrar",
 	"Close": "Cerrar",
-	"Code formatted successfully": "",
+	"Code formatted successfully": "Se ha formateado correctamente el código.",
 	"Collection": "Colección",
 	"Collection": "Colección",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI Base URL": "ComfyUI Base URL",
 	"ComfyUI Base URL": "ComfyUI Base URL",
 	"ComfyUI Base URL is required.": "ComfyUI Base URL es requerido.",
 	"ComfyUI Base URL is required.": "ComfyUI Base URL es requerido.",
 	"Command": "Comando",
 	"Command": "Comando",
 	"Concurrent Requests": "Solicitudes simultáneas",
 	"Concurrent Requests": "Solicitudes simultáneas",
-	"Confirm": "",
+	"Confirm": "Confirmar",
 	"Confirm Password": "Confirmar Contraseña",
 	"Confirm Password": "Confirmar Contraseña",
-	"Confirm your action": "",
+	"Confirm your action": "Confirma tu acción",
 	"Connections": "Conexiones",
 	"Connections": "Conexiones",
-	"Contact Admin for WebUI Access": "",
+	"Contact Admin for WebUI Access": "Contacta el administrador para obtener acceso al WebUI",
 	"Content": "Contenido",
 	"Content": "Contenido",
 	"Context Length": "Longitud del contexto",
 	"Context Length": "Longitud del contexto",
 	"Continue Response": "Continuar Respuesta",
 	"Continue Response": "Continuar Respuesta",
-	"Continue with {{provider}}": "",
+	"Continue with {{provider}}": "Continuar con {{provider}}",
 	"Copied shared chat URL to clipboard!": "¡URL de chat compartido copiado al portapapeles!",
 	"Copied shared chat URL to clipboard!": "¡URL de chat compartido copiado al portapapeles!",
 	"Copy": "Copiar",
 	"Copy": "Copiar",
 	"Copy last code block": "Copia el último bloque de código",
 	"Copy last code block": "Copia el último bloque de código",
@@ -141,14 +141,14 @@
 	"Create new secret key": "Crear una nueva clave secreta",
 	"Create new secret key": "Crear una nueva clave secreta",
 	"Created at": "Creado en",
 	"Created at": "Creado en",
 	"Created At": "Creado en",
 	"Created At": "Creado en",
-	"Created by": "",
-	"CSV Import": "",
+	"Created by": "Creado por",
+	"CSV Import": "Importa un CSV",
 	"Current Model": "Modelo Actual",
 	"Current Model": "Modelo Actual",
 	"Current Password": "Contraseña Actual",
 	"Current Password": "Contraseña Actual",
 	"Custom": "Personalizado",
 	"Custom": "Personalizado",
 	"Customize models for a specific purpose": "Personalizar modelos para un propósito específico",
 	"Customize models for a specific purpose": "Personalizar modelos para un propósito específico",
 	"Dark": "Oscuro",
 	"Dark": "Oscuro",
-	"Dashboard": "",
+	"Dashboard": "Panel de Control",
 	"Database": "Base de datos",
 	"Database": "Base de datos",
 	"December": "Diciembre",
 	"December": "Diciembre",
 	"Default": "Por defecto",
 	"Default": "Por defecto",
@@ -164,7 +164,7 @@
 	"Delete All Chats": "Eliminar todos los chats",
 	"Delete All Chats": "Eliminar todos los chats",
 	"Delete chat": "Borrar chat",
 	"Delete chat": "Borrar chat",
 	"Delete Chat": "Borrar Chat",
 	"Delete Chat": "Borrar Chat",
-	"Delete chat?": "",
+	"Delete chat?": "Borrar el chat?",
 	"Delete function?": "",
 	"Delete function?": "",
 	"Delete prompt?": "",
 	"Delete prompt?": "",
 	"delete this link": "Borrar este enlace",
 	"delete this link": "Borrar este enlace",
@@ -174,26 +174,26 @@
 	"Deleted {{name}}": "Eliminado {{nombre}}",
 	"Deleted {{name}}": "Eliminado {{nombre}}",
 	"Description": "Descripción",
 	"Description": "Descripción",
 	"Didn't fully follow instructions": "No siguió las instrucciones",
 	"Didn't fully follow instructions": "No siguió las instrucciones",
-	"Discover a function": "",
+	"Discover a function": "Descubre una función",
 	"Discover a model": "Descubrir un modelo",
 	"Discover a model": "Descubrir un modelo",
 	"Discover a prompt": "Descubre un Prompt",
 	"Discover a prompt": "Descubre un Prompt",
-	"Discover a tool": "",
-	"Discover, download, and explore custom functions": "",
+	"Discover a tool": "Descubre una herramienta",
+	"Discover, download, and explore custom functions": "Descubre, descarga y explora funciones personalizadas",
 	"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
 	"Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados",
-	"Discover, download, and explore custom tools": "",
+	"Discover, download, and explore custom tools": "Descubre, descarga y explora herramientas personalizadas",
 	"Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos",
 	"Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos",
-	"Dismissible": "",
-	"Display Emoji in Call": "",
+	"Dismissible": "Desestimable",
+	"Display Emoji in Call": "Muestra Emoji en llamada",
 	"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
 	"Display the username instead of You in the Chat": "Mostrar el nombre de usuario en lugar de Usted en el chat",
 	"Document": "Documento",
 	"Document": "Documento",
 	"Document Settings": "Configuración del Documento",
 	"Document Settings": "Configuración del Documento",
-	"Documentation": "",
+	"Documentation": "Documentación",
 	"Documents": "Documentos",
 	"Documents": "Documentos",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "no realiza ninguna conexión externa y sus datos permanecen seguros en su servidor alojado localmente.",
 	"does not make any external connections, and your data stays securely on your locally hosted server.": "no realiza ninguna conexión externa y sus datos permanecen seguros en su servidor alojado localmente.",
 	"Don't Allow": "No Permitir",
 	"Don't Allow": "No Permitir",
 	"Don't have an account?": "¿No tienes una cuenta?",
 	"Don't have an account?": "¿No tienes una cuenta?",
 	"Don't like the style": "No te gusta el estilo?",
 	"Don't like the style": "No te gusta el estilo?",
-	"Done": "",
+	"Done": "Hecho",
 	"Download": "Descargar",
 	"Download": "Descargar",
 	"Download canceled": "Descarga cancelada",
 	"Download canceled": "Descarga cancelada",
 	"Download Database": "Descarga la Base de Datos",
 	"Download Database": "Descarga la Base de Datos",
@@ -201,10 +201,10 @@
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades válidas de tiempo son 's', 'm', 'h'.",
 	"e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades válidas de tiempo son 's', 'm', 'h'.",
 	"Edit": "Editar",
 	"Edit": "Editar",
 	"Edit Doc": "Editar Documento",
 	"Edit Doc": "Editar Documento",
-	"Edit Memory": "",
+	"Edit Memory": "Editar Memoria",
 	"Edit User": "Editar Usuario",
 	"Edit User": "Editar Usuario",
 	"Email": "Email",
 	"Email": "Email",
-	"Embedding Batch Size": "",
+	"Embedding Batch Size": "Tamaño de Embedding",
 	"Embedding Model": "Modelo de Embedding",
 	"Embedding Model": "Modelo de Embedding",
 	"Embedding Model Engine": "Motor de Modelo de Embedding",
 	"Embedding Model Engine": "Motor de Modelo de Embedding",
 	"Embedding model set to \"{{embedding_model}}\"": "Modelo de Embedding configurado a \"{{embedding_model}}\"",
 	"Embedding model set to \"{{embedding_model}}\"": "Modelo de Embedding configurado a \"{{embedding_model}}\"",
@@ -229,10 +229,10 @@
 	"Enter Score": "Ingrese la puntuación",
 	"Enter Score": "Ingrese la puntuación",
 	"Enter Searxng Query URL": "Introduzca la URL de consulta de Searxng",
 	"Enter Searxng Query URL": "Introduzca la URL de consulta de Searxng",
 	"Enter Serper API Key": "Ingrese la clave API de Serper",
 	"Enter Serper API Key": "Ingrese la clave API de Serper",
-	"Enter Serply API Key": "",
+	"Enter Serply API Key": "Ingrese la clave API de Serply",
 	"Enter Serpstack API Key": "Ingrese la clave API de Serpstack",
 	"Enter Serpstack API Key": "Ingrese la clave API de Serpstack",
 	"Enter stop sequence": "Ingrese la secuencia de parada",
 	"Enter stop sequence": "Ingrese la secuencia de parada",
-	"Enter Tavily API Key": "",
+	"Enter Tavily API Key": "Ingrese la clave API de Tavily",
 	"Enter Top K": "Ingrese el Top K",
 	"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://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)",
 	"Enter URL (e.g. http://localhost:11434)": "Ingrese la URL (p.ej., http://localhost:11434)",
@@ -244,41 +244,44 @@
 	"Experimental": "Experimental",
 	"Experimental": "Experimental",
 	"Export": "Exportar",
 	"Export": "Exportar",
 	"Export All Chats (All Users)": "Exportar todos los chats (Todos los usuarios)",
 	"Export All Chats (All Users)": "Exportar todos los chats (Todos los usuarios)",
-	"Export chat (.json)": "",
+	"Export chat (.json)": "Exportar chat (.json)",
 	"Export Chats": "Exportar Chats",
 	"Export Chats": "Exportar Chats",
 	"Export Documents Mapping": "Exportar el mapeo de documentos",
 	"Export Documents Mapping": "Exportar el mapeo de documentos",
-	"Export Functions": "",
-	"Export LiteLLM config.yaml": "",
-	"Export Models": "Modelos de exportación",
+	"Export Functions": "Exportar Funciones",
+	"Export LiteLLM config.yaml": "Exportar LiteLLM config.yaml",
+	"Export Models": "Exportar Modelos",
 	"Export Prompts": "Exportar Prompts",
 	"Export Prompts": "Exportar Prompts",
-	"Export Tools": "",
-	"External Models": "",
+	"Export Tools": "Exportar Herramientas",
+	"External Models": "Modelos Externos",
 	"Failed to create API Key.": "No se pudo crear la clave API.",
 	"Failed to create API Key.": "No se pudo crear la clave API.",
 	"Failed to read clipboard contents": "No se pudo leer el contenido del portapapeles",
 	"Failed to read clipboard contents": "No se pudo leer el contenido del portapapeles",
-	"Failed to update settings": "",
+	"Failed to update settings": "Falla al actualizar los ajustes",
 	"February": "Febrero",
 	"February": "Febrero",
 	"Feel free to add specific details": "Libre de agregar detalles específicos",
 	"Feel free to add specific details": "Libre de agregar detalles específicos",
-	"File": "",
+	"File": "Archivo",
 	"File Mode": "Modo de archivo",
 	"File Mode": "Modo de archivo",
 	"File not found.": "Archivo no encontrado.",
 	"File not found.": "Archivo no encontrado.",
-	"Filters": "",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
+	"Filters": "Filtros",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Se detectó suplantación de huellas: No se pueden usar las iniciales como avatar. Por defecto se utiliza la imagen de perfil predeterminada.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Se detectó suplantación de huellas: No se pueden usar las iniciales como avatar. Por defecto se utiliza la imagen de perfil predeterminada.",
 	"Fluidly stream large external response chunks": "Transmita con fluidez grandes fragmentos de respuesta externa",
 	"Fluidly stream large external response chunks": "Transmita con fluidez grandes fragmentos de respuesta externa",
 	"Focus chat input": "Enfoca la entrada del chat",
 	"Focus chat input": "Enfoca la entrada del chat",
 	"Followed instructions perfectly": "Siguió las instrucciones perfectamente",
 	"Followed instructions perfectly": "Siguió las instrucciones perfectamente",
-	"Form": "",
+	"Form": "De",
 	"Format your variables using square brackets like this:": "Formatea tus variables usando corchetes de la siguiente manera:",
 	"Format your variables using square brackets like this:": "Formatea tus variables usando corchetes de la siguiente manera:",
 	"Frequency Penalty": "Penalización de frecuencia",
 	"Frequency Penalty": "Penalización de frecuencia",
-	"Function created successfully": "",
-	"Function deleted successfully": "",
-	"Function updated successfully": "",
-	"Functions": "",
-	"Functions imported successfully": "",
+	"Function created successfully": "Función creada exitosamente",
+	"Function deleted successfully": "Función borrada exitosamente",
+	"Function updated successfully": "Función actualizada exitosamente",
+	"Functions": "Funciones",
+	"Functions imported successfully": "Funciones importadas exitosamente",
 	"General": "General",
 	"General": "General",
 	"General Settings": "Opciones Generales",
 	"General Settings": "Opciones Generales",
-	"Generate Image": "",
+	"Generate Image": "Generar imagen",
 	"Generating search query": "Generación de consultas de búsqueda",
 	"Generating search query": "Generación de consultas de búsqueda",
 	"Generation Info": "Información de Generación",
 	"Generation Info": "Información de Generación",
+	"Global": "",
 	"Good Response": "Buena Respuesta",
 	"Good Response": "Buena Respuesta",
 	"Google PSE API Key": "Clave API de Google PSE",
 	"Google PSE API Key": "Clave API de Google PSE",
 	"Google PSE Engine Id": "ID del motor PSE de Google",
 	"Google PSE Engine Id": "ID del motor PSE de Google",
@@ -287,7 +290,7 @@
 	"Hello, {{name}}": "Hola, {{name}}",
 	"Hello, {{name}}": "Hola, {{name}}",
 	"Help": "Ayuda",
 	"Help": "Ayuda",
 	"Hide": "Esconder",
 	"Hide": "Esconder",
-	"Hide Model": "",
+	"Hide Model": "Esconder Modelo",
 	"How can I help you today?": "¿Cómo puedo ayudarte hoy?",
 	"How can I help you today?": "¿Cómo puedo ayudarte hoy?",
 	"Hybrid Search": "Búsqueda Híbrida",
 	"Hybrid Search": "Búsqueda Híbrida",
 	"Image Generation (Experimental)": "Generación de imágenes (experimental)",
 	"Image Generation (Experimental)": "Generación de imágenes (experimental)",
@@ -296,16 +299,16 @@
 	"Images": "Imágenes",
 	"Images": "Imágenes",
 	"Import Chats": "Importar chats",
 	"Import Chats": "Importar chats",
 	"Import Documents Mapping": "Importar Mapeo de Documentos",
 	"Import Documents Mapping": "Importar Mapeo de Documentos",
-	"Import Functions": "",
+	"Import Functions": "Importar Funciones",
 	"Import Models": "Importar modelos",
 	"Import Models": "Importar modelos",
 	"Import Prompts": "Importar Prompts",
 	"Import Prompts": "Importar Prompts",
-	"Import Tools": "",
+	"Import Tools": "Importar Herramientas",
 	"Include `--api-auth` flag when running stable-diffusion-webui": "",
 	"Include `--api-auth` flag when running stable-diffusion-webui": "",
 	"Include `--api` flag when running stable-diffusion-webui": "Incluir el indicador `--api` al ejecutar stable-diffusion-webui",
 	"Include `--api` flag when running stable-diffusion-webui": "Incluir el indicador `--api` al ejecutar stable-diffusion-webui",
 	"Info": "Información",
 	"Info": "Información",
 	"Input commands": "Ingresar comandos",
 	"Input commands": "Ingresar comandos",
 	"Install from Github URL": "Instalar desde la URL de Github",
 	"Install from Github URL": "Instalar desde la URL de Github",
-	"Instant Auto-Send After Voice Transcription": "",
+	"Instant Auto-Send After Voice Transcription": "Auto-Enviar Después de la Transcripción de Voz",
 	"Interface": "Interfaz",
 	"Interface": "Interfaz",
 	"Invalid Tag": "Etiqueta Inválida",
 	"Invalid Tag": "Etiqueta Inválida",
 	"January": "Enero",
 	"January": "Enero",
@@ -318,32 +321,32 @@
 	"JWT Token": "Token JWT",
 	"JWT Token": "Token JWT",
 	"Keep Alive": "Mantener Vivo",
 	"Keep Alive": "Mantener Vivo",
 	"Keyboard shortcuts": "Atajos de teclado",
 	"Keyboard shortcuts": "Atajos de teclado",
-	"Knowledge": "",
+	"Knowledge": "Conocimiento",
 	"Language": "Lenguaje",
 	"Language": "Lenguaje",
 	"Last Active": "Última Actividad",
 	"Last Active": "Última Actividad",
-	"Last Modified": "",
+	"Last Modified": "Modificado por última vez",
 	"Light": "Claro",
 	"Light": "Claro",
-	"Listening...": "",
+	"Listening...": "Escuchando...",
 	"LLMs can make mistakes. Verify important information.": "Los LLM pueden cometer errores. Verifica la información importante.",
 	"LLMs can make mistakes. Verify important information.": "Los LLM pueden cometer errores. Verifica la información importante.",
-	"Local Models": "",
+	"Local Models": "Modelos locales",
 	"LTR": "LTR",
 	"LTR": "LTR",
 	"Made by OpenWebUI Community": "Hecho por la comunidad de OpenWebUI",
 	"Made by OpenWebUI Community": "Hecho por la comunidad de OpenWebUI",
 	"Make sure to enclose them with": "Asegúrese de adjuntarlos con",
 	"Make sure to enclose them with": "Asegúrese de adjuntarlos con",
-	"Manage": "",
+	"Manage": "Gestionar",
 	"Manage Models": "Administrar Modelos",
 	"Manage Models": "Administrar Modelos",
 	"Manage Ollama Models": "Administrar Modelos Ollama",
 	"Manage Ollama Models": "Administrar Modelos Ollama",
-	"Manage Pipelines": "Administrar canalizaciones",
-	"Manage Valves": "",
+	"Manage Pipelines": "Administrar Pipelines",
+	"Manage Valves": "Gestionar Valves",
 	"March": "Marzo",
 	"March": "Marzo",
 	"Max Tokens (num_predict)": "Máximo de fichas (num_predict)",
 	"Max Tokens (num_predict)": "Máximo de fichas (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Se pueden descargar un máximo de 3 modelos simultáneamente. Por favor, inténtelo de nuevo más tarde.",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Se pueden descargar un máximo de 3 modelos simultáneamente. Por favor, inténtelo de nuevo más tarde.",
 	"May": "Mayo",
 	"May": "Mayo",
 	"Memories accessible by LLMs will be shown here.": "Las memorias accesibles por los LLMs se mostrarán aquí.",
 	"Memories accessible by LLMs will be shown here.": "Las memorias accesibles por los LLMs se mostrarán aquí.",
 	"Memory": "Memoria",
 	"Memory": "Memoria",
-	"Memory added successfully": "",
-	"Memory cleared successfully": "",
-	"Memory deleted successfully": "",
-	"Memory updated successfully": "",
+	"Memory added successfully": "Memoria añadida correctamente",
+	"Memory cleared successfully": "Memoria liberada correctamente",
+	"Memory deleted successfully": "Memoria borrada correctamente",
+	"Memory updated successfully": "Memoria actualizada correctamente",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de crear su enlace no se compartirán. Los usuarios con el enlace podrán ver el chat compartido.",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de crear su enlace no se compartirán. Los usuarios con el enlace podrán ver el chat compartido.",
 	"Minimum Score": "Puntuación mínima",
 	"Minimum Score": "Puntuación mínima",
 	"Mirostat": "Mirostat",
 	"Mirostat": "Mirostat",
@@ -351,18 +354,18 @@
 	"Mirostat Tau": "Mirostat Tau",
 	"Mirostat Tau": "Mirostat Tau",
 	"MMMM DD, YYYY": "MMMM DD, YYYY",
 	"MMMM DD, YYYY": "MMMM DD, YYYY",
 	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
 	"MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm",
-	"MMMM DD, YYYY hh:mm:ss A": "",
+	"MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A",
 	"Model '{{modelName}}' has been successfully downloaded.": "El modelo '{{modelName}}' se ha descargado correctamente.",
 	"Model '{{modelName}}' has been successfully downloaded.": "El modelo '{{modelName}}' se ha descargado correctamente.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "El modelo '{{modelTag}}' ya está en cola para descargar.",
 	"Model '{{modelTag}}' is already in queue for downloading.": "El modelo '{{modelTag}}' ya está en cola para descargar.",
 	"Model {{modelId}} not found": "El modelo {{modelId}} no fue encontrado",
 	"Model {{modelId}} not found": "El modelo {{modelId}} no fue encontrado",
 	"Model {{modelName}} is not vision capable": "El modelo {{modelName}} no es capaz de ver",
 	"Model {{modelName}} is not vision capable": "El modelo {{modelName}} no es capaz de ver",
 	"Model {{name}} is now {{status}}": "El modelo {{name}} ahora es {{status}}",
 	"Model {{name}} is now {{status}}": "El modelo {{name}} ahora es {{status}}",
-	"Model created successfully!": "",
+	"Model created successfully!": "Modelo creado correctamente!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Se detectó la ruta del sistema de archivos del modelo. Se requiere el nombre corto del modelo para la actualización, no se puede continuar.",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "Se detectó la ruta del sistema de archivos del modelo. Se requiere el nombre corto del modelo para la actualización, no se puede continuar.",
 	"Model ID": "ID del modelo",
 	"Model ID": "ID del modelo",
 	"Model not selected": "Modelo no seleccionado",
 	"Model not selected": "Modelo no seleccionado",
 	"Model Params": "Parámetros del modelo",
 	"Model Params": "Parámetros del modelo",
-	"Model updated successfully": "",
+	"Model updated successfully": "Modelo actualizado correctamente",
 	"Model Whitelisting": "Listado de Modelos habilitados",
 	"Model Whitelisting": "Listado de Modelos habilitados",
 	"Model(s) Whitelisted": "Modelo(s) habilitados",
 	"Model(s) Whitelisted": "Modelo(s) habilitados",
 	"Modelfile Content": "Contenido del Modelfile",
 	"Modelfile Content": "Contenido del Modelfile",
@@ -373,20 +376,20 @@
 	"Name your model": "Asigne un nombre a su modelo",
 	"Name your model": "Asigne un nombre a su modelo",
 	"New Chat": "Nuevo Chat",
 	"New Chat": "Nuevo Chat",
 	"New Password": "Nueva Contraseña",
 	"New Password": "Nueva Contraseña",
-	"No content to speak": "",
-	"No documents found": "",
-	"No file selected": "",
+	"No content to speak": "No hay contenido para hablar",
+	"No documents found": "No se han encontrado documentos",
+	"No file selected": "Ningún archivo fué seleccionado",
 	"No results found": "No se han encontrado resultados",
 	"No results found": "No se han encontrado resultados",
 	"No search query generated": "No se ha generado ninguna consulta de búsqueda",
 	"No search query generated": "No se ha generado ninguna consulta de búsqueda",
 	"No source available": "No hay fuente disponible",
 	"No source available": "No hay fuente disponible",
-	"No valves to update": "",
+	"No valves to update": "No valves para actualizar",
 	"None": "Ninguno",
 	"None": "Ninguno",
 	"Not factually correct": "No es correcto en todos los aspectos",
 	"Not factually correct": "No es correcto en todos los aspectos",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Si estableces una puntuación mínima, la búsqueda sólo devolverá documentos con una puntuación mayor o igual a la puntuación mínima.",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Si estableces una puntuación mínima, la búsqueda sólo devolverá documentos con una puntuación mayor o igual a la puntuación mínima.",
 	"Notifications": "Notificaciones",
 	"Notifications": "Notificaciones",
 	"November": "Noviembre",
 	"November": "Noviembre",
 	"num_thread (Ollama)": "num_thread (Ollama)",
 	"num_thread (Ollama)": "num_thread (Ollama)",
-	"OAuth ID": "",
+	"OAuth ID": "OAuth ID",
 	"October": "Octubre",
 	"October": "Octubre",
 	"Off": "Desactivado",
 	"Off": "Desactivado",
 	"Okay, Let's Go!": "Bien, ¡Vamos!",
 	"Okay, Let's Go!": "Bien, ¡Vamos!",
@@ -394,14 +397,14 @@
 	"Ollama": "Ollama",
 	"Ollama": "Ollama",
 	"Ollama API": "Ollama API",
 	"Ollama API": "Ollama API",
 	"Ollama API disabled": "API de Ollama deshabilitada",
 	"Ollama API disabled": "API de Ollama deshabilitada",
-	"Ollama API is disabled": "",
+	"Ollama API is disabled": "API de Ollama desactivada",
 	"Ollama Version": "Versión de Ollama",
 	"Ollama Version": "Versión de Ollama",
 	"On": "Activado",
 	"On": "Activado",
 	"Only": "Solamente",
 	"Only": "Solamente",
 	"Only alphanumeric characters and hyphens are allowed in the command string.": "Sólo se permiten caracteres alfanuméricos y guiones en la cadena de comando.",
 	"Only alphanumeric characters and hyphens are allowed in the command string.": "Sólo se permiten caracteres alfanuméricos y guiones en la cadena de comando.",
 	"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! ¡Agárrate fuerte! Tus archivos todavía están en el horno de procesamiento. Los estamos cocinando a la perfección. Tenga paciencia y le avisaremos una vez que estén listos.",
 	"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! ¡Agárrate fuerte! Tus archivos todavía están en el horno de procesamiento. Los estamos cocinando a la perfección. Tenga paciencia y le avisaremos una vez que estén listos.",
 	"Oops! Looks like the URL is invalid. Please double-check and try again.": "¡Ups! Parece que la URL no es válida. Vuelva a verificar e inténtelo nuevamente.",
 	"Oops! Looks like the URL is invalid. Please double-check and try again.": "¡Ups! Parece que la URL no es válida. Vuelva a verificar e inténtelo nuevamente.",
-	"Oops! There was an error in the previous response. Please try again or contact admin.": "",
+	"Oops! There was an error in the previous response. Please try again or contact admin.": "¡Oops! Hubo un error en la respuesta anterior. Intente de nuevo o póngase en contacto con el administrador.",
 	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "¡Ups! Estás utilizando un método no compatible (solo frontend). Por favor ejecute la WebUI desde el backend.",
 	"Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "¡Ups! Estás utilizando un método no compatible (solo frontend). Por favor ejecute la WebUI desde el backend.",
 	"Open": "Abrir",
 	"Open": "Abrir",
 	"Open AI (Dall-E)": "Abrir AI (Dall-E)",
 	"Open AI (Dall-E)": "Abrir AI (Dall-E)",
@@ -417,14 +420,14 @@
 	"PDF document (.pdf)": "PDF document (.pdf)",
 	"PDF document (.pdf)": "PDF document (.pdf)",
 	"PDF Extract Images (OCR)": "Extraer imágenes de PDF (OCR)",
 	"PDF Extract Images (OCR)": "Extraer imágenes de PDF (OCR)",
 	"pending": "pendiente",
 	"pending": "pendiente",
-	"Permission denied when accessing media devices": "",
-	"Permission denied when accessing microphone": "",
+	"Permission denied when accessing media devices": "Permiso denegado al acceder a los dispositivos",
+	"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}}",
 	"Permission denied when accessing microphone: {{error}}": "Permiso denegado al acceder al micrófono: {{error}}",
 	"Personalization": "Personalización",
 	"Personalization": "Personalización",
-	"Pipeline deleted successfully": "",
-	"Pipeline downloaded successfully": "",
-	"Pipelines": "Tuberías",
-	"Pipelines Not Detected": "",
+	"Pipeline deleted successfully": "Pipeline borrada exitosamente",
+	"Pipeline downloaded successfully": "Pipeline descargada exitosamente",
+	"Pipelines": "Pipelines",
+	"Pipelines Not Detected": "Pipeline No Detectada",
 	"Pipelines Valves": "Tuberías Válvulas",
 	"Pipelines Valves": "Tuberías Válvulas",
 	"Plain text (.txt)": "Texto plano (.txt)",
 	"Plain text (.txt)": "Texto plano (.txt)",
 	"Playground": "Patio de juegos",
 	"Playground": "Patio de juegos",
@@ -444,7 +447,7 @@
 	"Read Aloud": "Leer al oído",
 	"Read Aloud": "Leer al oído",
 	"Record voice": "Grabar voz",
 	"Record voice": "Grabar voz",
 	"Redirecting you to OpenWebUI Community": "Redireccionándote a la comunidad OpenWebUI",
 	"Redirecting you to OpenWebUI Community": "Redireccionándote a la comunidad OpenWebUI",
-	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "",
+	"Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referirse a usted mismo como \"Usuario\" (por ejemplo, \"El usuario está aprendiendo Español\")",
 	"Refused when it shouldn't have": "Rechazado cuando no debería",
 	"Refused when it shouldn't have": "Rechazado cuando no debería",
 	"Regenerate": "Regenerar",
 	"Regenerate": "Regenerar",
 	"Release Notes": "Notas de la versión",
 	"Release Notes": "Notas de la versión",
@@ -456,16 +459,16 @@
 	"Reranking Model": "Modelo de reranking",
 	"Reranking Model": "Modelo de reranking",
 	"Reranking model disabled": "Modelo de reranking deshabilitado",
 	"Reranking model disabled": "Modelo de reranking deshabilitado",
 	"Reranking model set to \"{{reranking_model}}\"": "Modelo de reranking establecido en \"{{reranking_model}}\"",
 	"Reranking model set to \"{{reranking_model}}\"": "Modelo de reranking establecido en \"{{reranking_model}}\"",
-	"Reset": "",
-	"Reset Upload Directory": "",
+	"Reset": "Reiniciar",
+	"Reset Upload Directory": "Reiniciar Directorio de carga",
 	"Reset Vector Storage": "Restablecer almacenamiento vectorial",
 	"Reset Vector Storage": "Restablecer almacenamiento vectorial",
 	"Response AutoCopy to Clipboard": "Copiar respuesta automáticamente al portapapeles",
 	"Response AutoCopy to Clipboard": "Copiar respuesta automáticamente al portapapeles",
-	"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.": "Las notificaciones de respuesta no pueden activarse debido a que los permisos del sitio web han sido denegados. Por favor, visite las configuraciones de su navegador para otorgar el acceso necesario.",
 	"Role": "Rol",
 	"Role": "Rol",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"RTL": "RTL",
 	"RTL": "RTL",
-	"Running": "",
+	"Running": "Ejecutando",
 	"Save": "Guardar",
 	"Save": "Guardar",
 	"Save & Create": "Guardar y Crear",
 	"Save & Create": "Guardar y Crear",
 	"Save & Update": "Guardar y Actualizar",
 	"Save & Update": "Guardar y Actualizar",
@@ -477,40 +480,40 @@
 	"Search a model": "Buscar un modelo",
 	"Search a model": "Buscar un modelo",
 	"Search Chats": "Chats de búsqueda",
 	"Search Chats": "Chats de búsqueda",
 	"Search Documents": "Buscar Documentos",
 	"Search Documents": "Buscar Documentos",
-	"Search Functions": "",
+	"Search Functions": "Funciones de Búsqueda",
 	"Search Models": "Modelos de búsqueda",
 	"Search Models": "Modelos de búsqueda",
 	"Search Prompts": "Buscar Prompts",
 	"Search Prompts": "Buscar Prompts",
-	"Search Query Generation Prompt": "",
-	"Search Query Generation Prompt Length Threshold": "",
+	"Search Query Generation Prompt": "Búsqueda de consulta de generación de prompts",
+	"Search Query Generation Prompt Length Threshold": "Nivel de longitud de Búsqueda de consulta de generación de prompts",
 	"Search Result Count": "Recuento de resultados de búsqueda",
 	"Search Result Count": "Recuento de resultados de búsqueda",
-	"Search Tools": "",
+	"Search Tools": "Búsqueda de herramientas",
 	"Searched {{count}} sites_one": "Buscado {{count}} sites_one",
 	"Searched {{count}} sites_one": "Buscado {{count}} sites_one",
 	"Searched {{count}} sites_many": "Buscado {{count}} sites_many",
 	"Searched {{count}} sites_many": "Buscado {{count}} sites_many",
 	"Searched {{count}} sites_other": "Buscó {{count}} sites_other",
 	"Searched {{count}} sites_other": "Buscó {{count}} sites_other",
-	"Searching \"{{searchQuery}}\"": "",
+	"Searching \"{{searchQuery}}\"": "Buscando \"{{searchQuery}}\"",
 	"Searxng Query URL": "Searxng URL de consulta",
 	"Searxng Query URL": "Searxng URL de consulta",
 	"See readme.md for instructions": "Vea el readme.md para instrucciones",
 	"See readme.md for instructions": "Vea el readme.md para instrucciones",
 	"See what's new": "Ver las novedades",
 	"See what's new": "Ver las novedades",
 	"Seed": "Seed",
 	"Seed": "Seed",
 	"Select a base model": "Seleccionar un modelo base",
 	"Select a base model": "Seleccionar un modelo base",
-	"Select a engine": "",
-	"Select a function": "",
+	"Select a engine": "Busca un motor",
+	"Select a function": "Busca una función",
 	"Select a mode": "Selecciona un modo",
 	"Select a mode": "Selecciona un modo",
 	"Select a model": "Selecciona un modelo",
 	"Select a model": "Selecciona un modelo",
-	"Select a pipeline": "Selección de una canalización",
-	"Select a pipeline url": "Selección de una dirección URL de canalización",
-	"Select a tool": "",
+	"Select a pipeline": "Selección de una Pipeline",
+	"Select a pipeline url": "Selección de una dirección URL de Pipeline",
+	"Select a tool": "Busca una herramienta",
 	"Select an Ollama instance": "Seleccione una instancia de Ollama",
 	"Select an Ollama instance": "Seleccione una instancia de Ollama",
-	"Select Documents": "",
+	"Select Documents": "Seleccionar Documentos",
 	"Select model": "Selecciona un modelo",
 	"Select model": "Selecciona un modelo",
-	"Select only one model to call": "",
+	"Select only one model to call": "Selecciona sólo un modelo para llamar",
 	"Selected model(s) do not support image inputs": "Los modelos seleccionados no admiten entradas de imagen",
 	"Selected model(s) do not support image inputs": "Los modelos seleccionados no admiten entradas de imagen",
 	"Send": "Enviar",
 	"Send": "Enviar",
 	"Send a Message": "Enviar un Mensaje",
 	"Send a Message": "Enviar un Mensaje",
 	"Send message": "Enviar Mensaje",
 	"Send message": "Enviar Mensaje",
 	"September": "Septiembre",
 	"September": "Septiembre",
 	"Serper API Key": "Clave API de Serper",
 	"Serper API Key": "Clave API de Serper",
-	"Serply API Key": "",
+	"Serply API Key": "Clave API de Serply",
 	"Serpstack API Key": "Clave API de Serpstack",
 	"Serpstack API Key": "Clave API de Serpstack",
 	"Server connection verified": "Conexión del servidor verificada",
 	"Server connection verified": "Conexión del servidor verificada",
 	"Set as default": "Establecer por defecto",
 	"Set as default": "Establecer por defecto",
@@ -522,18 +525,18 @@
 	"Set Task Model": "Establecer modelo de tarea",
 	"Set Task Model": "Establecer modelo de tarea",
 	"Set Voice": "Establecer la voz",
 	"Set Voice": "Establecer la voz",
 	"Settings": "Configuración",
 	"Settings": "Configuración",
-	"Settings saved successfully!": "¡Configuración guardada exitosamente!",
-	"Settings updated successfully": "",
+	"Settings saved successfully!": "¡Configuración guardada con éxito!",
+	"Settings updated successfully": "¡Configuración actualizada con éxito!",
 	"Share": "Compartir",
 	"Share": "Compartir",
 	"Share Chat": "Compartir Chat",
 	"Share Chat": "Compartir Chat",
 	"Share to OpenWebUI Community": "Compartir con la comunidad OpenWebUI",
 	"Share to OpenWebUI Community": "Compartir con la comunidad OpenWebUI",
 	"short-summary": "resumen-corto",
 	"short-summary": "resumen-corto",
 	"Show": "Mostrar",
 	"Show": "Mostrar",
-	"Show Admin Details in Account Pending Overlay": "",
-	"Show Model": "",
+	"Show Admin Details in Account Pending Overlay": "Mostrar detalles de administración en la capa de espera de la cuenta",
+	"Show Model": "Mostrar Modelo",
 	"Show shortcuts": "Mostrar atajos",
 	"Show shortcuts": "Mostrar atajos",
-	"Show your support!": "",
-	"Showcased creativity": "Mostrar creatividad",
+	"Show your support!": "¡Muestra tu apoyo!",
+	"Showcased creativity": "Creatividad mostrada",
 	"sidebar": "barra lateral",
 	"sidebar": "barra lateral",
 	"Sign in": "Iniciar sesión",
 	"Sign in": "Iniciar sesión",
 	"Sign Out": "Cerrar sesión",
 	"Sign Out": "Cerrar sesión",
@@ -543,7 +546,7 @@
 	"Speech recognition error: {{error}}": "Error de reconocimiento de voz: {{error}}",
 	"Speech recognition error: {{error}}": "Error de reconocimiento de voz: {{error}}",
 	"Speech-to-Text Engine": "Motor de voz a texto",
 	"Speech-to-Text Engine": "Motor de voz a texto",
 	"Stop Sequence": "Detener secuencia",
 	"Stop Sequence": "Detener secuencia",
-	"STT Model": "",
+	"STT Model": "Modelo STT",
 	"STT Settings": "Configuraciones de STT",
 	"STT Settings": "Configuraciones de STT",
 	"Submit": "Enviar",
 	"Submit": "Enviar",
 	"Subtitle (e.g. about the Roman Empire)": "Subtítulo (por ejemplo, sobre el Imperio Romano)",
 	"Subtitle (e.g. about the Roman Empire)": "Subtítulo (por ejemplo, sobre el Imperio Romano)",
@@ -553,8 +556,8 @@
 	"System": "Sistema",
 	"System": "Sistema",
 	"System Prompt": "Prompt del sistema",
 	"System Prompt": "Prompt del sistema",
 	"Tags": "Etiquetas",
 	"Tags": "Etiquetas",
-	"Tap to interrupt": "",
-	"Tavily API Key": "",
+	"Tap to interrupt": "Toca para interrumpir",
+	"Tavily API Key": "Clave API de Tavily",
 	"Tell us more:": "Dinos más:",
 	"Tell us more:": "Dinos más:",
 	"Temperature": "Temperatura",
 	"Temperature": "Temperatura",
 	"Template": "Plantilla",
 	"Template": "Plantilla",
@@ -564,12 +567,12 @@
 	"Thanks for your feedback!": "¡Gracias por tu retroalimentación!",
 	"Thanks for your feedback!": "¡Gracias por tu retroalimentación!",
 	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "El puntaje debe ser un valor entre 0.0 (0%) y 1.0 (100%).",
 	"The score should be a value between 0.0 (0%) and 1.0 (100%).": "El puntaje debe ser un valor entre 0.0 (0%) y 1.0 (100%).",
 	"Theme": "Tema",
 	"Theme": "Tema",
-	"Thinking...": "",
-	"This action cannot be undone. Do you wish to continue?": "",
+	"Thinking...": "Pensando...",
+	"This action cannot be undone. Do you wish to continue?": "Esta acción no se puede deshacer. ¿Desea continuar?",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Esto garantiza que sus valiosas conversaciones se guarden de forma segura en su base de datos en el backend. ¡Gracias!",
 	"This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Esto garantiza que sus valiosas conversaciones se guarden de forma segura en su base de datos en el backend. ¡Gracias!",
-	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "",
+	"This is an experimental feature, it may not function as expected and is subject to change at any time.": "Esta es una característica experimental que puede no funcionar como se esperaba y está sujeto a cambios en cualquier momento.",
 	"This setting does not sync across browsers or devices.": "Esta configuración no se sincroniza entre navegadores o dispositivos.",
 	"This setting does not sync across browsers or devices.": "Esta configuración no se sincroniza entre navegadores o dispositivos.",
-	"This will delete": "",
+	"This will delete": "Esto eliminará",
 	"Thorough explanation": "Explicación exhaustiva",
 	"Thorough explanation": "Explicación exhaustiva",
 	"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.",
 	"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": "Título",
@@ -580,39 +583,39 @@
 	"to": "para",
 	"to": "para",
 	"To access the available model names for downloading,": "Para acceder a los nombres de modelos disponibles para descargar,",
 	"To access the available model names for downloading,": "Para acceder a los nombres de modelos disponibles para descargar,",
 	"To access the GGUF models available for downloading,": "Para acceder a los modelos GGUF disponibles para descargar,",
 	"To access the GGUF models available for downloading,": "Para acceder a los modelos GGUF disponibles para descargar,",
-	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "",
-	"To add documents here, upload them to the \"Documents\" workspace first.": "",
+	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Para acceder al interfaz de usuario web, por favor contacte al administrador. Los administradores pueden administrar los estados de los usuarios desde el panel de administración.",
+	"To add documents here, upload them to the \"Documents\" workspace first.": "Para agregar documentos aquí, subalos al área de trabajo \"Documentos\" primero.",
 	"to chat input.": "a la entrada del chat.",
 	"to chat input.": "a la entrada del chat.",
-	"To select filters here, add them to the \"Functions\" workspace first.": "",
-	"To select toolkits here, add them to the \"Tools\" workspace first.": "",
+	"To select filters here, add them to the \"Functions\" workspace first.": "Para seleccionar filtros aquí, agreguelos al área de trabajo \"Funciones\" primero.",
+	"To select toolkits here, add them to the \"Tools\" workspace first.": "Para seleccionar herramientas aquí, agreguelas al área de trabajo \"Herramientas\" primero.",
 	"Today": "Hoy",
 	"Today": "Hoy",
 	"Toggle settings": "Alternar configuración",
 	"Toggle settings": "Alternar configuración",
 	"Toggle sidebar": "Alternar barra lateral",
 	"Toggle sidebar": "Alternar barra lateral",
-	"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)": "Tokens a mantener en el contexto de actualización (num_keep)",
+	"Tool created successfully": "Herramienta creada con éxito",
+	"Tool deleted successfully": "Herramienta eliminada con éxito",
+	"Tool imported successfully": "Herramienta importada con éxito",
+	"Tool updated successfully": "Herramienta actualizada con éxito",
+	"Tools": "Herramientas",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",
 	"Trouble accessing Ollama?": "¿Problemas para acceder a Ollama?",
 	"Trouble accessing Ollama?": "¿Problemas para acceder a Ollama?",
-	"TTS Model": "",
+	"TTS Model": "Modelo TTS",
 	"TTS Settings": "Configuración de TTS",
 	"TTS Settings": "Configuración de TTS",
-	"TTS Voice": "",
+	"TTS Voice": "Voz del TTS",
 	"Type": "Tipo",
 	"Type": "Tipo",
 	"Type Hugging Face Resolve (Download) URL": "Escriba la URL (Descarga) de Hugging Face Resolve",
 	"Type Hugging Face Resolve (Download) URL": "Escriba la URL (Descarga) de Hugging Face Resolve",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "¡Uh oh! Hubo un problema al conectarse a {{provider}}.",
 	"Uh-oh! There was an issue connecting to {{provider}}.": "¡Uh oh! Hubo un problema al conectarse a {{provider}}.",
-	"UI": "",
-	"Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "",
-	"Update": "",
+	"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.",
+	"Update": "Actualizar",
 	"Update and Copy Link": "Actualizar y copiar enlace",
 	"Update and Copy Link": "Actualizar y copiar enlace",
 	"Update password": "Actualizar contraseña",
 	"Update password": "Actualizar contraseña",
-	"Updated at": "",
-	"Upload": "",
+	"Updated at": "Actualizado en",
+	"Upload": "Subir",
 	"Upload a GGUF model": "Subir un modelo GGUF",
 	"Upload a GGUF model": "Subir un modelo GGUF",
 	"Upload Files": "Subir archivos",
 	"Upload Files": "Subir archivos",
-	"Upload Pipeline": "",
+	"Upload Pipeline": "Subir Pipeline",
 	"Upload Progress": "Progreso de carga",
 	"Upload Progress": "Progreso de carga",
 	"URL Mode": "Modo de URL",
 	"URL Mode": "Modo de URL",
 	"Use '#' in the prompt input to load and select your documents.": "Utilice '#' en el prompt para cargar y seleccionar sus documentos.",
 	"Use '#' in the prompt input to load and select your documents.": "Utilice '#' en el prompt para cargar y seleccionar sus documentos.",
@@ -621,22 +624,22 @@
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "usuario",
 	"user": "usuario",
-	"User location successfully retrieved.": "",
+	"User location successfully retrieved.": "Localización del usuario recuperada con éxito.",
 	"User Permissions": "Permisos de usuario",
 	"User Permissions": "Permisos de usuario",
 	"Users": "Usuarios",
 	"Users": "Usuarios",
 	"Utilize": "Utilizar",
 	"Utilize": "Utilizar",
 	"Valid time units:": "Unidades válidas de tiempo:",
 	"Valid time units:": "Unidades válidas de tiempo:",
-	"Valves": "",
-	"Valves updated": "",
-	"Valves updated successfully": "",
+	"Valves": "Valves",
+	"Valves updated": "Valves actualizados",
+	"Valves updated successfully": "Valves actualizados con éxito",
 	"variable": "variable",
 	"variable": "variable",
 	"variable to have them replaced with clipboard content.": "variable para reemplazarlos con el contenido del portapapeles.",
 	"variable to have them replaced with clipboard content.": "variable para reemplazarlos con el contenido del portapapeles.",
 	"Version": "Versión",
 	"Version": "Versión",
-	"Voice": "",
+	"Voice": "Voz",
 	"Warning": "Advertencia",
 	"Warning": "Advertencia",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Advertencia: Si actualiza o cambia su modelo de inserción, necesitará volver a importar todos los documentos.",
 	"Warning: If you update or change your embedding model, you will need to re-import all documents.": "Advertencia: Si actualiza o cambia su modelo de inserción, necesitará volver a importar todos los documentos.",
 	"Web": "Web",
 	"Web": "Web",
-	"Web API": "",
+	"Web API": "API Web",
 	"Web Loader Settings": "Web Loader Settings",
 	"Web Loader Settings": "Web Loader Settings",
 	"Web Params": "Web Params",
 	"Web Params": "Web Params",
 	"Web Search": "Búsqueda en la Web",
 	"Web Search": "Búsqueda en la Web",
@@ -646,20 +649,20 @@
 	"WebUI will make requests to": "WebUI realizará solicitudes a",
 	"WebUI will make requests to": "WebUI realizará solicitudes a",
 	"What’s New in": "Novedades en",
 	"What’s New in": "Novedades en",
 	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Cuando el historial está desactivado, los nuevos chats en este navegador no aparecerán en el historial de ninguno de sus dispositivos..",
 	"When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Cuando el historial está desactivado, los nuevos chats en este navegador no aparecerán en el historial de ninguno de sus dispositivos..",
-	"Whisper (Local)": "",
-	"Widescreen Mode": "",
+	"Whisper (Local)": "Whisper (Local)",
+	"Widescreen Mode": "Modo de pantalla ancha",
 	"Workspace": "Espacio de trabajo",
 	"Workspace": "Espacio de trabajo",
 	"Write a prompt suggestion (e.g. Who are you?)": "Escribe una sugerencia para un prompt (por ejemplo, ¿quién eres?)",
 	"Write a prompt suggestion (e.g. Who are you?)": "Escribe una sugerencia para un prompt (por ejemplo, ¿quién eres?)",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Escribe un resumen en 50 palabras que resuma [tema o palabra clave].",
 	"Write a summary in 50 words that summarizes [topic or keyword].": "Escribe un resumen en 50 palabras que resuma [tema o palabra clave].",
 	"Yesterday": "Ayer",
 	"Yesterday": "Ayer",
 	"You": "Usted",
 	"You": "Usted",
-	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "",
+	"You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Puede personalizar sus interacciones con LLMs añadiendo memorias a través del botón 'Gestionar' debajo, haciendo que sean más útiles y personalizados para usted.",
 	"You cannot clone a base model": "No se puede clonar un modelo base",
 	"You cannot clone a base model": "No se puede clonar un modelo base",
 	"You have no archived conversations.": "No tiene conversaciones archivadas.",
 	"You have no archived conversations.": "No tiene conversaciones archivadas.",
 	"You have shared this chat": "Usted ha compartido esta conversación",
 	"You have shared this chat": "Usted ha compartido esta conversación",
 	"You're a helpful assistant.": "Usted es un asistente útil.",
 	"You're a helpful assistant.": "Usted es un asistente útil.",
 	"You're now logged in.": "Usted ahora está conectado.",
 	"You're now logged in.": "Usted ahora está conectado.",
-	"Your account status is currently pending activation.": "",
+	"Your account status is currently pending activation.": "El estado de su cuenta actualmente se encuentra pendiente de activación.",
 	"Youtube": "Youtube",
 	"Youtube": "Youtube",
 	"Youtube Loader Settings": "Configuración del cargador de Youtube"
 	"Youtube Loader Settings": "Configuración del cargador de Youtube"
 }
 }

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "حالت فایل",
 	"File Mode": "حالت فایل",
 	"File not found.": "فایل یافت نشد.",
 	"File not found.": "فایل یافت نشد.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "فانگ سرفیس شناسایی شد: نمی توان از نمایه شما به عنوان آواتار استفاده کرد. پیش فرض به عکس پروفایل پیش فرض برگشت داده شد.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "فانگ سرفیس شناسایی شد: نمی توان از نمایه شما به عنوان آواتار استفاده کرد. پیش فرض به عکس پروفایل پیش فرض برگشت داده شد.",
 	"Fluidly stream large external response chunks": "تکه های پاسخ خارجی بزرگ را به صورت سیال پخش کنید",
 	"Fluidly stream large external response chunks": "تکه های پاسخ خارجی بزرگ را به صورت سیال پخش کنید",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "در حال تولید پرسوجوی جستجو",
 	"Generating search query": "در حال تولید پرسوجوی جستجو",
 	"Generation Info": "اطلاعات تولید",
 	"Generation Info": "اطلاعات تولید",
+	"Global": "",
 	"Good Response": "پاسخ خوب",
 	"Good Response": "پاسخ خوب",
 	"Google PSE API Key": "گوگل PSE API کلید",
 	"Google PSE API Key": "گوگل PSE API کلید",
 	"Google PSE Engine Id": "شناسه موتور PSE گوگل",
 	"Google PSE Engine Id": "شناسه موتور PSE گوگل",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Tiedostotila",
 	"File Mode": "Tiedostotila",
 	"File not found.": "Tiedostoa ei löytynyt.",
 	"File not found.": "Tiedostoa ei löytynyt.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Sormenjäljen väärentäminen havaittu: Ei voi käyttää alkukirjaimia avatarina. Käytetään oletusprofiilikuvaa.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Sormenjäljen väärentäminen havaittu: Ei voi käyttää alkukirjaimia avatarina. Käytetään oletusprofiilikuvaa.",
 	"Fluidly stream large external response chunks": "Virtaa suuria ulkoisia vastausosia joustavasti",
 	"Fluidly stream large external response chunks": "Virtaa suuria ulkoisia vastausosia joustavasti",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Hakukyselyn luominen",
 	"Generating search query": "Hakukyselyn luominen",
 	"Generation Info": "Generointitiedot",
 	"Generation Info": "Generointitiedot",
+	"Global": "",
 	"Good Response": "Hyvä vastaus",
 	"Good Response": "Hyvä vastaus",
 	"Google PSE API Key": "Google PSE API -avain",
 	"Google PSE API Key": "Google PSE API -avain",
 	"Google PSE Engine Id": "Google PSE -moduulin tunnus",
 	"Google PSE Engine Id": "Google PSE -moduulin tunnus",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Mode fichier",
 	"File Mode": "Mode fichier",
 	"File not found.": "Fichier introuvable.",
 	"File not found.": "Fichier introuvable.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Détection de falsification de empreinte digitale\u00a0: impossible d'utiliser les initiales comme avatar. Par défaut, l'image de profil par défaut est utilisée.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Détection de falsification de empreinte digitale\u00a0: impossible d'utiliser les initiales comme avatar. Par défaut, l'image de profil par défaut est utilisée.",
 	"Fluidly stream large external response chunks": "Diffusez de manière fluide de gros morceaux de réponses externes",
 	"Fluidly stream large external response chunks": "Diffusez de manière fluide de gros morceaux de réponses externes",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Génération d’une requête de recherche",
 	"Generating search query": "Génération d’une requête de recherche",
 	"Generation Info": "Informations de génération",
 	"Generation Info": "Informations de génération",
+	"Global": "",
 	"Good Response": "Bonne réponse",
 	"Good Response": "Bonne réponse",
 	"Google PSE API Key": "Clé d’API Google PSE",
 	"Google PSE API Key": "Clé d’API Google PSE",
 	"Google PSE Engine Id": "Id du moteur Google PSE",
 	"Google PSE Engine Id": "Id du moteur Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Mode Fichier",
 	"File Mode": "Mode Fichier",
 	"File not found.": "Fichier non trouvé.",
 	"File not found.": "Fichier non trouvé.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Usurpation d'empreinte digitale détectée : Impossible d'utiliser les initiales comme avatar. L'image de profil par défaut sera utilisée.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Usurpation d'empreinte digitale détectée : Impossible d'utiliser les initiales comme avatar. L'image de profil par défaut sera utilisée.",
 	"Fluidly stream large external response chunks": "Diffusez de manière fluide de gros morceaux de réponses externes",
 	"Fluidly stream large external response chunks": "Diffusez de manière fluide de gros morceaux de réponses externes",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Génération d’une requête de recherche",
 	"Generating search query": "Génération d’une requête de recherche",
 	"Generation Info": "Informations de la Génération",
 	"Generation Info": "Informations de la Génération",
+	"Global": "",
 	"Good Response": "Bonne Réponse",
 	"Good Response": "Bonne Réponse",
 	"Google PSE API Key": "Clé API Google PSE",
 	"Google PSE API Key": "Clé API Google PSE",
 	"Google PSE Engine Id": "ID du moteur Google PSE",
 	"Google PSE Engine Id": "ID du moteur Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "מצב קובץ",
 	"File Mode": "מצב קובץ",
 	"File not found.": "הקובץ לא נמצא.",
 	"File not found.": "הקובץ לא נמצא.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "התגלתה הזיית טביעת אצבע: לא ניתן להשתמש בראשי תיבות כאווטאר. משתמש בתמונת פרופיל ברירת מחדל.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "התגלתה הזיית טביעת אצבע: לא ניתן להשתמש בראשי תיבות כאווטאר. משתמש בתמונת פרופיל ברירת מחדל.",
 	"Fluidly stream large external response chunks": "שידור נתונים חיצוניים בקצב רציף",
 	"Fluidly stream large external response chunks": "שידור נתונים חיצוניים בקצב רציף",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "יצירת שאילתת חיפוש",
 	"Generating search query": "יצירת שאילתת חיפוש",
 	"Generation Info": "מידע על היצירה",
 	"Generation Info": "מידע על היצירה",
+	"Global": "",
 	"Good Response": "תגובה טובה",
 	"Good Response": "תגובה טובה",
 	"Google PSE API Key": "מפתח API של Google PSE",
 	"Google PSE API Key": "מפתח API של Google PSE",
 	"Google PSE Engine Id": "מזהה מנוע PSE של Google",
 	"Google PSE Engine Id": "מזהה מנוע PSE של Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "फ़ाइल मोड",
 	"File Mode": "फ़ाइल मोड",
 	"File not found.": "फ़ाइल प्राप्त नहीं हुई।",
 	"File not found.": "फ़ाइल प्राप्त नहीं हुई।",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "फ़िंगरप्रिंट स्पूफ़िंग का पता चला: प्रारंभिक अक्षरों को अवतार के रूप में उपयोग करने में असमर्थ। प्रोफ़ाइल छवि को डिफ़ॉल्ट पर डिफ़ॉल्ट किया जा रहा है.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "फ़िंगरप्रिंट स्पूफ़िंग का पता चला: प्रारंभिक अक्षरों को अवतार के रूप में उपयोग करने में असमर्थ। प्रोफ़ाइल छवि को डिफ़ॉल्ट पर डिफ़ॉल्ट किया जा रहा है.",
 	"Fluidly stream large external response chunks": "बड़े बाह्य प्रतिक्रिया खंडों को तरल रूप से प्रवाहित करें",
 	"Fluidly stream large external response chunks": "बड़े बाह्य प्रतिक्रिया खंडों को तरल रूप से प्रवाहित करें",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "खोज क्वेरी जनरेट करना",
 	"Generating search query": "खोज क्वेरी जनरेट करना",
 	"Generation Info": "जनरेशन की जानकारी",
 	"Generation Info": "जनरेशन की जानकारी",
+	"Global": "",
 	"Good Response": "अच्छी प्रतिक्रिया",
 	"Good Response": "अच्छी प्रतिक्रिया",
 	"Google PSE API Key": "Google PSE API कुंजी",
 	"Google PSE API Key": "Google PSE API कुंजी",
 	"Google PSE Engine Id": "Google PSE इंजन आईडी",
 	"Google PSE Engine Id": "Google PSE इंजन आईडी",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Način datoteke",
 	"File Mode": "Način datoteke",
 	"File not found.": "Datoteka nije pronađena.",
 	"File not found.": "Datoteka nije pronađena.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Otkriveno krivotvorenje otisaka prstiju: Nemoguće je koristiti inicijale kao avatar. Postavljanje na zadanu profilnu sliku.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Otkriveno krivotvorenje otisaka prstiju: Nemoguće je koristiti inicijale kao avatar. Postavljanje na zadanu profilnu sliku.",
 	"Fluidly stream large external response chunks": "Glavno strujanje velikih vanjskih dijelova odgovora",
 	"Fluidly stream large external response chunks": "Glavno strujanje velikih vanjskih dijelova odgovora",
@@ -279,6 +281,7 @@
 	"Generate Image": "Gneriraj sliku",
 	"Generate Image": "Gneriraj sliku",
 	"Generating search query": "Generiranje upita za pretraživanje",
 	"Generating search query": "Generiranje upita za pretraživanje",
 	"Generation Info": "Informacije o generaciji",
 	"Generation Info": "Informacije o generaciji",
+	"Global": "",
 	"Good Response": "Dobar odgovor",
 	"Good Response": "Dobar odgovor",
 	"Google PSE API Key": "Google PSE API ključ",
 	"Google PSE API Key": "Google PSE API ključ",
 	"Google PSE Engine Id": "ID Google PSE modula",
 	"Google PSE Engine Id": "ID Google PSE modula",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Modalità file",
 	"File Mode": "Modalità file",
 	"File not found.": "File non trovato.",
 	"File not found.": "File non trovato.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Rilevato spoofing delle impronte digitali: impossibile utilizzare le iniziali come avatar. Ripristino all'immagine del profilo predefinita.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Rilevato spoofing delle impronte digitali: impossibile utilizzare le iniziali come avatar. Ripristino all'immagine del profilo predefinita.",
 	"Fluidly stream large external response chunks": "Trasmetti in modo fluido blocchi di risposta esterni di grandi dimensioni",
 	"Fluidly stream large external response chunks": "Trasmetti in modo fluido blocchi di risposta esterni di grandi dimensioni",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Generazione di query di ricerca",
 	"Generating search query": "Generazione di query di ricerca",
 	"Generation Info": "Informazioni generazione",
 	"Generation Info": "Informazioni generazione",
+	"Global": "",
 	"Good Response": "Buona risposta",
 	"Good Response": "Buona risposta",
 	"Google PSE API Key": "Chiave API PSE di Google",
 	"Google PSE API Key": "Chiave API PSE di Google",
 	"Google PSE Engine Id": "ID motore PSE di Google",
 	"Google PSE Engine Id": "ID motore PSE di Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "ファイルモード",
 	"File Mode": "ファイルモード",
 	"File not found.": "ファイルが見つかりません。",
 	"File not found.": "ファイルが見つかりません。",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "指紋のなりすましが検出されました: イニシャルをアバターとして使用できません。デフォルトのプロファイル画像にデフォルト設定されています。",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "指紋のなりすましが検出されました: イニシャルをアバターとして使用できません。デフォルトのプロファイル画像にデフォルト設定されています。",
 	"Fluidly stream large external response chunks": "大規模な外部応答チャンクを流動的にストリーミングする",
 	"Fluidly stream large external response chunks": "大規模な外部応答チャンクを流動的にストリーミングする",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "検索クエリの生成",
 	"Generating search query": "検索クエリの生成",
 	"Generation Info": "生成情報",
 	"Generation Info": "生成情報",
+	"Global": "",
 	"Good Response": "良い応答",
 	"Good Response": "良い応答",
 	"Google PSE API Key": "Google PSE APIキー",
 	"Google PSE API Key": "Google PSE APIキー",
 	"Google PSE Engine Id": "Google PSE エンジン ID",
 	"Google PSE Engine Id": "Google PSE エンジン ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "ფაილური რეჟიმი",
 	"File Mode": "ფაილური რეჟიმი",
 	"File not found.": "ფაილი ვერ მოიძებნა",
 	"File not found.": "ფაილი ვერ მოიძებნა",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "აღმოჩენილია თითის ანაბეჭდის გაყალბება: ინიციალების გამოყენება ავატარად შეუძლებელია. დეფოლტ პროფილის დეფოლტ სურათი.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "აღმოჩენილია თითის ანაბეჭდის გაყალბება: ინიციალების გამოყენება ავატარად შეუძლებელია. დეფოლტ პროფილის დეფოლტ სურათი.",
 	"Fluidly stream large external response chunks": "თხევადი ნაკადი დიდი გარე საპასუხო ნაწილაკების",
 	"Fluidly stream large external response chunks": "თხევადი ნაკადი დიდი გარე საპასუხო ნაწილაკების",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "საძიებო მოთხოვნის გენერირება",
 	"Generating search query": "საძიებო მოთხოვნის გენერირება",
 	"Generation Info": "გენერაციის ინფორმაცია",
 	"Generation Info": "გენერაციის ინფორმაცია",
+	"Global": "",
 	"Good Response": "დიდი პასუხი",
 	"Good Response": "დიდი პასუხი",
 	"Google PSE API Key": "Google PSE API გასაღები",
 	"Google PSE API Key": "Google PSE API გასაღები",
 	"Google PSE Engine Id": "Google PSE ძრავის Id",
 	"Google PSE Engine Id": "Google PSE ძრავის Id",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "파일 모드",
 	"File Mode": "파일 모드",
 	"File not found.": "파일을 찾을 수 없습니다.",
 	"File not found.": "파일을 찾을 수 없습니다.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint spoofing 감지: 이니셜을 아바타로 사용할 수 없습니다. 기본 프로필 이미지로 설정합니다.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerprint spoofing 감지: 이니셜을 아바타로 사용할 수 없습니다. 기본 프로필 이미지로 설정합니다.",
 	"Fluidly stream large external response chunks": "대규모 외부 응답 청크를 유연하게 스트리밍",
 	"Fluidly stream large external response chunks": "대규모 외부 응답 청크를 유연하게 스트리밍",
@@ -279,6 +281,7 @@
 	"Generate Image": "이미지 생성",
 	"Generate Image": "이미지 생성",
 	"Generating search query": "검색 쿼리 생성",
 	"Generating search query": "검색 쿼리 생성",
 	"Generation Info": "생성 정보",
 	"Generation Info": "생성 정보",
+	"Global": "",
 	"Good Response": "좋은 응답",
 	"Good Response": "좋은 응답",
 	"Google PSE API Key": "Google PSE API 키",
 	"Google PSE API Key": "Google PSE API 키",
 	"Google PSE Engine Id": "Google PSE 엔진 ID",
 	"Google PSE Engine Id": "Google PSE 엔진 ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Dokumentų rėžimas",
 	"File Mode": "Dokumentų rėžimas",
 	"File not found.": "Failas nerastas.",
 	"File not found.": "Failas nerastas.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Nepavyko nsutatyti profilio nuotraukos",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Nepavyko nsutatyti profilio nuotraukos",
 	"Fluidly stream large external response chunks": "Sklandžiai transliuoti ilgus atsakymus",
 	"Fluidly stream large external response chunks": "Sklandžiai transliuoti ilgus atsakymus",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "Generavimo informacija",
 	"Generation Info": "Generavimo informacija",
+	"Global": "",
 	"Good Response": "Geras atsakymas",
 	"Good Response": "Geras atsakymas",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Filmodus",
 	"File Mode": "Filmodus",
 	"File not found.": "Fil ikke funnet.",
 	"File not found.": "Fil ikke funnet.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrykk-spoofing oppdaget: Kan ikke bruke initialer som avatar. Bruker standard profilbilde.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrykk-spoofing oppdaget: Kan ikke bruke initialer som avatar. Bruker standard profilbilde.",
 	"Fluidly stream large external response chunks": "Strøm store eksterne svarchunks flytende",
 	"Fluidly stream large external response chunks": "Strøm store eksterne svarchunks flytende",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Genererer søkeforespørsel",
 	"Generating search query": "Genererer søkeforespørsel",
 	"Generation Info": "Generasjonsinfo",
 	"Generation Info": "Generasjonsinfo",
+	"Global": "",
 	"Good Response": "Godt svar",
 	"Good Response": "Godt svar",
 	"Google PSE API Key": "Google PSE API-nøkkel",
 	"Google PSE API Key": "Google PSE API-nøkkel",
 	"Google PSE Engine Id": "Google PSE Motor-ID",
 	"Google PSE Engine Id": "Google PSE Motor-ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Bestandsmodus",
 	"File Mode": "Bestandsmodus",
 	"File not found.": "Bestand niet gevonden.",
 	"File not found.": "Bestand niet gevonden.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Vingerafdruk spoofing gedetecteerd: kan initialen niet gebruiken als avatar. Standaardprofielafbeelding wordt gebruikt.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Vingerafdruk spoofing gedetecteerd: kan initialen niet gebruiken als avatar. Standaardprofielafbeelding wordt gebruikt.",
 	"Fluidly stream large external response chunks": "Stream vloeiend grote externe responsbrokken",
 	"Fluidly stream large external response chunks": "Stream vloeiend grote externe responsbrokken",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Zoekopdracht genereren",
 	"Generating search query": "Zoekopdracht genereren",
 	"Generation Info": "Generatie Info",
 	"Generation Info": "Generatie Info",
+	"Global": "",
 	"Good Response": "Goede Antwoord",
 	"Good Response": "Goede Antwoord",
 	"Google PSE API Key": "Google PSE API-sleutel",
 	"Google PSE API Key": "Google PSE API-sleutel",
 	"Google PSE Engine Id": "Google PSE-engine-ID",
 	"Google PSE Engine Id": "Google PSE-engine-ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "ਫਾਈਲ ਮੋਡ",
 	"File Mode": "ਫਾਈਲ ਮੋਡ",
 	"File not found.": "ਫਾਈਲ ਨਹੀਂ ਮਿਲੀ।",
 	"File not found.": "ਫਾਈਲ ਨਹੀਂ ਮਿਲੀ।",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਪੂਫਿੰਗ ਪਾਈ ਗਈ: ਅਵਤਾਰ ਵਜੋਂ ਸ਼ੁਰੂਆਤੀ ਅੱਖਰ ਵਰਤਣ ਵਿੱਚ ਅਸਮਰੱਥ। ਮੂਲ ਪ੍ਰੋਫਾਈਲ ਚਿੱਤਰ 'ਤੇ ਡਿਫਾਲਟ।",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "ਫਿੰਗਰਪ੍ਰਿੰਟ ਸਪੂਫਿੰਗ ਪਾਈ ਗਈ: ਅਵਤਾਰ ਵਜੋਂ ਸ਼ੁਰੂਆਤੀ ਅੱਖਰ ਵਰਤਣ ਵਿੱਚ ਅਸਮਰੱਥ। ਮੂਲ ਪ੍ਰੋਫਾਈਲ ਚਿੱਤਰ 'ਤੇ ਡਿਫਾਲਟ।",
 	"Fluidly stream large external response chunks": "ਵੱਡੇ ਬਾਹਰੀ ਜਵਾਬ ਚੰਕਾਂ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਸਟ੍ਰੀਮ ਕਰੋ",
 	"Fluidly stream large external response chunks": "ਵੱਡੇ ਬਾਹਰੀ ਜਵਾਬ ਚੰਕਾਂ ਨੂੰ ਸਹੀ ਢੰਗ ਨਾਲ ਸਟ੍ਰੀਮ ਕਰੋ",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "ਖੋਜ ਪੁੱਛਗਿੱਛ ਤਿਆਰ ਕਰਨਾ",
 	"Generating search query": "ਖੋਜ ਪੁੱਛਗਿੱਛ ਤਿਆਰ ਕਰਨਾ",
 	"Generation Info": "ਜਨਰੇਸ਼ਨ ਜਾਣਕਾਰੀ",
 	"Generation Info": "ਜਨਰੇਸ਼ਨ ਜਾਣਕਾਰੀ",
+	"Global": "",
 	"Good Response": "ਵਧੀਆ ਜਵਾਬ",
 	"Good Response": "ਵਧੀਆ ਜਵਾਬ",
 	"Google PSE API Key": "Google PSE API ਕੁੰਜੀ",
 	"Google PSE API Key": "Google PSE API ਕੁੰਜੀ",
 	"Google PSE Engine Id": "ਗੂਗਲ PSE ਇੰਜਣ ID",
 	"Google PSE Engine Id": "ਗੂਗਲ PSE ਇੰਜਣ ID",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Tryb pliku",
 	"File Mode": "Tryb pliku",
 	"File not found.": "Plik nie został znaleziony.",
 	"File not found.": "Plik nie został znaleziony.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Wykryto podszywanie się pod odcisk palca: Nie można używać inicjałów jako awatara. Przechodzenie do domyślnego obrazu profilowego.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Wykryto podszywanie się pod odcisk palca: Nie można używać inicjałów jako awatara. Przechodzenie do domyślnego obrazu profilowego.",
 	"Fluidly stream large external response chunks": "Płynnie przesyłaj strumieniowo duże fragmenty odpowiedzi zewnętrznych",
 	"Fluidly stream large external response chunks": "Płynnie przesyłaj strumieniowo duże fragmenty odpowiedzi zewnętrznych",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Generowanie zapytania",
 	"Generating search query": "Generowanie zapytania",
 	"Generation Info": "Informacja o generacji",
 	"Generation Info": "Informacja o generacji",
+	"Global": "",
 	"Good Response": "Dobra odpowiedź",
 	"Good Response": "Dobra odpowiedź",
 	"Google PSE API Key": "Klucz API Google PSE",
 	"Google PSE API Key": "Klucz API Google PSE",
 	"Google PSE Engine Id": "Identyfikator silnika Google PSE",
 	"Google PSE Engine Id": "Identyfikator silnika Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Modo de Arquivo",
 	"File Mode": "Modo de Arquivo",
 	"File not found.": "Arquivo não encontrado.",
 	"File not found.": "Arquivo não encontrado.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Impostação de impressão digital detectada: Não é possível usar iniciais como avatar. Padronizando para imagem de perfil padrão.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Impostação de impressão digital detectada: Não é possível usar iniciais como avatar. Padronizando para imagem de perfil padrão.",
 	"Fluidly stream large external response chunks": "Transmita com fluidez grandes blocos de resposta externa",
 	"Fluidly stream large external response chunks": "Transmita com fluidez grandes blocos de resposta externa",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Gerando consulta de pesquisa",
 	"Generating search query": "Gerando consulta de pesquisa",
 	"Generation Info": "Informações de Geração",
 	"Generation Info": "Informações de Geração",
+	"Global": "",
 	"Good Response": "Boa Resposta",
 	"Good Response": "Boa Resposta",
 	"Google PSE API Key": "Chave de API PSE do Google",
 	"Google PSE API Key": "Chave de API PSE do Google",
 	"Google PSE Engine Id": "ID do mecanismo PSE do Google",
 	"Google PSE Engine Id": "ID do mecanismo PSE do Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Modo de Ficheiro",
 	"File Mode": "Modo de Ficheiro",
 	"File not found.": "Ficheiro não encontrado.",
 	"File not found.": "Ficheiro não encontrado.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Detectada falsificação da impressão digital: Não é possível usar iniciais como avatar. A usar a imagem de perfil padrão.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Detectada falsificação da impressão digital: Não é possível usar iniciais como avatar. A usar a imagem de perfil padrão.",
 	"Fluidly stream large external response chunks": "Transmita com fluidez grandes blocos de resposta externa",
 	"Fluidly stream large external response chunks": "Transmita com fluidez grandes blocos de resposta externa",
@@ -279,6 +281,7 @@
 	"Generate Image": "Gerar imagem",
 	"Generate Image": "Gerar imagem",
 	"Generating search query": "A gerar a consulta da pesquisa",
 	"Generating search query": "A gerar a consulta da pesquisa",
 	"Generation Info": "Informações de Geração",
 	"Generation Info": "Informações de Geração",
+	"Global": "",
 	"Good Response": "Boa Resposta",
 	"Good Response": "Boa Resposta",
 	"Google PSE API Key": "Chave da API PSE do Google",
 	"Google PSE API Key": "Chave da API PSE do Google",
 	"Google PSE Engine Id": "ID do mecanismo PSE do Google",
 	"Google PSE Engine Id": "ID do mecanismo PSE do Google",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Режим файла",
 	"File Mode": "Режим файла",
 	"File not found.": "Файл не найден.",
 	"File not found.": "Файл не найден.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Определение подделки отпечатка: Невозможно использовать инициалы в качестве аватара. По умолчанию используется изображение профиля по умолчанию.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Определение подделки отпечатка: Невозможно использовать инициалы в качестве аватара. По умолчанию используется изображение профиля по умолчанию.",
 	"Fluidly stream large external response chunks": "Плавная потоковая передача больших фрагментов внешних ответов",
 	"Fluidly stream large external response chunks": "Плавная потоковая передача больших фрагментов внешних ответов",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Генерация поискового запроса",
 	"Generating search query": "Генерация поискового запроса",
 	"Generation Info": "Информация о генерации",
 	"Generation Info": "Информация о генерации",
+	"Global": "",
 	"Good Response": "Хороший ответ",
 	"Good Response": "Хороший ответ",
 	"Google PSE API Key": "Ключ API Google PSE",
 	"Google PSE API Key": "Ключ API Google PSE",
 	"Google PSE Engine Id": "Идентификатор движка Google PSE",
 	"Google PSE Engine Id": "Идентификатор движка Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Режим датотеке",
 	"File Mode": "Режим датотеке",
 	"File not found.": "Датотека није пронађена.",
 	"File not found.": "Датотека није пронађена.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Откривено лажно представљање отиска прста: Немогуће је користити иницијале као аватар. Прелазак на подразумевану профилну слику.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Откривено лажно представљање отиска прста: Немогуће је користити иницијале као аватар. Прелазак на подразумевану профилну слику.",
 	"Fluidly stream large external response chunks": "Течно стримујте велике спољне делове одговора",
 	"Fluidly stream large external response chunks": "Течно стримујте велике спољне делове одговора",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Генерисање упита претраге",
 	"Generating search query": "Генерисање упита претраге",
 	"Generation Info": "Информације о стварању",
 	"Generation Info": "Информације о стварању",
+	"Global": "",
 	"Good Response": "Добар одговор",
 	"Good Response": "Добар одговор",
 	"Google PSE API Key": "Гоогле ПСЕ АПИ кључ",
 	"Google PSE API Key": "Гоогле ПСЕ АПИ кључ",
 	"Google PSE Engine Id": "Гоогле ПСЕ ИД мотора",
 	"Google PSE Engine Id": "Гоогле ПСЕ ИД мотора",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Fil-läge",
 	"File Mode": "Fil-läge",
 	"File not found.": "Fil hittades inte.",
 	"File not found.": "Fil hittades inte.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrycksmanipulering upptäckt: Kan inte använda initialer som avatar. Återställning till standardprofilbild.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingeravtrycksmanipulering upptäckt: Kan inte använda initialer som avatar. Återställning till standardprofilbild.",
 	"Fluidly stream large external response chunks": "Strömma flytande stora externa svarschunks",
 	"Fluidly stream large external response chunks": "Strömma flytande stora externa svarschunks",
@@ -279,6 +281,7 @@
 	"Generate Image": "Generera bild",
 	"Generate Image": "Generera bild",
 	"Generating search query": "Genererar sökfråga",
 	"Generating search query": "Genererar sökfråga",
 	"Generation Info": "Info om generation",
 	"Generation Info": "Info om generation",
+	"Global": "",
 	"Good Response": "Bra svar",
 	"Good Response": "Bra svar",
 	"Google PSE API Key": "Google PSE API-nyckel",
 	"Google PSE API Key": "Google PSE API-nyckel",
 	"Google PSE Engine Id": "Google PSE Engine Id",
 	"Google PSE Engine Id": "Google PSE Engine Id",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "",
 	"File Mode": "",
 	"File not found.": "",
 	"File not found.": "",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "",
 	"Fluidly stream large external response chunks": "",
 	"Fluidly stream large external response chunks": "",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "",
 	"Generating search query": "",
 	"Generation Info": "",
 	"Generation Info": "",
+	"Global": "",
 	"Good Response": "",
 	"Good Response": "",
 	"Google PSE API Key": "",
 	"Google PSE API Key": "",
 	"Google PSE Engine Id": "",
 	"Google PSE Engine Id": "",

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

@@ -261,6 +261,8 @@
 	"File": "",
 	"File": "",
 	"File Mode": "Dosya Modu",
 	"File Mode": "Dosya Modu",
 	"File not found.": "Dosya bulunamadı.",
 	"File not found.": "Dosya bulunamadı.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Parmak izi sahteciliği tespit edildi: Avatar olarak baş harfler kullanılamıyor. Varsayılan profil resmine dönülüyor.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Parmak izi sahteciliği tespit edildi: Avatar olarak baş harfler kullanılamıyor. Varsayılan profil resmine dönülüyor.",
 	"Fluidly stream large external response chunks": "Büyük harici yanıt chunklarını akıcı bir şekilde yayınlayın",
 	"Fluidly stream large external response chunks": "Büyük harici yanıt chunklarını akıcı bir şekilde yayınlayın",
@@ -279,6 +281,7 @@
 	"Generate Image": "",
 	"Generate Image": "",
 	"Generating search query": "Arama sorgusu oluşturma",
 	"Generating search query": "Arama sorgusu oluşturma",
 	"Generation Info": "Üretim Bilgisi",
 	"Generation Info": "Üretim Bilgisi",
+	"Global": "",
 	"Good Response": "İyi Yanıt",
 	"Good Response": "İyi Yanıt",
 	"Google PSE API Key": "Google PSE API Anahtarı",
 	"Google PSE API Key": "Google PSE API Anahtarı",
 	"Google PSE Engine Id": "Google PSE Engine Id",
 	"Google PSE Engine Id": "Google PSE Engine Id",

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

@@ -261,6 +261,8 @@
 	"File": "Файл",
 	"File": "Файл",
 	"File Mode": "Файловий режим",
 	"File Mode": "Файловий режим",
 	"File not found.": "Файл не знайдено.",
 	"File not found.": "Файл не знайдено.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "Фільтри",
 	"Filters": "Фільтри",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Виявлено підробку відбитків: Неможливо використовувати ініціали як аватар. Повернення до зображення профілю за замовчуванням.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Виявлено підробку відбитків: Неможливо використовувати ініціали як аватар. Повернення до зображення профілю за замовчуванням.",
 	"Fluidly stream large external response chunks": "Плавно передавати великі фрагменти зовнішніх відповідей",
 	"Fluidly stream large external response chunks": "Плавно передавати великі фрагменти зовнішніх відповідей",
@@ -279,6 +281,7 @@
 	"Generate Image": "Створити зображення",
 	"Generate Image": "Створити зображення",
 	"Generating search query": "Сформувати пошуковий запит",
 	"Generating search query": "Сформувати пошуковий запит",
 	"Generation Info": "Інформація про генерацію",
 	"Generation Info": "Інформація про генерацію",
+	"Global": "",
 	"Good Response": "Гарна відповідь",
 	"Good Response": "Гарна відповідь",
 	"Google PSE API Key": "Ключ API Google PSE",
 	"Google PSE API Key": "Ключ API Google PSE",
 	"Google PSE Engine Id": "Id рушія Google PSE",
 	"Google PSE Engine Id": "Id рушія Google PSE",

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

@@ -261,6 +261,8 @@
 	"File": "Tệp",
 	"File": "Tệp",
 	"File Mode": "Chế độ Tệp văn bản",
 	"File Mode": "Chế độ Tệp văn bản",
 	"File not found.": "Không tìm thấy tệp.",
 	"File not found.": "Không tìm thấy tệp.",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "",
 	"Filters": "",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Phát hiện giả mạo vân tay: Không thể sử dụng tên viết tắt làm hình đại diện. Mặc định là hình ảnh hồ sơ mặc định.",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Phát hiện giả mạo vân tay: Không thể sử dụng tên viết tắt làm hình đại diện. Mặc định là hình ảnh hồ sơ mặc định.",
 	"Fluidly stream large external response chunks": "Truyền tải các khối phản hồi bên ngoài lớn một cách trôi chảy",
 	"Fluidly stream large external response chunks": "Truyền tải các khối phản hồi bên ngoài lớn một cách trôi chảy",
@@ -279,6 +281,7 @@
 	"Generate Image": "Sinh ảnh",
 	"Generate Image": "Sinh ảnh",
 	"Generating search query": "Tạo truy vấn tìm kiếm",
 	"Generating search query": "Tạo truy vấn tìm kiếm",
 	"Generation Info": "Thông tin chung",
 	"Generation Info": "Thông tin chung",
+	"Global": "",
 	"Good Response": "Trả lời tốt",
 	"Good Response": "Trả lời tốt",
 	"Google PSE API Key": "Khóa API Google PSE",
 	"Google PSE API Key": "Khóa API Google PSE",
 	"Google PSE Engine Id": "ID công cụ Google PSE",
 	"Google PSE Engine Id": "ID công cụ Google PSE",

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

@@ -18,7 +18,7 @@
 	"Active Users": "当前在线用户",
 	"Active Users": "当前在线用户",
 	"Add": "添加",
 	"Add": "添加",
 	"Add a model id": "添加一个模型 ID",
 	"Add a model id": "添加一个模型 ID",
-	"Add a short description about what this model does": "添加有关该模型能的简短描述",
+	"Add a short description about what this model does": "添加有关该模型能的简短描述",
 	"Add a short title for this prompt": "为此提示词添加一个简短的标题",
 	"Add a short title for this prompt": "为此提示词添加一个简短的标题",
 	"Add a tag": "添加标签",
 	"Add a tag": "添加标签",
 	"Add custom prompt": "添加自定义提示词",
 	"Add custom prompt": "添加自定义提示词",
@@ -44,7 +44,7 @@
 	"Allow Chat Deletion": "允许删除聊天记录",
 	"Allow Chat Deletion": "允许删除聊天记录",
 	"Allow non-local voices": "允许调用非本地音色",
 	"Allow non-local voices": "允许调用非本地音色",
 	"Allow User Location": "允许获取您的位置",
 	"Allow User Location": "允许获取您的位置",
-	"Allow Voice Interruption in Call": "",
+	"Allow Voice Interruption in Call": "允许通话中的打断语音",
 	"alphanumeric characters and hyphens": "字母数字字符和连字符",
 	"alphanumeric characters and hyphens": "字母数字字符和连字符",
 	"Already have an account?": "已经拥有账号了?",
 	"Already have an account?": "已经拥有账号了?",
 	"an assistant": "助手",
 	"an assistant": "助手",
@@ -63,7 +63,7 @@
 	"Attach file": "添加文件",
 	"Attach file": "添加文件",
 	"Attention to detail": "注重细节",
 	"Attention to detail": "注重细节",
 	"Audio": "语音",
 	"Audio": "语音",
-	"Audio settings updated successfully": "",
+	"Audio settings updated successfully": "语音设置更新成功",
 	"August": "八月",
 	"August": "八月",
 	"Auto-playback response": "自动念出回复内容",
 	"Auto-playback response": "自动念出回复内容",
 	"AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api鉴权字符串",
 	"AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api鉴权字符串",
@@ -110,10 +110,10 @@
 	"Click here to select documents.": "单击选择文档",
 	"Click here to select documents.": "单击选择文档",
 	"click here.": "点击这里。",
 	"click here.": "点击这里。",
 	"Click on the user role button to change a user's role.": "点击角色前方的组别按钮以更改用户所属权限组。",
 	"Click on the user role button to change a user's role.": "点击角色前方的组别按钮以更改用户所属权限组。",
-	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "",
+	"Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "写入剪贴板时被拒绝。请检查浏览器设置,授予必要权限。",
 	"Clone": "复制",
 	"Clone": "复制",
 	"Close": "关闭",
 	"Close": "关闭",
-	"Code formatted successfully": "",
+	"Code formatted successfully": "代码格式化成功",
 	"Collection": "集合",
 	"Collection": "集合",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI Base URL": "ComfyUI 基础地址",
 	"ComfyUI Base URL": "ComfyUI 基础地址",
@@ -128,7 +128,7 @@
 	"Content": "内容",
 	"Content": "内容",
 	"Context Length": "上下文长度",
 	"Context Length": "上下文长度",
 	"Continue Response": "继续生成",
 	"Continue Response": "继续生成",
-	"Continue with {{provider}}": "",
+	"Continue with {{provider}}": "使用 {{provider}} 继续",
 	"Copied shared chat URL to clipboard!": "已复制此对话分享链接至剪贴板!",
 	"Copied shared chat URL to clipboard!": "已复制此对话分享链接至剪贴板!",
 	"Copy": "复制",
 	"Copy": "复制",
 	"Copy last code block": "复制最后一个代码块中的代码",
 	"Copy last code block": "复制最后一个代码块中的代码",
@@ -165,22 +165,22 @@
 	"Delete chat": "删除对话记录",
 	"Delete chat": "删除对话记录",
 	"Delete Chat": "删除对话记录",
 	"Delete Chat": "删除对话记录",
 	"Delete chat?": "删除对话记录?",
 	"Delete chat?": "删除对话记录?",
-	"Delete function?": "",
-	"Delete prompt?": "",
+	"Delete function?": "删除函数?",
+	"Delete prompt?": "删除提示词?",
 	"delete this link": "此处删除这个链接",
 	"delete this link": "此处删除这个链接",
-	"Delete tool?": "",
+	"Delete tool?": "删除工具?",
 	"Delete User": "删除用户",
 	"Delete User": "删除用户",
 	"Deleted {{deleteModelTag}}": "已删除 {{deleteModelTag}}",
 	"Deleted {{deleteModelTag}}": "已删除 {{deleteModelTag}}",
 	"Deleted {{name}}": "已删除 {{name}}",
 	"Deleted {{name}}": "已删除 {{name}}",
 	"Description": "描述",
 	"Description": "描述",
 	"Didn't fully follow instructions": "没有完全遵照指示",
 	"Didn't fully follow instructions": "没有完全遵照指示",
-	"Discover a function": "",
+	"Discover a function": "发现更多函数",
 	"Discover a model": "发现更多模型",
 	"Discover a model": "发现更多模型",
 	"Discover a prompt": "发现更多提示词",
 	"Discover a prompt": "发现更多提示词",
-	"Discover a tool": "",
-	"Discover, download, and explore custom functions": "",
+	"Discover a tool": "发现更多工具",
+	"Discover, download, and explore custom functions": "发现、下载并探索更多函数",
 	"Discover, download, and explore custom prompts": "发现、下载并探索更多自定义提示词",
 	"Discover, download, and explore custom prompts": "发现、下载并探索更多自定义提示词",
-	"Discover, download, and explore custom tools": "",
+	"Discover, download, and explore custom tools": "发现、下载并探索更多工具",
 	"Discover, download, and explore model presets": "发现、下载并探索更多模型预设",
 	"Discover, download, and explore model presets": "发现、下载并探索更多模型预设",
 	"Dismissible": "是否可关闭",
 	"Dismissible": "是否可关闭",
 	"Display Emoji in Call": "在通话中显示 Emoji 表情符号",
 	"Display Emoji in Call": "在通话中显示 Emoji 表情符号",
@@ -193,7 +193,7 @@
 	"Don't Allow": "不允许",
 	"Don't Allow": "不允许",
 	"Don't have an account?": "没有账号?",
 	"Don't have an account?": "没有账号?",
 	"Don't like the style": "不喜欢这个文风",
 	"Don't like the style": "不喜欢这个文风",
-	"Done": "",
+	"Done": "完成",
 	"Download": "下载",
 	"Download": "下载",
 	"Download canceled": "下载已取消",
 	"Download canceled": "下载已取消",
 	"Download Database": "下载数据库",
 	"Download Database": "下载数据库",
@@ -247,8 +247,8 @@
 	"Export chat (.json)": "JSON 文件 (.json)",
 	"Export chat (.json)": "JSON 文件 (.json)",
 	"Export Chats": "导出对话",
 	"Export Chats": "导出对话",
 	"Export Documents Mapping": "导出文档映射",
 	"Export Documents Mapping": "导出文档映射",
-	"Export Functions": "导出功能",
-	"Export LiteLLM config.yaml": "",
+	"Export Functions": "导出函数",
+	"Export LiteLLM config.yaml": "导出 LteLLM config.yaml 文件",
 	"Export Models": "导出模型",
 	"Export Models": "导出模型",
 	"Export Prompts": "导出提示词",
 	"Export Prompts": "导出提示词",
 	"Export Tools": "导出工具",
 	"Export Tools": "导出工具",
@@ -261,6 +261,8 @@
 	"File": "文件",
 	"File": "文件",
 	"File Mode": "文件模式",
 	"File Mode": "文件模式",
 	"File not found.": "文件未找到。",
 	"File not found.": "文件未找到。",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "过滤器",
 	"Filters": "过滤器",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "检测到指纹伪造:无法使用姓名缩写作为头像。默认使用默认个人形象。",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "检测到指纹伪造:无法使用姓名缩写作为头像。默认使用默认个人形象。",
 	"Fluidly stream large external response chunks": "流畅地传输外部大型响应块数据",
 	"Fluidly stream large external response chunks": "流畅地传输外部大型响应块数据",
@@ -269,16 +271,17 @@
 	"Form": "手动创建",
 	"Form": "手动创建",
 	"Format your variables using square brackets like this:": "使用这样的方括号格式化你的变量:",
 	"Format your variables using square brackets like this:": "使用这样的方括号格式化你的变量:",
 	"Frequency Penalty": "频率惩罚",
 	"Frequency Penalty": "频率惩罚",
-	"Function created successfully": "",
-	"Function deleted successfully": "",
-	"Function updated successfully": "",
-	"Functions": "功能",
-	"Functions imported successfully": "",
+	"Function created successfully": "函数创建成功",
+	"Function deleted successfully": "函数删除成功",
+	"Function updated successfully": "函数更新成功",
+	"Functions": "函数",
+	"Functions imported successfully": "函数导入成功",
 	"General": "通用",
 	"General": "通用",
 	"General Settings": "通用设置",
 	"General Settings": "通用设置",
 	"Generate Image": "生成图像",
 	"Generate Image": "生成图像",
 	"Generating search query": "生成搜索查询",
 	"Generating search query": "生成搜索查询",
 	"Generation Info": "生成信息",
 	"Generation Info": "生成信息",
+	"Global": "",
 	"Good Response": "点赞此回答",
 	"Good Response": "点赞此回答",
 	"Google PSE API Key": "Google PSE API 密钥",
 	"Google PSE API Key": "Google PSE API 密钥",
 	"Google PSE Engine Id": "Google PSE 引擎 ID",
 	"Google PSE Engine Id": "Google PSE 引擎 ID",
@@ -296,7 +299,7 @@
 	"Images": "图像",
 	"Images": "图像",
 	"Import Chats": "导入对话记录",
 	"Import Chats": "导入对话记录",
 	"Import Documents Mapping": "导入文档映射",
 	"Import Documents Mapping": "导入文档映射",
-	"Import Functions": "导入功能",
+	"Import Functions": "导入函数",
 	"Import Models": "导入模型",
 	"Import Models": "导入模型",
 	"Import Prompts": "导入提示词",
 	"Import Prompts": "导入提示词",
 	"Import Tools": "导入工具",
 	"Import Tools": "导入工具",
@@ -333,17 +336,17 @@
 	"Manage Models": "管理模型",
 	"Manage Models": "管理模型",
 	"Manage Ollama Models": "管理 Ollama 模型",
 	"Manage Ollama Models": "管理 Ollama 模型",
 	"Manage Pipelines": "管理 Pipeline",
 	"Manage Pipelines": "管理 Pipeline",
-	"Manage Valves": "",
+	"Manage Valves": "管理值",
 	"March": "三月",
 	"March": "三月",
 	"Max Tokens (num_predict)": "最多 Token (num_predict)",
 	"Max Tokens (num_predict)": "最多 Token (num_predict)",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "最多可以同时下载 3 个模型,请稍后重试。",
 	"Maximum of 3 models can be downloaded simultaneously. Please try again later.": "最多可以同时下载 3 个模型,请稍后重试。",
 	"May": "五月",
 	"May": "五月",
 	"Memories accessible by LLMs will be shown here.": "大语言模型可访问的记忆将在此显示。",
 	"Memories accessible by LLMs will be shown here.": "大语言模型可访问的记忆将在此显示。",
 	"Memory": "记忆",
 	"Memory": "记忆",
-	"Memory added successfully": "",
-	"Memory cleared successfully": "",
-	"Memory deleted successfully": "",
-	"Memory updated successfully": "",
+	"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.": "创建链接后发送的消息不会被共享。具有 URL 的用户将能够查看共享对话。",
 	"Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "创建链接后发送的消息不会被共享。具有 URL 的用户将能够查看共享对话。",
 	"Minimum Score": "最低分",
 	"Minimum Score": "最低分",
 	"Mirostat": "Mirostat",
 	"Mirostat": "Mirostat",
@@ -355,14 +358,14 @@
 	"Model '{{modelName}}' has been successfully downloaded.": "模型'{{modelName}}'已成功下载。",
 	"Model '{{modelName}}' has been successfully downloaded.": "模型'{{modelName}}'已成功下载。",
 	"Model '{{modelTag}}' is already in queue for downloading.": "模型'{{modelTag}}'已在下载队列中。",
 	"Model '{{modelTag}}' is already in queue for downloading.": "模型'{{modelTag}}'已在下载队列中。",
 	"Model {{modelId}} not found": "未找到模型 {{modelId}}",
 	"Model {{modelId}} not found": "未找到模型 {{modelId}}",
-	"Model {{modelName}} is not vision capable": "模型 {{modelName}} 不支持视觉能",
+	"Model {{modelName}} is not vision capable": "模型 {{modelName}} 不支持视觉能",
 	"Model {{name}} is now {{status}}": "模型 {{name}} 现在是 {{status}}",
 	"Model {{name}} is now {{status}}": "模型 {{name}} 现在是 {{status}}",
-	"Model created successfully!": "",
+	"Model created successfully!": "模型创建成功!",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "检测到模型文件系统路径,无法继续进行。更新操作需要提供模型简称。",
 	"Model filesystem path detected. Model shortname is required for update, cannot continue.": "检测到模型文件系统路径,无法继续进行。更新操作需要提供模型简称。",
 	"Model ID": "模型 ID",
 	"Model ID": "模型 ID",
 	"Model not selected": "未选择模型",
 	"Model not selected": "未选择模型",
 	"Model Params": "模型参数",
 	"Model Params": "模型参数",
-	"Model updated successfully": "",
+	"Model updated successfully": "模型更新成功",
 	"Model Whitelisting": "白名单模型",
 	"Model Whitelisting": "白名单模型",
 	"Model(s) Whitelisted": "模型已加入白名单",
 	"Model(s) Whitelisted": "模型已加入白名单",
 	"Modelfile Content": "模型文件内容",
 	"Modelfile Content": "模型文件内容",
@@ -373,20 +376,20 @@
 	"Name your model": "为您的模型命名",
 	"Name your model": "为您的模型命名",
 	"New Chat": "新对话",
 	"New Chat": "新对话",
 	"New Password": "新密码",
 	"New Password": "新密码",
-	"No content to speak": "",
+	"No content to speak": "没有内容可朗读",
 	"No documents found": "未找到文档",
 	"No documents found": "未找到文档",
-	"No file selected": "",
+	"No file selected": "未选中文件",
 	"No results found": "未找到结果",
 	"No results found": "未找到结果",
 	"No search query generated": "未生成搜索查询",
 	"No search query generated": "未生成搜索查询",
 	"No source available": "没有可用来源",
 	"No source available": "没有可用来源",
-	"No valves to update": "",
+	"No valves to update": "没有需要更新的值",
 	"None": "无",
 	"None": "无",
 	"Not factually correct": "事实并非如此",
 	"Not factually correct": "事实并非如此",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "注意:如果设置了最低分数,搜索只会返回分数大于或等于最低分数的文档。",
 	"Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "注意:如果设置了最低分数,搜索只会返回分数大于或等于最低分数的文档。",
 	"Notifications": "桌面通知",
 	"Notifications": "桌面通知",
 	"November": "十一月",
 	"November": "十一月",
 	"num_thread (Ollama)": "num_thread(Ollama)",
 	"num_thread (Ollama)": "num_thread(Ollama)",
-	"OAuth ID": "",
+	"OAuth ID": "OAuth ID",
 	"October": "十月",
 	"October": "十月",
 	"Off": "关闭",
 	"Off": "关闭",
 	"Okay, Let's Go!": "确认,开始使用!",
 	"Okay, Let's Go!": "确认,开始使用!",
@@ -421,10 +424,10 @@
 	"Permission denied when accessing microphone": "申请麦克风权限被拒绝",
 	"Permission denied when accessing microphone": "申请麦克风权限被拒绝",
 	"Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}",
 	"Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}",
 	"Personalization": "个性化",
 	"Personalization": "个性化",
-	"Pipeline deleted successfully": "",
-	"Pipeline downloaded successfully": "",
+	"Pipeline deleted successfully": "Pipeline 删除成功",
+	"Pipeline downloaded successfully": "Pipeline 下载成功",
 	"Pipelines": "Pipeline",
 	"Pipelines": "Pipeline",
-	"Pipelines Not Detected": "",
+	"Pipelines Not Detected": "未检测到 Pipeline",
 	"Pipelines Valves": "Pipeline 值",
 	"Pipelines Valves": "Pipeline 值",
 	"Plain text (.txt)": "TXT 文档 (.txt)",
 	"Plain text (.txt)": "TXT 文档 (.txt)",
 	"Playground": "AI 对话游乐场",
 	"Playground": "AI 对话游乐场",
@@ -460,7 +463,7 @@
 	"Reset Upload Directory": "重置上传目录",
 	"Reset Upload Directory": "重置上传目录",
 	"Reset Vector Storage": "重置向量存储",
 	"Reset Vector Storage": "重置向量存储",
 	"Response AutoCopy to Clipboard": "自动复制回复到剪贴板",
 	"Response AutoCopy to Clipboard": "自动复制回复到剪贴板",
-	"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.": "无法激活回复时发送通知。请检查浏览器设置,并授予必要的访问权限。",
 	"Role": "权限组",
 	"Role": "权限组",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine": "Rosé Pine",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
 	"Rosé Pine Dawn": "Rosé Pine Dawn",
@@ -477,7 +480,7 @@
 	"Search a model": "搜索模型",
 	"Search a model": "搜索模型",
 	"Search Chats": "搜索对话",
 	"Search Chats": "搜索对话",
 	"Search Documents": "搜索文档",
 	"Search Documents": "搜索文档",
-	"Search Functions": "搜索功能",
+	"Search Functions": "搜索函数",
 	"Search Models": "搜索模型",
 	"Search Models": "搜索模型",
 	"Search Prompts": "搜索提示词",
 	"Search Prompts": "搜索提示词",
 	"Search Query Generation Prompt": "搜索查询生成提示",
 	"Search Query Generation Prompt": "搜索查询生成提示",
@@ -492,12 +495,12 @@
 	"Seed": "种子 (Seed)",
 	"Seed": "种子 (Seed)",
 	"Select a base model": "选择一个基础模型",
 	"Select a base model": "选择一个基础模型",
 	"Select a engine": "选择一个搜索引擎",
 	"Select a engine": "选择一个搜索引擎",
-	"Select a function": "",
+	"Select a function": "选择一个函数",
 	"Select a mode": "选择一个模式",
 	"Select a mode": "选择一个模式",
 	"Select a model": "选择一个模型",
 	"Select a model": "选择一个模型",
 	"Select a pipeline": "选择一个管道",
 	"Select a pipeline": "选择一个管道",
 	"Select a pipeline url": "选择一个管道 URL",
 	"Select a pipeline url": "选择一个管道 URL",
-	"Select a tool": "",
+	"Select a tool": "选择一个工具",
 	"Select an Ollama instance": "选择一个 Ollama 实例",
 	"Select an Ollama instance": "选择一个 Ollama 实例",
 	"Select Documents": "选择文档",
 	"Select Documents": "选择文档",
 	"Select model": "选择模型",
 	"Select model": "选择模型",
@@ -530,7 +533,7 @@
 	"Show Admin Details in Account Pending Overlay": "在用户待激活界面中显示管理员邮箱等详细信息",
 	"Show Admin Details in Account Pending Overlay": "在用户待激活界面中显示管理员邮箱等详细信息",
 	"Show Model": "显示",
 	"Show Model": "显示",
 	"Show shortcuts": "显示快捷方式",
 	"Show shortcuts": "显示快捷方式",
-	"Show your support!": "",
+	"Show your support!": "表达你的支持!",
 	"Showcased creativity": "很有创意",
 	"Showcased creativity": "很有创意",
 	"sidebar": "侧边栏",
 	"sidebar": "侧边栏",
 	"Sign in": "登录",
 	"Sign in": "登录",
@@ -581,16 +584,16 @@
 	"To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "请联系管理员以访问。管理员可以在后台管理面板中管理用户状态。",
 	"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 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 filters here, add them to the \"Functions\" workspace first.": "要在这里选择过滤器,请先将它们添加到工作空间中的“函数”。",
 	"To select toolkits here, add them to the \"Tools\" workspace first.": "要在这里选择工具包,请先将它们添加到工作空间中的“工具”。",
 	"To select toolkits here, add them to the \"Tools\" workspace first.": "要在这里选择工具包,请先将它们添加到工作空间中的“工具”。",
 	"Today": "今天",
 	"Today": "今天",
 	"Toggle settings": "切换设置",
 	"Toggle settings": "切换设置",
 	"Toggle sidebar": "切换侧边栏",
 	"Toggle sidebar": "切换侧边栏",
 	"Tokens To Keep On Context Refresh (num_keep)": "在语境刷新时需保留的 Tokens",
 	"Tokens To Keep On Context Refresh (num_keep)": "在语境刷新时需保留的 Tokens",
-	"Tool created successfully": "",
-	"Tool deleted successfully": "",
-	"Tool imported successfully": "",
-	"Tool updated successfully": "",
+	"Tool created successfully": "工具创建成功",
+	"Tool deleted successfully": "工具删除成功",
+	"Tool imported successfully": "工具导入成功",
+	"Tool updated successfully": "工具更新成功",
 	"Tools": "工具",
 	"Tools": "工具",
 	"Top K": "Top K",
 	"Top K": "Top K",
 	"Top P": "Top P",
 	"Top P": "Top P",
@@ -619,14 +622,14 @@
 	"use_mlock (Ollama)": "use_mlock(Ollama)",
 	"use_mlock (Ollama)": "use_mlock(Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "用户",
 	"user": "用户",
-	"User location successfully retrieved.": "",
+	"User location successfully retrieved.": "成功检索到用户位置。",
 	"User Permissions": "用户权限",
 	"User Permissions": "用户权限",
 	"Users": "用户",
 	"Users": "用户",
 	"Utilize": "利用",
 	"Utilize": "利用",
 	"Valid time units:": "有效时间单位:",
 	"Valid time units:": "有效时间单位:",
-	"Valves": "",
-	"Valves updated": "",
-	"Valves updated successfully": "",
+	"Valves": "",
+	"Valves updated": "已更新值",
+	"Valves updated successfully": "值更新成功",
 	"variable": "变量",
 	"variable": "变量",
 	"variable to have them replaced with clipboard content.": "变量将被剪贴板内容替换。",
 	"variable to have them replaced with clipboard content.": "变量将被剪贴板内容替换。",
 	"Version": "版本",
 	"Version": "版本",

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

@@ -261,6 +261,8 @@
 	"File": "檔案",
 	"File": "檔案",
 	"File Mode": "檔案模式",
 	"File Mode": "檔案模式",
 	"File not found.": "找不到檔案。",
 	"File not found.": "找不到檔案。",
+	"Filter is now globally disabled": "",
+	"Filter is now globally enabled": "",
 	"Filters": "篩選器",
 	"Filters": "篩選器",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "偽造偵測:無法使用初始頭像。預設為預設個人影象。",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "偽造偵測:無法使用初始頭像。預設為預設個人影象。",
 	"Fluidly stream large external response chunks": "流暢地傳輸大型外部回應區塊",
 	"Fluidly stream large external response chunks": "流暢地傳輸大型外部回應區塊",
@@ -279,6 +281,7 @@
 	"Generate Image": "生成圖片",
 	"Generate Image": "生成圖片",
 	"Generating search query": "生成搜尋查詢",
 	"Generating search query": "生成搜尋查詢",
 	"Generation Info": "生成資訊",
 	"Generation Info": "生成資訊",
+	"Global": "",
 	"Good Response": "優秀的回應",
 	"Good Response": "優秀的回應",
 	"Google PSE API Key": "Google PSE API 金鑰",
 	"Google PSE API Key": "Google PSE API 金鑰",
 	"Google PSE Engine Id": "Google PSE 引擎 ID",
 	"Google PSE Engine Id": "Google PSE 引擎 ID",

+ 16 - 10
src/routes/(app)/workspace/functions/create/+page.svelte

@@ -48,6 +48,10 @@
 			console.log(func);
 			console.log(func);
 		});
 		});
 
 
+		if (window.opener ?? false) {
+			window.opener.postMessage('loaded', '*');
+		}
+
 		if (sessionStorage.function) {
 		if (sessionStorage.function) {
 			func = JSON.parse(sessionStorage.function);
 			func = JSON.parse(sessionStorage.function);
 			sessionStorage.removeItem('function');
 			sessionStorage.removeItem('function');
@@ -61,14 +65,16 @@
 </script>
 </script>
 
 
 {#if mounted}
 {#if mounted}
-	<FunctionEditor
-		id={func?.id ?? ''}
-		name={func?.name ?? ''}
-		meta={func?.meta ?? { description: '' }}
-		content={func?.content ?? ''}
-		{clone}
-		on:save={(e) => {
-			saveHandler(e.detail);
-		}}
-	/>
+	{#key func?.content}
+		<FunctionEditor
+			id={func?.id ?? ''}
+			name={func?.name ?? ''}
+			meta={func?.meta ?? { description: '' }}
+			content={func?.content ?? ''}
+			{clone}
+			on:save={(e) => {
+				saveHandler(e.detail);
+			}}
+		/>
+	{/key}
 {/if}
 {/if}

+ 22 - 1
src/routes/(app)/workspace/models/create/+page.svelte

@@ -2,7 +2,7 @@
 	import { v4 as uuidv4 } from 'uuid';
 	import { v4 as uuidv4 } from 'uuid';
 	import { toast } from 'svelte-sonner';
 	import { toast } from 'svelte-sonner';
 	import { goto } from '$app/navigation';
 	import { goto } from '$app/navigation';
-	import { settings, user, config, models, tools } from '$lib/stores';
+	import { settings, user, config, models, tools, functions } from '$lib/stores';
 
 
 	import TurndownService from 'turndown';
 	import TurndownService from 'turndown';
 
 
@@ -17,6 +17,7 @@
 	import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
 	import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
 	import { stringify } from 'postcss';
 	import { stringify } from 'postcss';
 	import { parseFile } from '$lib/utils/characters';
 	import { parseFile } from '$lib/utils/characters';
+	import FiltersSelector from '$lib/components/workspace/Models/FiltersSelector.svelte';
 
 
 	const i18n = getContext('i18n');
 	const i18n = getContext('i18n');
 
 
@@ -61,6 +62,7 @@
 
 
 	let toolIds = [];
 	let toolIds = [];
 	let knowledge = [];
 	let knowledge = [];
+	let filterIds = [];
 
 
 	$: if (name) {
 	$: if (name) {
 		id = name
 		id = name
@@ -105,6 +107,14 @@
 			}
 			}
 		}
 		}
 
 
+		if (filterIds.length > 0) {
+			info.meta.filterIds = filterIds;
+		} else {
+			if (info.meta.filterIds) {
+				delete info.meta.filterIds;
+			}
+		}
+
 		info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
 		info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null;
 		Object.keys(info.params).forEach((key) => {
 		Object.keys(info.params).forEach((key) => {
 			if (info.params[key] === '' || info.params[key] === null) {
 			if (info.params[key] === '' || info.params[key] === null) {
@@ -173,6 +183,10 @@
 		capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) };
 		capabilities = { ...capabilities, ...(model?.info?.meta?.capabilities ?? {}) };
 		toolIds = model?.info?.meta?.toolIds ?? [];
 		toolIds = model?.info?.meta?.toolIds ?? [];
 
 
+		if (model?.info?.meta?.filterIds) {
+			filterIds = [...model?.info?.meta?.filterIds];
+		}
+
 		info = {
 		info = {
 			...info,
 			...info,
 			...model.info
 			...model.info
@@ -604,6 +618,13 @@
 			<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
 			<ToolsSelector bind:selectedToolIds={toolIds} tools={$tools} />
 		</div>
 		</div>
 
 
+		<div class="my-2">
+			<FiltersSelector
+				bind:selectedFilterIds={filterIds}
+				filters={$functions.filter((func) => func.type === 'filter')}
+			/>
+		</div>
+
 		<div class="my-1">
 		<div class="my-1">
 			<div class="flex w-full justify-between mb-1">
 			<div class="flex w-full justify-between mb-1">
 				<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>
 				<div class=" self-center text-sm font-semibold">{$i18n.t('Capabilities')}</div>

+ 16 - 10
src/routes/(app)/workspace/tools/create/+page.svelte

@@ -45,6 +45,10 @@
 			console.log(tool);
 			console.log(tool);
 		});
 		});
 
 
+		if (window.opener ?? false) {
+			window.opener.postMessage('loaded', '*');
+		}
+
 		if (sessionStorage.tool) {
 		if (sessionStorage.tool) {
 			tool = JSON.parse(sessionStorage.tool);
 			tool = JSON.parse(sessionStorage.tool);
 			sessionStorage.removeItem('tool');
 			sessionStorage.removeItem('tool');
@@ -58,14 +62,16 @@
 </script>
 </script>
 
 
 {#if mounted}
 {#if mounted}
-	<ToolkitEditor
-		id={tool?.id ?? ''}
-		name={tool?.name ?? ''}
-		meta={tool?.meta ?? { description: '' }}
-		content={tool?.content ?? ''}
-		{clone}
-		on:save={(e) => {
-			saveHandler(e.detail);
-		}}
-	/>
+	{#key tool?.content}
+		<ToolkitEditor
+			id={tool?.id ?? ''}
+			name={tool?.name ?? ''}
+			meta={tool?.meta ?? { description: '' }}
+			content={tool?.content ?? ''}
+			{clone}
+			on:save={(e) => {
+				saveHandler(e.detail);
+			}}
+		/>
+	{/key}
 {/if}
 {/if}