diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 3ba13e0cec..abb131c930 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1 +1,5 @@ blank_issues_enabled: false +contact_links: + - name: 🔒 Report a Security Vulnerability + url: https://github.com/open-webui/open-webui/security + about: Do NOT open a public issue for security vulnerabilities, suspected vulnerabilities, or any security-related concern. Please review our Security Policy and report privately via the "Report a vulnerability" button so it can be handled as a private advisory. diff --git a/.github/workflows/backend.yaml b/.github/workflows/backend.yaml index 877a6b0ecc..56dcf5a396 100644 --- a/.github/workflows/backend.yaml +++ b/.github/workflows/backend.yaml @@ -7,10 +7,10 @@ name: Python CI on: push: branches: [main, dev] - paths: ['backend/**', 'pyproject.toml', 'uv.lock'] + paths: ['backend/**', 'pyproject.toml', 'uv.lock', '.github/workflows/backend.yaml'] pull_request: branches: [main, dev] - paths: ['backend/**', 'pyproject.toml', 'uv.lock'] + paths: ['backend/**', 'pyproject.toml', 'uv.lock', '.github/workflows/backend.yaml'] concurrency: group: backend-${{ github.ref }} @@ -38,3 +38,6 @@ jobs: - name: Verify formatting run: ruff format --check . --exclude .venv --exclude venv + + - name: Detect logic errors + run: ruff check --select=F --ignore=F401,F403,F405,F541,F811,F841 --output-format=github . diff --git a/.github/workflows/docker.yaml b/.github/workflows/docker.yaml index abd0362814..b54f3631d9 100644 --- a/.github/workflows/docker.yaml +++ b/.github/workflows/docker.yaml @@ -231,6 +231,70 @@ jobs: run: | docker buildx imagetools inspect ${{ env.FULL_IMAGE_NAME }}:${{ steps.meta.outputs.version }} + notify-helm-charts: + runs-on: ubuntu-latest + needs: [merge] + if: ${{ !cancelled() && needs.merge.result == 'success' && (github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/v')) }} + steps: + - name: Create Helm charts app token + id: helm-app-token + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.HELM_CHARTS_APP_ID }} + private-key: ${{ secrets.HELM_CHARTS_APP_PRIVATE_KEY }} + owner: ${{ github.repository_owner }} + repositories: helm-charts + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Verify published Open WebUI image + id: image + run: | + set -euo pipefail + + image_name="ghcr.io/${GITHUB_REPOSITORY,,}" + ref_name="${GITHUB_REF_NAME}" + + if [ "${GITHUB_REF}" = "refs/heads/dev" ]; then + image_tag="dev" + else + image_tag="${ref_name#v}" + fi + + docker buildx imagetools inspect "${image_name}:${image_tag}" + echo "tag=${image_tag}" >> "${GITHUB_OUTPUT}" + + - name: Dispatch Helm chart automation + uses: actions/github-script@v8 + with: + github-token: ${{ steps.helm-app-token.outputs.token }} + script: | + const isDev = context.ref === 'refs/heads/dev'; + const eventType = isDev + ? 'open-webui-dev-image-published' + : 'open-webui-release-published'; + const refName = context.ref.replace('refs/heads/', '').replace('refs/tags/', ''); + const appVersion = refName.startsWith('v') ? refName.slice(1) : refName; + const payload = { + image_tag: isDev ? 'dev' : appVersion, + source_ref: context.ref, + source_sha: context.sha, + source_run_id: String(context.runId), + source_repository: context.repo.repo, + }; + + if (!isDev) { + payload.app_version = appVersion; + } + + await github.rest.repos.createDispatchEvent({ + owner: context.repo.owner, + repo: 'helm-charts', + event_type: eventType, + client_payload: payload, + }); + copy-to-dockerhub: runs-on: ubuntu-latest if: ${{ !cancelled() && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')) }} diff --git a/.gitignore b/.gitignore index 07494bd151..32c6aa4c1b 100644 --- a/.gitignore +++ b/.gitignore @@ -310,3 +310,4 @@ dist cypress/videos cypress/screenshots .vscode/settings.json +.cptr diff --git a/CHANGELOG.md b/CHANGELOG.md index 310d62dc61..550df4a110 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,222 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.10.0] - 2026-06-29 + +### Added + +- 🤝 **Share folders with your team.** You can now share a folder and the chats inside it with specific users, groups, or everyone, with read or write access; people you share with see shared folders in their sidebar and open the chats in a read-only view when they are not the owner, and administrators control who is allowed to share folders with a new "Folders Sharing" permission that is off by default. [Commit](https://github.com/open-webui/open-webui/commit/5019af79a0c45743ede8c9ff37d68f768e7f6174), [Commit](https://github.com/open-webui/open-webui/commit/38920c0ed1f6ad5fe3bb9d12898fa968ead3634a), [Commit](https://github.com/open-webui/open-webui/commit/d65ac445a43348c5f0323d54c37397ae7f483cb8), [Commit](https://github.com/open-webui/open-webui/commit/c783fd30f20d6be5028cf337bc5e5c2f9afbd3f8), [Commit](https://github.com/open-webui/open-webui/commit/45fcf272ef51c84cb01c1454589da3f98e4adc2c), [Commit](https://github.com/open-webui/open-webui/commit/76854d14246660af8222a5302513020e1f36c4f3), [Commit](https://github.com/open-webui/open-webui/commit/084d040e220ee39f62757d928d839646e813fb25), [Commit](https://github.com/open-webui/open-webui/commit/10558173fb155c63403aa8d80f16f8a3ccfa72a6) +- 🗜️ **Automatic context compaction for long chats.** Conversations that grow past a configurable token threshold can now be summarized automatically so they stay within a model's context window, with a notification shown while it happens; administrators can enable it, set the threshold, customize the summarization prompt, and lower the threshold per model. It is off by default. [Commit](https://github.com/open-webui/open-webui/commit/3f0c0e0a0ddff841b015f96f9649c6999a435c73), [Commit](https://github.com/open-webui/open-webui/commit/7f08376f0c06e1a7fba983a2fa93deb8dfbe7cb0), [Commit](https://github.com/open-webui/open-webui/commit/8934bfb04bf366aece872028944e280c25e36d3e), [#19594](https://github.com/open-webui/open-webui/issues/19594) +- 🖥️ **Open WebUI Computer agent support.** Open WebUI can now connect to Open WebUI Computer through its OpenAI-compatible gateway, letting chats run full agent sessions on your own machine with file, terminal, git, and web access. [GitHub](https://github.com/open-webui/computer) +- 🚀 **Much faster hybrid search on large knowledge bases.** Hybrid search now runs natively in the database on pgvector setups instead of loading an entire collection into memory, so querying large knowledge bases is dramatically faster. [Commit](https://github.com/open-webui/open-webui/commit/223f484ded01d092979693341dc03351a9fa17fa), [#20737](https://github.com/open-webui/open-webui/discussions/20737) +- 🗂️ **External knowledge bases.** Knowledge bases can now be backed by an external retrieval source through configurable external knowledge connections, so you can search an existing external system from chat instead of only Open WebUI's built-in store. [Commit](https://github.com/open-webui/open-webui/commit/15c7e374384488effc3d6059d09b3a8aa79c618d) +- 🧠 **Reworked memory system.** Memory has been overhauled with distinct memory types — long-lived personal memories and per-conversation context — managed through a structured add, update, and delete flow, giving models a more reliable way to remember and apply what they've learned about you. [Commit](https://github.com/open-webui/open-webui/commit/dbdcfd8c6080c284024052a482e589de226dbf05), [Commit](https://github.com/open-webui/open-webui/commit/7e13fd7ad19c28ba34502bde6c709665f7a6808c), [Commit](https://github.com/open-webui/open-webui/commit/2560533c1a8a2b2a0f7b47becf3703031053ad30), [Commit](https://github.com/open-webui/open-webui/commit/8977a10a2b1e150393635dc5c24e59660d0f2da9), [Commit](https://github.com/open-webui/open-webui/commit/260f3c3a22c55f15ca8f06c5314b23f2a9eb1739), [Commit](https://github.com/open-webui/open-webui/commit/b0487dd6dd942a757828a25aba92e9feef685275), [Commit](https://github.com/open-webui/open-webui/commit/a285a390c12e27e614d1ba9ffb92d1a0e49e7dfa), [Commit](https://github.com/open-webui/open-webui/commit/70e4ffcc6526c1bc90dbfdc0287283574b12c18b), [Commit](https://github.com/open-webui/open-webui/commit/2c4e1fce8f40b0cb5028f1afcb184b6e58c33041), [Commit](https://github.com/open-webui/open-webui/commit/c7e634776d7e77556d149b6cc884ed64363648a9) +- 🧩 **New plugin primitive: the Event function.** Where pipe, filter, and action functions all run inside a conversation, the new Event function is the first primitive that hooks into the system itself: it runs your own Python in response to events emitted across the whole application — sign-ups, configuration changes, file uploads, role changes, deletions, startup and shutdown, and more. That makes a new class of behavior possible directly inside Open WebUI, from onboarding and access control to auditing, lifecycle automation, and external integrations. Comes with starter boilerplate in the function editor. [Commit](https://github.com/open-webui/open-webui/commit/e124c2656a4c2092b070e570e35b2f0fb7f584de), [Docs](https://docs.openwebui.com/features/extensibility/plugin/functions/event) +- 🔔 **New event system with webhooks.** Open WebUI now emits events for a wide range of system activity — sign-ins, configuration changes, startup, and actions across chats, knowledge, files, and more. Administrators can send these as outbound webhooks, route them to specific users or groups, and manage which events go where from a new event settings admin page. [Commit](https://github.com/open-webui/open-webui/commit/b5c43968db0ea1556b228d143ae5946dc4e944ba), [Commit](https://github.com/open-webui/open-webui/commit/745396867888718289a2dfcf0809b3e162e00629), [Commit](https://github.com/open-webui/open-webui/commit/5576e6ed8a80a4032b7c6cb3ee0cda0254019355), [Commit](https://github.com/open-webui/open-webui/commit/7b55a63fc7ee323e9114713ce1d2f3f688aa37e6), [Commit](https://github.com/open-webui/open-webui/commit/1a8e1a993928a28b9d814c77b2aef0361b630f27), [Commit](https://github.com/open-webui/open-webui/commit/ede39d82de05eeb7591329679c8cab97753e5ff0), [Commit](https://github.com/open-webui/open-webui/commit/8f890f0b43aed3d42b9e3d954e25e54e37d526d0), [Commit](https://github.com/open-webui/open-webui/commit/741b64edb6c2ff04c4b787528cfca1c5b66a1a27), [Commit](https://github.com/open-webui/open-webui/commit/303c426c3fffafc2369205021a82659ee8715a85), [#1240](https://github.com/open-webui/open-webui/issues/1240), [#16426](https://github.com/open-webui/open-webui/pull/16426) +- 🔐 **Configure authentication from the admin panel.** LDAP and OAuth/OIDC settings now have a dedicated Authentication settings page, so providers can be configured from the admin interface. [Commit](https://github.com/open-webui/open-webui/commit/5cdcdbaeec9fc8156721c38c33ec37956962871c), [#12945](https://github.com/open-webui/open-webui/pull/12945) +- 🏷️ **More custom header variables.** Custom request headers now support "{{USER_MESSAGE_ID}}", "{{USER_MESSAGE_PARENT_ID}}", and "{{TASK}}", letting connected services tell apart real user messages from automated background requests like title, tag, and follow-up generation. [Commit](https://github.com/open-webui/open-webui/commit/f85cb27ef835aa76aff7de6176bf2159ba392061) +- 📄 **File details forwarded to external document extractors.** External custom document-extraction servers now receive the file's ID, name, and content type, and these are also available as custom header variables, so extraction can be tailored per file. [Commit](https://github.com/open-webui/open-webui/commit/b1c2536ed2f8639efade04618018e6de9b332df2), [#26259](https://github.com/open-webui/open-webui/issues/26259) +- 🎰 **Last model pre-selected for new slots.** When you add another model to a multi-model chat, the slot now defaults to the model you last picked instead of starting empty. [#25974](https://github.com/open-webui/open-webui/pull/25974) +- ⚡ **Faster model overview.** The admin model overview now loads its feedback history and tags through batched queries, so it opens noticeably faster on instances with many chats. [Commit](https://github.com/open-webui/open-webui/commit/40c09167cd6de1c853a5dd03c88b4fdcb279dfe1) +- 🏎️ **Lighter channel profile previews.** Profile previews in channels now load a person's details only when you hover to open one, rather than fetching them for every message up front. [Commit](https://github.com/open-webui/open-webui/commit/4f69c33de0e9a8fde4f16d0b2f1ed8aac8741772) +- ↩️ **Reset permissions to defaults.** The group and default permission dialogs now include a button to restore all permissions back to their built-in defaults in one step. [#25931](https://github.com/open-webui/open-webui/pull/25931) +- 📥 **Chat import permission.** Administrators can now control whether users are allowed to import or clone chats, with a new "Allow Chat Import" permission. [Commit](https://github.com/open-webui/open-webui/commit/edf3ae920989b01383be543e7379d3eade03c0b6), [Commit](https://github.com/open-webui/open-webui/commit/9ccda6715c3b2dc2cbc1302d2396b2f0233bdea8), [Commit](https://github.com/open-webui/open-webui/commit/ed4cb358a06fc6962b378f20ef846fd2b0af90bc), [#25927](https://github.com/open-webui/open-webui/pull/25927) +- 🔔 **Per-group user webhook permission.** Administrators can now control which users may set a personal notification webhook, with a new "User Webhooks" permission. [#25923](https://github.com/open-webui/open-webui/pull/25923) +- ✍️ **Customizable autocomplete prompt.** Administrators can now set a custom prompt template for autocomplete generation from the admin interface settings. [Commit](https://github.com/open-webui/open-webui/commit/4dbb2f94a66d6e0035e2da857ddb6a841a68f862), [#25879](https://github.com/open-webui/open-webui/pull/25879) +- 🔑 **Configurable secret key length.** The auto-generated secret key length can now be set with a new environment variable, instead of always using a fixed length. [Commit](https://github.com/open-webui/open-webui/commit/e473ab1231abedcb188c259b42ae7f2390739223), [#25906](https://github.com/open-webui/open-webui/pull/25906) +- 🏟️ **Arena evaluation models configurable via environment.** Arena evaluation models can now be defined through an environment variable, which previously could not be set that way. [Commit](https://github.com/open-webui/open-webui/commit/fd56086e793a0eceb07a55ff972a5492d8f8a285) +- ✏️ **Edit prompts from the menu.** The prompts list now has an Edit option in each prompt's menu, taking you straight to its editor. [#25789](https://github.com/open-webui/open-webui/pull/25789) +- 📋 **Clone automations.** Automations now have a Clone option in their menu, so you can duplicate one as a starting point. [#25790](https://github.com/open-webui/open-webui/pull/25790) +- 🔁 **Recurring calendar events.** The calendar event editor now includes a repeat option, so events can recur on a schedule. [#25865](https://github.com/open-webui/open-webui/pull/25865) +- 🧷 **Separate skills import and export permissions.** Administrators can now control importing and exporting skills independently, with new skills import and export permissions. [#25921](https://github.com/open-webui/open-webui/pull/25921) +- 🏷️ **Filter admin models by tag.** The admin Models settings page now has a tag filter for narrowing the model list by base-model tags. [Commit](https://github.com/open-webui/open-webui/commit/2bdd2ab94eefd3d75dd6511c445e302f82221b5d) +- 📊 **Sortable analytics chat list.** The model chat list in analytics now has sortable column headers, so you can order it by title, last updated, or user. [Commit](https://github.com/open-webui/open-webui/commit/3730a9eaac68dff60b3ae5b4ed160b91480d66eb), [#26168](https://github.com/open-webui/open-webui/pull/26168) +- 🔐 **Argon2 password hashing option.** Password hashing can now use Argon2 through a configurable algorithm setting, removing the 72-byte password length limit that came with the previous default. [Commit](https://github.com/open-webui/open-webui/commit/33cd199e6dffddd4ee8974af41ebb894871d74c1), [Commit](https://github.com/open-webui/open-webui/commit/a70a6589afad0b429cdd77afa62163391f406a87), [#25656](https://github.com/open-webui/open-webui/pull/25656) +- 🔐 **Optional encryption of valve values at rest.** Tool and function valve values can now be encrypted at rest through a new opt-in setting, with existing stored values migrated automatically, so sensitive settings like API keys aren't kept in plaintext. [Commit](https://github.com/open-webui/open-webui/commit/b4073f6378392b23a3954e33031bf5e1d98e090a), [#23721](https://github.com/open-webui/open-webui/pull/23721) +- 🗄️ **AWS RDS IAM database authentication.** The database connection can now authenticate using AWS RDS IAM tokens through a new opt-in setting, instead of only a static password. [Commit](https://github.com/open-webui/open-webui/commit/c0c6c2181a8dc57b62e8a5eabd550bf89db7ffed), [#23580](https://github.com/open-webui/open-webui/pull/23580) +- 🔓 **Automatic auth for models with OAuth 2.1 tools.** When a model uses tools that require OAuth 2.1, Open WebUI now initiates the authorization flow automatically instead of failing the request. [Commit](https://github.com/open-webui/open-webui/commit/ae5d23f2267845922c2acb507a4a432908d03b41), [#23325](https://github.com/open-webui/open-webui/pull/23325), [#23272](https://github.com/open-webui/open-webui/issues/23272) +- 🔤 **Custom tokenizer for token-based text splitting.** Token-based document splitting can now use a configurable Hugging Face tokenizer model, so chunking can match the tokenizer of the model you use. [Commit](https://github.com/open-webui/open-webui/commit/bb6b2db88b1e82395531f67db4f6accd49d8b9eb), [#24139](https://github.com/open-webui/open-webui/pull/24139) +- 🔒 **Restrict OAuth scopes requested from MCP servers.** A new setting lets administrators limit which OAuth scopes Open WebUI requests when connecting to MCP servers. [Commit](https://github.com/open-webui/open-webui/commit/7be009649a0a94008484335c492ab0af18fde41f), [#25981](https://github.com/open-webui/open-webui/pull/25981), [#25978](https://github.com/open-webui/open-webui/issues/25978) +- 🧩 **Filter Outlet Hook can now run on API requests and responses.** A filter function's outlet hook now runs for direct API callers, including streaming responses, so response post-processing isn't limited to the web interface; this is controlled by a new setting and on by default. [Commit](https://github.com/open-webui/open-webui/commit/390e200f76877b185002c88b4dda27b123d29e83), [#25650](https://github.com/open-webui/open-webui/pull/25650) +- 🖥️ **Setting for terminal sidebar auto-open.** A new interface setting controls whether the files sidebar opens automatically when you select a terminal. [Commit](https://github.com/open-webui/open-webui/commit/958237473f8cbde97eb0df8c21f2a4de088c4459), [#25628](https://github.com/open-webui/open-webui/pull/25628) +- 📌 **Reorder pinned notes by dragging.** Pinned notes in the sidebar can now be dragged to reorder them. [#25677](https://github.com/open-webui/open-webui/pull/25677) +- 🔎 **Chat actions in search.** The search dialog now offers a context menu on each result, so you can act on a chat directly from search. [#25490](https://github.com/open-webui/open-webui/pull/25490) +- 🔎 **Snippets in chat search results.** Searching your chats now shows a snippet of the matching content in each result, so you can tell results apart at a glance. [Commit](https://github.com/open-webui/open-webui/commit/0eba3df1199f56e8ac77213772a41313a3237296), [Commit](https://github.com/open-webui/open-webui/commit/67a7b23b85d2e3ce6b094b682ba9f07dc453d355), [Commit](https://github.com/open-webui/open-webui/commit/8927c9bb3d4b04f4fc8e443f42089f2a551276bc), [#25178](https://github.com/open-webui/open-webui/pull/25178) +- 📝 **Formatted valve descriptions.** Valve descriptions for tools and functions now render Markdown, so they can include formatting and links. [Commit](https://github.com/open-webui/open-webui/commit/7c0b0e42f5afb0e9c39bd2d42e4822d64d0c7b3e) +- 🔽 **Dropdown inputs for valve options.** Valve and confirmation inputs can now present a set of options as a dropdown instead of free text, making fixed-choice settings easier to configure. [Commit](https://github.com/open-webui/open-webui/commit/422a4768ea7428b5dd6d401ccfba00e1e86eb98a), [#26278](https://github.com/open-webui/open-webui/pull/26278) +- 🔌 **Control the OAuth resource parameter for MCP connectors.** MCP connectors can now be set to always send, never send, or automatically decide whether to include the OAuth resource parameter, so they work with providers that reject it. [Commit](https://github.com/open-webui/open-webui/commit/5576e6ed8a80a4032b7c6cb3ee0cda0254019355) +- 🔎 **SERPHouse web search.** SERPHouse can now be used as a web search provider. [Commit](https://github.com/open-webui/open-webui/commit/3a232f5e9a4d31a6b74cb34d007b581feeb2f005), [Commit](https://github.com/open-webui/open-webui/commit/dd4f43bfdb793c4276e6468b65fc32d9b881578a), [#26254](https://github.com/open-webui/open-webui/pull/26254) +- 🔎 **Microsoft Web IQ web search.** Microsoft Web IQ can now be used as a web search provider, with a matching page-browse loader. [#26178](https://github.com/open-webui/open-webui/pull/26178) +- ⚠️ **Optional web search confirmation.** Administrators can now require users to confirm before a web search runs, with a banner and message making it clear when search is about to be used. [Commit](https://github.com/open-webui/open-webui/commit/fa76764c3b7f99c5adacd34dabd51ead09542c13), [#24942](https://github.com/open-webui/open-webui/pull/24942) +- 🪪 **Client User-Agent forwarded to model backends.** The browser's User-Agent is now passed through to all model backends, so upstream services can see the originating client. [#26333](https://github.com/open-webui/open-webui/pull/26333) +- 🖐️ **Drag items from the sidebar into chat.** Folders, notes, and models — including pinned notes — can now be dragged from the sidebar into the chat input. [#25771](https://github.com/open-webui/open-webui/pull/25771), [Commit](https://github.com/open-webui/open-webui/commit/dc1bc41d2e), [#26384](https://github.com/open-webui/open-webui/pull/26384) +- 🏷️ **Tag suggestions in the model editor.** The model editor now suggests existing tags as you type, making it easier to reuse a consistent set. [Commit](https://github.com/open-webui/open-webui/commit/b58b0ea7ca849b89d217e1077498a8a3fc92471f), [#25703](https://github.com/open-webui/open-webui/pull/25703) +- 🗣️ **Voice suggestions in the model editor.** The model editor now offers a dropdown of available text-to-speech voices, making it easier to pick one. [Commit](https://github.com/open-webui/open-webui/commit/a5c945940134b957dbad47790b5baafeecdac6c4), [#25706](https://github.com/open-webui/open-webui/pull/25706) +- 🎛️ **Unified model picker for workspace base model.** Choosing a base model in the model editor now uses the searchable model selector instead of a plain field, making it easier to find and pick the right model. [Commit](https://github.com/open-webui/open-webui/commit/c89fd237b822877bffbb33a37402622983c7189d), [#24576](https://github.com/open-webui/open-webui/issues/24576) +- 🔍 **Searchable pickers in the model editor.** Attaching actions, filters, tools, knowledge, and skills to a model now uses type-to-search pickers instead of long checkbox lists, making large libraries easier to manage. [Commit](https://github.com/open-webui/open-webui/commit/61cee42ded4e84e31d7cc9b168994ef165efa8ca) +- 🖼️ **iPhone images work with OpenAI image editing.** Uploaded images are now normalized before being sent to OpenAI image editing, fixing edits that failed for certain iPhone photo formats, with a new admin toggle to control the behavior. [Commit](https://github.com/open-webui/open-webui/commit/39837e0a3afd17b7ff617d97dddf4c5d6446e42d), [Commit](https://github.com/open-webui/open-webui/commit/2d3035a1122123df471ac9d0a591a9465a8212e2), [#26252](https://github.com/open-webui/open-webui/pull/26252), [#26249](https://github.com/open-webui/open-webui/issues/26249) +- 🟢 **Loaded-model indicator for llama.cpp.** Models served through llama.cpp now report whether they're currently loaded in memory, including the sleeping state, so the loaded indicator works for them too. [Commit](https://github.com/open-webui/open-webui/commit/b696c5deff15d4c85c84c5bac244f062b1bc879a) +- 🧱 **Structured model output rendered on the client.** Reasoning, tool calls, and server-side tool steps such as web and file search are now rendered in the browser from the model's structured output instead of being flattened into the message text on the server, giving more accurate and editable rendering of these items. [Commit](https://github.com/open-webui/open-webui/commit/0443ab3a61492799f1aaa449f89cbd8aa5912f57), [Commit](https://github.com/open-webui/open-webui/commit/c33fadc26671190c94d86485e6e2ef2f6fd486a3) +- 📜 **Custom CA bundle for outbound connections.** A new environment variable lets you point Open WebUI at a custom CA certificate bundle, and the per-connection SSL settings now accept a bundle path, so deployments behind a corporate or internal CA can keep certificate verification on instead of disabling it. [Commit](https://github.com/open-webui/open-webui/commit/a54878b14f044d4aa1d8cf5be6f8ce9fc4285438), [Commit](https://github.com/open-webui/open-webui/commit/8b9e28b50354307a314111262f6737b6d8aa4685) +- 🖥️ **More terminal server orchestrator controls.** Admins connecting an orchestrator terminal server can now configure session lifecycle policies and refresh or reset running terminal sessions, including targeting only idle ones, from the connection settings. [Commit](https://github.com/open-webui/open-webui/commit/7e8153e889a59afe4cf77261ea5e1ef5a66665f1) +- 📁 **Terminal file browser can stay within a root folder.** The terminal file navigator now anchors to a defined root and home directory, so users can be kept within their workspace instead of browsing into system folders by accident. [Commit](https://github.com/open-webui/open-webui/commit/a0c2ec3d2cf8d696ede479211330eec2da360d39) +- 🧠 **Memory toggle follows the server default.** When a user hasn't set their own memory preference, it now follows the admin's global memory setting instead of defaulting to off. [#25909](https://github.com/open-webui/open-webui/pull/25909) +- 🧹 **Unshare all shared chats at once.** The Shared Chats dialog now has a button to stop sharing every shared chat in one action. [#25848](https://github.com/open-webui/open-webui/pull/25848) +- 📈 **Richer analytics with a date picker.** The analytics dashboard now lets you choose a date range and shows additional columns. [#25922](https://github.com/open-webui/open-webui/pull/25922), [#25919](https://github.com/open-webui/open-webui/issues/25919) +- 🔢 **Chat and file counts in their dialogs.** The Chats and Files dialogs now show the total number of chats and files in their titles. [#25872](https://github.com/open-webui/open-webui/pull/25872), [#25873](https://github.com/open-webui/open-webui/pull/25873) +- ⚡ **Faster math rendering.** Rendered math is now cached and reused, so messages with repeated or unchanged math expressions render more efficiently. [#25847](https://github.com/open-webui/open-webui/pull/25847) +- ⚡ **Lighter Markdown setup.** Markdown extension setup now runs once instead of on every render, avoiding repeated work and extension stacking. [#25837](https://github.com/open-webui/open-webui/pull/25837) +- ⚡ **Snappier read-only code blocks.** Read-only code blocks now skip language auto-detection, so they render faster. [#25824](https://github.com/open-webui/open-webui/pull/25824) +- ⚡ **Non-blocking audio model loading.** Loading speech models no longer blocks the server, keeping it responsive while they initialize. [#25806](https://github.com/open-webui/open-webui/pull/25806) +- ⚡ **Faster URL safety checks.** The safety check on fetched URLs now resolves addresses off the main loop, so it no longer blocks other work. [#25825](https://github.com/open-webui/open-webui/pull/25825) +- ⚡ **Fewer queries for channel reactions and replies.** Channel reactions and thread replies now load through batched queries, reducing database load on busy channels. [#25831](https://github.com/open-webui/open-webui/pull/25831) +- ⚡ **Lighter streaming.** Streaming responses now skip re-processing message content that hasn't changed, reducing work on every update. [#26325](https://github.com/open-webui/open-webui/pull/26325), [#26326](https://github.com/open-webui/open-webui/pull/26326) +- ⚡ **Smoother tool-call rendering.** Displaying tool calls now parses their content iteratively, avoiding slowdowns on deeply nested data. [#26146](https://github.com/open-webui/open-webui/pull/26146) +- ⚡ **Hidden tool-call details cost nothing.** When tool-call arguments are collapsed, they are no longer rendered behind the scenes, noticeably speeding up chats with heavy tool use. [Commit](https://github.com/open-webui/open-webui/commit/b7934e918223ec0a9e972accd647a8654e503156), [#26147](https://github.com/open-webui/open-webui/pull/26147) +- ⚡ **Leaner knowledge-file reading for agents.** The built-in tools that let a model read knowledge files now return output in bounded, paginated chunks with a default and a hard cap, instead of potentially returning an entire large file at once, sharply reducing token usage. [Commit](https://github.com/open-webui/open-webui/commit/a285a390c12e27e614d1ba9ffb92d1a0e49e7dfa), [#26139](https://github.com/open-webui/open-webui/issues/26139) +- ⚡ **Lighter, faster file search on large knowledge bases.** Listing and searching files no longer returns each file's full extracted text by default, and content matching is now length-bounded, so these requests are far lighter and searching across very large knowledge bases is dramatically faster. [Commit](https://github.com/open-webui/open-webui/commit/36d08fa2a7), [Commit](https://github.com/open-webui/open-webui/commit/46c1d6591badb6ab567ba1b8fae23475d5da105a), [Commit](https://github.com/open-webui/open-webui/commit/ab84bbf08c5935f1a19044ef581986f83311da8b), [#25774](https://github.com/open-webui/open-webui/pull/25774), [#25741](https://github.com/open-webui/open-webui/issues/25741), [#26145](https://github.com/open-webui/open-webui/pull/26145), [#25867](https://github.com/open-webui/open-webui/issues/25867) +- ⚡ **Faster password hashing and bulk user import.** Password hashing and verification no longer block the server, and importing users from a CSV is now processed in a single batch, keeping large imports and sign-ins responsive. [Commit](https://github.com/open-webui/open-webui/commit/6fdf9b4340), [#25804](https://github.com/open-webui/open-webui/pull/25804), [#25805](https://github.com/open-webui/open-webui/pull/25805) +- ⚡ **Non-blocking model downloads.** Downloading large Ollama models no longer blocks the server on file reads and checksums, keeping it responsive during big downloads. [#25829](https://github.com/open-webui/open-webui/pull/25829) +- ⚡ **Non-blocking uploads and link fetches.** Hashing uploaded files and fetching URLs now run off the main loop, so large uploads and link previews don't hold up other requests. [#25822](https://github.com/open-webui/open-webui/pull/25822) +- ⚡ **More blocking work moved off the main loop.** Additional blocking operations in audio, pipelines, and plugin handling now run in worker threads, keeping the server responsive under load. [#26381](https://github.com/open-webui/open-webui/pull/26381) +- ⚡ **Unreachable backends don't stall model loading.** Loading models and tool servers no longer blocks on backends that are down or slow to respond, so the model list stays responsive when one connection is unreachable. [#26289](https://github.com/open-webui/open-webui/pull/26289) +- ⚡ **Batched streaming updates.** Streaming responses now group small updates of the same type before sending them, reducing overhead during fast token streams and tool-call output. [Commit](https://github.com/open-webui/open-webui/commit/7240517807a8b0097065f7cbbb384d34084f90fd), [#26202](https://github.com/open-webui/open-webui/pull/26202) +- 🔄 **General improvements.** Various improvements were implemented across the application to enhance performance, stability, and security. +- 🌐 **Updated translations.** Catalan, Brazilian Portuguese (pt-BR), Irish, German (de-DE), and Spanish (es-ES) translations were updated. + +### Fixed + +- 🛡️ **Security Advisory**: This release includes security and access-control fixes. We recommend updating production deployments at your earliest convenience. Not all security fixes in this version may be enumerated in the fixed section — some may be withheld for a short time to give administrators time to upgrade. [Advisories](https://github.com/open-webui/open-webui/security) +- 🔐 **Knowledge base write access enforced on upload.** Attaching an uploaded file to a knowledge base now requires the same write access as the rest of the knowledge API, so users without write access can no longer add files to a collection by referencing its ID. [#26001](https://github.com/open-webui/open-webui/pull/26001) +- 🗝️ **API key permission enforced on all key endpoints.** Viewing and deleting API keys now respects the API keys permission, matching the protection already applied to key creation. [#25992](https://github.com/open-webui/open-webui/pull/25992) +- 🔊 **Text-to-speech permission enforced on the speech endpoint.** The OpenAI speech proxy now honors the text-to-speech permission, so it can no longer be used by people who are not allowed to use that feature. [#25993](https://github.com/open-webui/open-webui/pull/25993) +- 🎲 **Model access enforced on arena fallback.** Reaching a model indirectly through an arena model on background and task requests now enforces that model's access rules, closing a path that could otherwise bypass them. [#26046](https://github.com/open-webui/open-webui/pull/26046) +- ⏰ **Scheduled automations stop for deactivated accounts.** Scheduled automations now re-check the owner's account status and permissions before each run, so they stop when an account is deactivated or has automations access revoked. [#26047](https://github.com/open-webui/open-webui/pull/26047) +- 🚧 **Heavily encoded paths rejected behind the proxy.** Request paths that remain encoded after repeated decoding are now rejected instead of forwarded, preventing a path traversal that could otherwise slip through. [#26050](https://github.com/open-webui/open-webui/pull/26050) +- 🌐 **Image URL fetches hardened against DNS rebinding.** Fetching user-supplied image URLs now re-checks the destination address at connection time, closing a path that could be used to reach internal addresses behind a public hostname. [#25960](https://github.com/open-webui/open-webui/pull/25960) +- 🛂 **Web fetch blocklist matches on hostname.** The web fetch filter now matches entries against the request's hostname on domain boundaries, so blocked hosts can no longer slip through with an added path and lookalike domains are no longer mistaken for allowed ones. [#25949](https://github.com/open-webui/open-webui/pull/25949) +- 🪪 **MCP connectors request least-privilege scopes.** MCP connectors that register dynamically over OAuth now request only the scopes for the specific resource rather than the authorization server's full catalog. [#25958](https://github.com/open-webui/open-webui/pull/25958) +- 🙈 **Channel member lists no longer expose private data.** Viewing a channel's members now returns only basic profile details, instead of also exposing other members' settings, linked-account data, and personal information. [Commit](https://github.com/open-webui/open-webui/commit/fbcdcf146b99b5002705060a8243eee769108f9e) +- 🛟 **SCIM sync can't demote an admin.** A SCIM provisioning sync that marks a user inactive can no longer strip an existing administrator's role, preventing an instance from being locked out of its own administration. [#25948](https://github.com/open-webui/open-webui/pull/25948) +- 👻 **Collaborative notes reject unauthenticated presence events.** The remaining real-time note-collaboration events now require an authenticated session, so presence and cursors can no longer be spoofed by someone who only knows a note's ID. [#25946](https://github.com/open-webui/open-webui/pull/25946) +- ⏱️ **Login timing no longer reveals which accounts exist.** Sign-in now takes the same amount of time whether or not an account exists, removing a timing difference that could be used to discover valid accounts. [Commit](https://github.com/open-webui/open-webui/commit/993e74912199c66c522f08ec81abe31d76985e39), [Commit](https://github.com/open-webui/open-webui/commit/7b29834d4216e5db70b68f3598fa1ad654d3512b) +- 🔌 **Terminal connections can't be redirected to another user.** Terminal session identifiers are now safely encoded before being passed upstream, closing a way to tamper with the connection's user identity. [#26042](https://github.com/open-webui/open-webui/pull/26042) +- 📡 **Real-time events only reach your own session.** The server now verifies that a real-time event is delivered only to the requesting user's own active session, instead of trusting a client-supplied session identifier. [#25763](https://github.com/open-webui/open-webui/pull/25763) +- 🔓 **Revoked sessions are rejected on real-time connections.** Real-time and terminal WebSocket connections now honor token revocation and expiry, so a signed-out or expired session can no longer keep a live connection open. [Commit](https://github.com/open-webui/open-webui/commit/33b91bd8ae8a100a5a306c91441a7d0b422c4cde), [#25764](https://github.com/open-webui/open-webui/pull/25764), [#25686](https://github.com/open-webui/open-webui/pull/25686) +- 🕳️ **Another DNS-rebinding gap closed in URL fetching.** Fetching a URL's content now re-checks the destination address at connection time, closing another path that could reach internal addresses behind a public hostname. [#25775](https://github.com/open-webui/open-webui/pull/25775) +- 🗣️ **Azure speech input is escaped.** Voice and language values are now escaped when building Azure text-to-speech requests, preventing malformed or injected markup. [#25776](https://github.com/open-webui/open-webui/pull/25776) +- ⚙️ **Interface settings update respects its permission.** Saving interface settings now enforces the interface permission, so users without it can no longer change those settings through the API. [#25996](https://github.com/open-webui/open-webui/pull/25996) +- 🗄️ **Unknown knowledge collections are denied by default.** Retrieval now rejects unknown or unscoped collection names by default, closing a legacy path that could be used to reach collections outside the normal access checks. [Commit](https://github.com/open-webui/open-webui/commit/d99ac7d3f83b25161ca775229150c8f7c74cceee) +- 🙈 **Error responses no longer leak internals.** Server error responses now return sanitized messages instead of raw exception text, so internal details aren't exposed to signed-in users. [Commit](https://github.com/open-webui/open-webui/commit/ee5de69e374aabf5631da18a5bbc1c285ee6f7a1), [Commit](https://github.com/open-webui/open-webui/commit/0cc331d1c60341bb06b78ceeecfb2db86179c93e), [Commit](https://github.com/open-webui/open-webui/commit/396d9ac18193d43e40fb9d068075d4b780e971d7), [Commit](https://github.com/open-webui/open-webui/commit/0883638027a9b3cb7c9851f031c4f5fc1af1f25d), [#26375](https://github.com/open-webui/open-webui/pull/26375), [#26374](https://github.com/open-webui/open-webui/issues/26374) +- 📏 **Upload size limit enforced on the server.** The maximum upload size is now enforced server-side, so it can't be bypassed by a client that ignores the limit. [Commit](https://github.com/open-webui/open-webui/commit/f8ec63203c4408c46bb06698ae624d17b01b9301), [Commit](https://github.com/open-webui/open-webui/commit/d3676b4f71bfdbaf4e4d76943c51117e18932ccf), [#25869](https://github.com/open-webui/open-webui/pull/25869) +- 🖼️ **OAuth profile pictures are validated.** Profile picture URLs from OAuth providers are now validated and their type checked when stored, preventing unsafe image sources. [Commit](https://github.com/open-webui/open-webui/commit/eb53281c9acb3660e09554a8dbde0a0b42646b70), [#24548](https://github.com/open-webui/open-webui/pull/24548) +- 📦 **Security updates to frontend dependencies.** Several frontend dependencies were updated to patch known security vulnerabilities. [#26281](https://github.com/open-webui/open-webui/pull/26281) +- 🤝 **Chat sharing respects the user-sharing permission.** The share-chat dialog now hides the option to share with specific users from people who lack that permission, matching the access rules enforced elsewhere. [#25915](https://github.com/open-webui/open-webui/pull/25915) +- 📤 **Chat export respects its permission everywhere.** Every chat export menu now checks the export permission, so users without it can no longer export chats through one of the dropdown menus. [#25914](https://github.com/open-webui/open-webui/pull/25914) +- 📂 **File write access requires real ownership.** Editing or deleting a file through a knowledge base or workspace model now requires that the object's owner actually owns the file, so a read-only file can no longer gain write access by being referenced from an object you control. [#26032](https://github.com/open-webui/open-webui/pull/26032) +- 🖌️ **Image edit endpoint enforces permission.** The image-edit endpoint now checks the image-edit switch and the image-generation permission, matching image generation, so it can't be called by users who lack access. [#26009](https://github.com/open-webui/open-webui/pull/26009) +- 📁 **Folder permission enforced on all folder actions.** Every folder operation now checks the folders permission, so the setting is respected consistently instead of only when listing folders. [Commit](https://github.com/open-webui/open-webui/commit/19a176fd36bea15c49d7f2d1539b4832e57a8bc2) +- 🧩 **Code Execution settings collapse when off.** The Code Execution settings section now collapses when the toggle is disabled, keeping the settings page tidy. [#25970](https://github.com/open-webui/open-webui/pull/25970) +- 📅 **German date format in Notes.** Dates in the Notes view now display correctly for German, where they previously failed to render. [#25985](https://github.com/open-webui/open-webui/pull/25985) +- 🎙️ **ElevenLabs speech keeps working when voices can't load.** Text-to-speech through ElevenLabs no longer fails when the available-voice list can't be fetched, instead of rejecting every voice. [Commit](https://github.com/open-webui/open-webui/commit/bb1419328b11b801b4c939dfc112700ba6f6fdab), [#26075](https://github.com/open-webui/open-webui/issues/26075) +- 🪟 **Default Permissions modal resets on close.** Closing the Default Permissions dialog without saving now discards unsaved edits instead of keeping them around the next time you open it. [Commit](https://github.com/open-webui/open-webui/commit/78a5015846a9e55ff2bc9d6cc98f880437abe8ed) +- 👯 **Side-by-side chat with the same model.** Running two panes with the same model no longer leaves one pane stuck waiting or showing the other pane's reply after a reload, since each pane's messages are now tracked separately. [Commit](https://github.com/open-webui/open-webui/commit/56ae99e96a845289b5787d2dd26a3d828f2295e7), [#25982](https://github.com/open-webui/open-webui/issues/25982) +- 💾 **Model edits no longer lost when changing access.** Adjusting a model's access no longer auto-saves on its own and discards your other unsaved changes to that model. [#26004](https://github.com/open-webui/open-webui/pull/26004) +- 🔧 **Parallel tool calls over the Anthropic-compatible API.** External Anthropic-compatible clients calling Open WebUI's messages endpoint now receive tool calls reliably when a model issues several at once or returns them in its final message. [Commit](https://github.com/open-webui/open-webui/commit/4210cae68e30173d7902582d32128dd699d5628a), [#25963](https://github.com/open-webui/open-webui/pull/25963), [#25964](https://github.com/open-webui/open-webui/discussions/25964) +- 🗃️ **Prompt caching preserved over the Anthropic-compatible API.** Requests through the Anthropic-compatible API now keep their prompt-caching markers instead of having them stripped, so clients that rely on caching work as intended. [Commit](https://github.com/open-webui/open-webui/commit/caedcbae4988ef59ea7052b2a3198e2da4b5291a), [#25998](https://github.com/open-webui/open-webui/pull/25998), [#25964](https://github.com/open-webui/open-webui/discussions/25964) +- 🔁 **Fewer redundant data loads.** Several views no longer fire duplicate background fetches at once, avoiding occasional glitches from overlapping requests. [#25943](https://github.com/open-webui/open-webui/pull/25943), [#25942](https://github.com/open-webui/open-webui/pull/25942), [#25934](https://github.com/open-webui/open-webui/pull/25934), [#25935](https://github.com/open-webui/open-webui/pull/25935), [#25838](https://github.com/open-webui/open-webui/pull/25838), [Commit](https://github.com/open-webui/open-webui/commit/e8d55c0a8beac9de0b2a0fe90f0bc0f9b64c1c1f) +- 🔎 **Steadier search boxes across admin and workspace.** Search fields for users, knowledge, prompts, tools, and similar lists now run only as you type and reset to the first page correctly, instead of occasionally re-searching on their own. [Commit](https://github.com/open-webui/open-webui/commit/fc9c2ea1915accd1f6edca467e965283dff71cd7), [#25938](https://github.com/open-webui/open-webui/pull/25938) +- 📊 **Admin feedback list loads again on PostgreSQL.** The admin feedback list no longer fails to load on PostgreSQL setups, where it previously returned a server error. [Commit](https://github.com/open-webui/open-webui/commit/7ee75a0c04a31528954903e88c9213d5fbb31aa7), [#25953](https://github.com/open-webui/open-webui/issues/25953) +- 🗂️ **Deleting nested folders checks chats correctly.** Deleting a folder that contains subfolders now accounts for the chats inside those subfolders when applying the delete-permission check, instead of only the top-level folder's chats. [Commit](https://github.com/open-webui/open-webui/commit/232421f40b84590e6d6fdecab4e43274aac37add), [#25920](https://github.com/open-webui/open-webui/issues/25920) +- 🖱️ **Dragging chats into folders is more reliable.** Dragging a chat into a folder no longer throws an error in cases where the chat couldn't be resolved. [#25928](https://github.com/open-webui/open-webui/pull/25928) +- 🛠️ **Workspace menu shows for the skills permission.** Users who only have the skills permission now see the Workspace entry in their menu, which previously appeared only for other workspace permissions. [#25925](https://github.com/open-webui/open-webui/pull/25925) +- 🧠 **Admins can always reach memories.** Administrators can now use the memories endpoints regardless of the memories permission toggle, matching how admin access works for other features. [#25924](https://github.com/open-webui/open-webui/pull/25924) +- 🖼️ **Image settings page survives a config load failure.** The admin image settings page no longer crashes when its configuration fails to load, showing the page instead. [#25933](https://github.com/open-webui/open-webui/pull/25933) +- 🧵 **Code blocks render in channel threads.** Code blocks now display correctly in a channel's thread view, where duplicated message identifiers previously broke their rendering. [Commit](https://github.com/open-webui/open-webui/commit/7d1f9415807a47e0da4f862327e9802a3b839753), [#25917](https://github.com/open-webui/open-webui/pull/25917) +- 🔵 **No more false unread badges on chats.** Chats no longer show an unread indicator after automatic changes like title generation or pinning, archiving, and moving them between folders, and newly created chats are marked read correctly so they don't appear unread after a refresh. [#25912](https://github.com/open-webui/open-webui/pull/25912), [#25782](https://github.com/open-webui/open-webui/pull/25782), [#25108](https://github.com/open-webui/open-webui/issues/25108) +- 📌 **Pinned notes stay in sync.** Pinning, unpinning, or deleting a note now updates the sidebar's pinned list consistently, instead of showing a stale pin state. [#25918](https://github.com/open-webui/open-webui/pull/25918), [#25640](https://github.com/open-webui/open-webui/pull/25640) +- 📅 **All-day calendar events keep their date.** Saving an all-day calendar event no longer shifts it by a day for users in certain time zones. [#25864](https://github.com/open-webui/open-webui/pull/25864) +- 🧷 **Damaged chat history recovers more reliably.** When a chat's current position is missing or points at a malformed message, Open WebUI now repairs it from the latest valid message — on both the client and the server — instead of risking a broken history view. [Commit](https://github.com/open-webui/open-webui/commit/2308b59f135e4c2da11eabdf2306e55a5dd4e9fb), [Commit](https://github.com/open-webui/open-webui/commit/a146e17bdcaf94fee3a98aa36b4f401e1f06c1d4), [#26298](https://github.com/open-webui/open-webui/pull/26298), [#26258](https://github.com/open-webui/open-webui/pull/26258), [#26257](https://github.com/open-webui/open-webui/issues/26257) +- 💾 **Saving a chat no longer drops messages.** Chat updates are now merged with the existing history on the server, with explicit tracking of deleted messages, instead of overwriting it, preventing message loss from concurrent or partial saves. [Commit](https://github.com/open-webui/open-webui/commit/22a44e67a8ba781feb8f2a267fed0c40213d8432), [Commit](https://github.com/open-webui/open-webui/commit/3319b6410e1b600b7a885a5fb78573e9a2061c22), [Commit](https://github.com/open-webui/open-webui/commit/24b8619f64731788ac38813768abbb64405effa4), [#25657](https://github.com/open-webui/open-webui/pull/25657) +- 📺 **Channel message updates stay in their channel.** Streaming updates to a channel message are now skipped if the message no longer exists or belongs to a different channel, preventing stray updates. [Commit](https://github.com/open-webui/open-webui/commit/ac3449cac91e62b08a7c28e54fcd044d14dea791) +- 📌 **Pinned channel messages update for everyone.** Pinning or unpinning a channel message now updates live for all members and works from thread views, instead of only changing for the person who pinned it. [Commit](https://github.com/open-webui/open-webui/commit/7ea7680f563da30b121258e5a7d7123185c4da2a) +- 📄 **Mistral OCR uploads work again.** Document OCR through Mistral has been repaired after an upstream library change broke its file uploads. [#25779](https://github.com/open-webui/open-webui/pull/25779) +- 🗂️ **Chroma collection detection fixed.** Open WebUI now correctly detects existing Chroma collections, fixing a case where it always reported them as missing. [#25780](https://github.com/open-webui/open-webui/pull/25780) +- 📊 **Vega-Lite charts render reliably.** Vega-Lite charts in chat are now detected by their code block language tag, so they render correctly. [#25843](https://github.com/open-webui/open-webui/pull/25843) +- 🏷️ **Long chat tag lists scroll.** The tags section in the chat menu now scrolls instead of overflowing when a chat has many tags. [#26031](https://github.com/open-webui/open-webui/pull/26031) +- ⌨️ **Enter key shows correctly on iOS.** The Enter key symbol in the keyboard shortcuts list no longer renders as an emoji on iOS. [#26173](https://github.com/open-webui/open-webui/pull/26173) +- 🔗 **Whitespace in names no longer breaks MCP connections.** User name and info headers are now trimmed before being forwarded, fixing MCP connection failures when a display name contained leading or trailing whitespace. [#26182](https://github.com/open-webui/open-webui/pull/26182), [#26181](https://github.com/open-webui/open-webui/issues/26181) +- 🈳 **Search no longer fires mid-composition.** Typing in search with an input method editor (such as Japanese, Chinese, or Korean) no longer triggers a search when you press Enter to confirm a composition. [#26238](https://github.com/open-webui/open-webui/pull/26238), [#26285](https://github.com/open-webui/open-webui/pull/26285), [#26172](https://github.com/open-webui/open-webui/issues/26172) +- 🧰 **Valves icon stays visible.** The icon for configuring valves no longer disappears, so user-configurable tool and function settings remain reachable. [#26256](https://github.com/open-webui/open-webui/pull/26256) +- 🎛️ **Chat controls persist across navigation.** Edits to chat controls are now kept when navigating between chats, and reverting a control to the chat's saved value persists correctly, instead of being lost. [#26336](https://github.com/open-webui/open-webui/pull/26336), [#25793](https://github.com/open-webui/open-webui/pull/25793) +- 🔍 **Chat search tool handles empty queries.** The built-in chat search tool no longer crashes when called with an empty query. [Commit](https://github.com/open-webui/open-webui/commit/b854eb09b13216f914ce5fd07ab717b8f752882b), [#26310](https://github.com/open-webui/open-webui/issues/26310) +- 📑 **More robust MinerU document processing.** Document processing through MinerU now handles its ZIP results more safely, including very large outputs. [Commit](https://github.com/open-webui/open-webui/commit/23d03d6aaebcced6c1e39e98dfff76ab73df8804), [#26263](https://github.com/open-webui/open-webui/pull/26263) +- ⏰ **Scheduled automations with session-auth tools work.** Automations that use session-authenticated tools or terminals now authenticate correctly when running on a schedule, instead of failing. [Commit](https://github.com/open-webui/open-webui/commit/5b1c42e81a3ef3ad5ce5852dbf84020cb5e2498c), [#26247](https://github.com/open-webui/open-webui/pull/26247), [#26137](https://github.com/open-webui/open-webui/issues/26137) +- 📝 **Model system prompt preserved with knowledge.** A model's system prompt is no longer dropped when knowledge retrieval runs with native tool calling. [Commit](https://github.com/open-webui/open-webui/commit/cfb49c4c181a96d5df07fbfacd819639baef0bab), [#26217](https://github.com/open-webui/open-webui/pull/26217) +- 🔑 **Expired sessions return you to sign-in.** When a request fails because your session has expired, Open WebUI now redirects you to the sign-in page instead of leaving you on a broken view. [Commit](https://github.com/open-webui/open-webui/commit/5922727402593900758d84004f950071c701f6de), [#26237](https://github.com/open-webui/open-webui/pull/26237) +- 🎯 **Ejecting a workspace model unloads the right model.** Unloading a workspace model now resolves to its underlying base model, so the correct model is freed from memory. [Commit](https://github.com/open-webui/open-webui/commit/464e703e4716812d015966582152ddd8a2c71572), [#26269](https://github.com/open-webui/open-webui/pull/26269) +- 🔄 **Edited models refresh in the admin list.** After editing a model in the admin settings, the models list now updates right away instead of needing a manual reload. [Commit](https://github.com/open-webui/open-webui/commit/b34d6c836ee43d0e9721fa4fd6457d934e3e2a17) +- 🗂️ **Workspace model bulk actions and search work across pages.** Bulk actions on workspace models now apply across all of them, and search results paginate correctly. [#26274](https://github.com/open-webui/open-webui/pull/26274) +- 🧩 **MCP resource results come through.** Tool results that return resource content — including binary blobs and URI references — are no longer silently dropped, and image results are attached as files. [#25260](https://github.com/open-webui/open-webui/pull/25260), [#24038](https://github.com/open-webui/open-webui/issues/24038), [Commit](https://github.com/open-webui/open-webui/commit/783205a965c556815fae84b64d74f26a2e5e5729) +- 🔗 **Broader MCP server compatibility for OAuth.** Open WebUI now discovers an MCP server's protected resource metadata even when the server doesn't advertise it, and recognizes more OAuth preflight variations, so more MCP servers connect. [#25980](https://github.com/open-webui/open-webui/pull/25980), [#25954](https://github.com/open-webui/open-webui/issues/25954), [Commit](https://github.com/open-webui/open-webui/commit/45fea34bd0c8ce54b0822499c40e3e6964220354), [#26068](https://github.com/open-webui/open-webui/pull/26068) +- 📤 **Clearer upload error messages.** Failed uploads now show a readable explanation instead of an opaque error stub. [#25961](https://github.com/open-webui/open-webui/pull/25961) +- 📋 **Cloned prompts get a proper title.** Cloning a prompt now adds the clone suffix to the correct field, so the duplicate is named as expected. [#25800](https://github.com/open-webui/open-webui/pull/25800) +- 📐 **Long default group names don't overflow.** A long default group name no longer overflows its row in the admin authentication settings. [#25685](https://github.com/open-webui/open-webui/pull/25685) +- 🖐️ **Sidebar drags don't trigger uploads.** Dragging a chat item in the sidebar no longer shows the file-upload overlay. [#25675](https://github.com/open-webui/open-webui/pull/25675) +- 🔁 **Recovers from a stuck streaming response.** If the signal that a response finished is missed — for example after a mobile app is backgrounded mid-stream — Open WebUI now recovers the chat instead of leaving it stuck in a streaming state. [Commit](https://github.com/open-webui/open-webui/commit/aa851d93c63e7da6e94292d0b7586674339d47e5), [Commit](https://github.com/open-webui/open-webui/commit/edf2c6c8f76e7f6a5917e991f371a604adc34c5f), [Commit](https://github.com/open-webui/open-webui/commit/2856def6c05b2fb8c55b4e7170f05db0c4f956f1), [#26320](https://github.com/open-webui/open-webui/pull/26320), [#26315](https://github.com/open-webui/open-webui/issues/26315) +- 🧠 **Model skills load on demand instead of filling the prompt.** A model's attached skills are now presented to the model as a manifest it can load when needed, rather than having their full content inserted into the system prompt; skills you mention inline still get their content included directly. [Commit](https://github.com/open-webui/open-webui/commit/e6d35fc4cca4f4b1e5cad97d7b7e3089ef832018), [Commit](https://github.com/open-webui/open-webui/commit/44b9463498085741669e6f5d92e21b5ecc5fd795), [#25592](https://github.com/open-webui/open-webui/issues/25592), [#25599](https://github.com/open-webui/open-webui/pull/25599) +- 🗂️ **Empty metadata no longer breaks Chroma indexing.** Document metadata with empty values is now filtered out before indexing, fixing a case that could fail on Chroma. [Commit](https://github.com/open-webui/open-webui/commit/118549caf3), [#26342](https://github.com/open-webui/open-webui/pull/26342), [#26339](https://github.com/open-webui/open-webui/issues/26339) +- 🔁 **Updating a knowledge file won't break the knowledge base.** When a file's content is updated, its new embeddings are now added before the old ones are removed, so a failed reindex leaves the knowledge base intact and usable instead of empty. [Commit](https://github.com/open-webui/open-webui/commit/248315de14d4537e0f2ec3f94dee8a7334cad248), [#23789](https://github.com/open-webui/open-webui/pull/23789), [#23787](https://github.com/open-webui/open-webui/issues/23787) +- 🔤 **Documents with special tokens index correctly.** Measuring chunk sizes no longer fails when a document contains text that looks like a special token. [#26210](https://github.com/open-webui/open-webui/pull/26210) +- 📝 **Note file attachments stay in sync.** Updating the files attached to a note now keeps the editor and saved note in sync. [Commit](https://github.com/open-webui/open-webui/commit/5055fb85aa8c8d5ef785daea7438498e36ddf33f) +- 📱 **Better banner layout on mobile.** Notification banners now lay out correctly on small screens. [Commit](https://github.com/open-webui/open-webui/commit/4ed45ce84394c435405f93d03f07dabd797cdec3), [#24912](https://github.com/open-webui/open-webui/pull/24912) +- 📂 **Knowledge file listing includes attached files.** Listing files through the knowledge tools now also shows files attached directly to a model, not only those inside a knowledge base, fixing cases where listing returned no results for a model with a single attached file. [Commit](https://github.com/open-webui/open-webui/commit/40b655e99e2c6dd802654ec0cdac38a4bcda08b3), [#26301](https://github.com/open-webui/open-webui/issues/26301) +- 🏷️ **Chat titles generate after long first responses.** A new chat now gets its title even when the first response takes a long time, such as one with extensive reasoning or many tool calls, instead of staying "New Chat". [Commit](https://github.com/open-webui/open-webui/commit/754787f43dffad3dce2c90e4fd0417b1f9dbb3c0), [#26240](https://github.com/open-webui/open-webui/issues/26240) +- 🔌 **Cancelling an MCP request no longer errors.** Stopping a response that was using MCP tools now shuts the connection down cleanly instead of surfacing a server error. [Commit](https://github.com/open-webui/open-webui/commit/ff5cec43bd360829cfdcc6a5253d1ba63f236b7f) +- 🧠 **Reasoning details preserved across turns.** Models that return structured or encrypted reasoning data, such as Gemini, no longer have their assistant message split mid-stream, keeping reasoning continuity across turns. [Commit](https://github.com/open-webui/open-webui/commit/75db531c1238af113bb2b211882713e5e2f459cf), [#23852](https://github.com/open-webui/open-webui/pull/23852) +- 📡 **Error messages show for non-standard streaming responses.** Providers that send errors over non-standard server-sent events now surface a readable error instead of nothing. [#23228](https://github.com/open-webui/open-webui/pull/23228) +- 🔑 **Whitespace in terminal server keys no longer breaks auth.** Terminal server API keys are now trimmed before use, so a key with stray leading or trailing whitespace still authenticates. [Commit](https://github.com/open-webui/open-webui/commit/fe3300bd6581aa469c2cdf757700ecc65a200df4), [Commit](https://github.com/open-webui/open-webui/commit/d6cda4a04b2e3a48855fc91abb2376cfd3a0378d) +- 🔥 **One bad URL no longer fails Firecrawl scraping.** When fetching multiple pages through Firecrawl, a single failing URL is now skipped instead of aborting the whole batch, and rate limits are respected between requests. [Commit](https://github.com/open-webui/open-webui/commit/6f8221df58b17334233ac6bfe069b8f837f677d6), [#24183](https://github.com/open-webui/open-webui/pull/24183) +- 📱 **Usable chat input on mobile with many tools.** When skills, tools, terminal, web search, and image generation buttons fill the chat input, the row of buttons now scrolls horizontally while the menu, voice, and send controls stay reachable, instead of pushing them off-screen. [Commit](https://github.com/open-webui/open-webui/commit/6f8221df58b17334233ac6bfe069b8f837f677d6), [#26142](https://github.com/open-webui/open-webui/issues/26142) +- 👤 **Owner avatars only show on shared folders.** Chat owner avatars in a folder's chat list now appear only when the folder is actually shared, instead of showing whenever owner information happened to be present. [Commit](https://github.com/open-webui/open-webui/commit/9802b0d13563b3535b86a350bab000d84686b1e9) +- 📜 **No stray scrollbar on the About page.** Extra spacing that caused an unnecessary scrollbar on the About settings page has been removed. [#25802](https://github.com/open-webui/open-webui/pull/25802) +- 🚪 **Sign out works from the Account Pending page.** Signing out while your account is pending now goes through the proper sign-out flow, so single sign-on sessions are ended and you are no longer left stuck on the pending screen. [#25681](https://github.com/open-webui/open-webui/pull/25681), [#25644](https://github.com/open-webui/open-webui/issues/25644) +- 🔢 **Built-in tools accept numeric arguments.** Built-in tools no longer crash when a model passes a number or a string where a specific scalar type is expected; values are now coerced to the declared type. [Commit](https://github.com/open-webui/open-webui/commit/c4688b958d7f7929f5f4303493ca311c2c121683), [#25638](https://github.com/open-webui/open-webui/pull/25638), [#25731](https://github.com/open-webui/open-webui/pull/25731), [#25641](https://github.com/open-webui/open-webui/issues/25641) +- ⏱️ **MinerU timeout saves.** The MinerU API timeout can now be saved from the admin settings, accepting a numeric value. [Commit](https://github.com/open-webui/open-webui/commit/3fd0384ffcd0eddd6f4c688475f8ad5d3b4de510), [#25604](https://github.com/open-webui/open-webui/pull/25604), [#25603](https://github.com/open-webui/open-webui/issues/25603) +- 🔧 **Background completion no longer clears active tasks.** Finishing a chat in the background no longer wipes the set of active tasks, fixing a case where ongoing task indicators could be lost. [Commit](https://github.com/open-webui/open-webui/commit/388f62f8a002b789887d016892a1bf152c9d90af), [#25217](https://github.com/open-webui/open-webui/issues/25217) +- 👁️ **Workspace base model selector respects visibility.** The base model selector in the workspace now hides models you don't have access to, matching their visibility settings. [#25668](https://github.com/open-webui/open-webui/pull/25668) +- 🧵 **Channel threads bind to the right channel.** A channel thread's parent and replies are now tied to the channel in the URL, preventing mismatches when switching channels. [#25766](https://github.com/open-webui/open-webui/pull/25766) +- 🗑️ **Unsharing cleans up orphaned rows.** Unsharing a chat now handles leftover shared-chat records, avoiding stale entries. [#25632](https://github.com/open-webui/open-webui/pull/25632) +- 🔎 **Web search results reach the model with retrieval on.** Web search results are now passed to the model even when embedding and retrieval are enabled, instead of being left out. [#25600](https://github.com/open-webui/open-webui/pull/25600) +- 🔢 **Group count follows search.** The groups count now reflects the filtered search results instead of the full list. [#25689](https://github.com/open-webui/open-webui/pull/25689) +- ␣ **Space key works when renaming.** Pressing space while renaming a file or folder no longer opens it, so spaces can be typed in names. [#25627](https://github.com/open-webui/open-webui/pull/25627) +- 🩹 **Missing local embedding model no longer blocks startup.** A missing local embedding model now surfaces as a deferred error instead of preventing the server from starting. [#25683](https://github.com/open-webui/open-webui/pull/25683) +- 🔤 **Consistent settings label capitalization.** Toggle labels in settings now use consistent title casing. [#25765](https://github.com/open-webui/open-webui/pull/25765) +- ♿ **Better screen-reader labels on toggles.** Integration and switch toggles now expose proper accessibility labels and pressed state for screen readers. [#25258](https://github.com/open-webui/open-webui/pull/25258), [#25230](https://github.com/open-webui/open-webui/pull/25230) +- 📜 **Long dropdowns scroll.** Dropdown selects now scroll when their list is long, so all options stay reachable. [Commit](https://github.com/open-webui/open-webui/commit/4bc463072185d0d7c1c9218cd4487501090eccfe), [#25608](https://github.com/open-webui/open-webui/pull/25608) +- 🔽 **Collapsible sections don't misfire on load.** Collapsible sections no longer trigger their change action when first rendered, avoiding unintended toggles on page load. [Commit](https://github.com/open-webui/open-webui/commit/c93d4f04aad1b0d4f8a8bda7ac403b2c8ee35f38), [#25229](https://github.com/open-webui/open-webui/pull/25229) +- ➗ **Large math expressions no longer crash rendering.** Parsing math delimiters no longer overflows on very large or deeply nested input, so messages with heavy math render instead of failing. [#25845](https://github.com/open-webui/open-webui/pull/25845) +- 🗄️ **Oversized chunks no longer break Milvus indexing.** Overly long text chunks are now trimmed before being sent to Milvus, so a single large chunk can no longer fail the whole batch and leave a file with no embeddings. [#25857](https://github.com/open-webui/open-webui/pull/25857), [#25858](https://github.com/open-webui/open-webui/pull/25858) +- 📝 **Code editor stays open when empty.** The code editor drawer no longer collapses when its content is empty. [#25855](https://github.com/open-webui/open-webui/pull/25855) +- 💽 **Settings no longer lost after a restart.** Admin configuration is now stored more reliably, fixing cases where external connections and model parameters could be lost after restarting the server. [Commit](https://github.com/open-webui/open-webui/commit/5cdcdbaeec9fc8156721c38c33ec37956962871c), [Commit](https://github.com/open-webui/open-webui/commit/21f9e5295bf484169d72f4538f7c926b5519723c), [Commit](https://github.com/open-webui/open-webui/commit/8958b64b5a7e96cd8c2260571b54324ca3bfe127), [#24743](https://github.com/open-webui/open-webui/issues/24743), [#25911](https://github.com/open-webui/open-webui/pull/25911), [#25959](https://github.com/open-webui/open-webui/pull/25959) +- 📜 **Visible chat scrollbar.** The chat area now shows a scrollbar, making it easier to scroll through long responses. [Commit](https://github.com/open-webui/open-webui/commit/d56e1cb0b9), [#25833](https://github.com/open-webui/open-webui/issues/25833) +- 🎚️ **Default model parameters apply to requests.** Default model parameters are now applied to outbound requests, so settings like temperature and the context window take effect as configured. [Commit](https://github.com/open-webui/open-webui/commit/cd6cc39c6d), [Commit](https://github.com/open-webui/open-webui/commit/19db873603215773f9a64e03785a1a076dc6c8a8), [#24930](https://github.com/open-webui/open-webui/issues/24930), [#26209](https://github.com/open-webui/open-webui/issues/26209) +- 🟢 **Ollama loaded-model indicator restored.** The indicator showing which Ollama model is loaded in VRAM works again after recent changes. [#25586](https://github.com/open-webui/open-webui/issues/25586), [#25732](https://github.com/open-webui/open-webui/issues/25732) +- 🪪 **Static MCP connectors recover missing OAuth details.** MCP connectors configured with static OAuth credentials now fill in a missing scope or resource from the server's published metadata, so they connect correctly instead of failing when those values were left out. [Commit](https://github.com/open-webui/open-webui/commit/88901bfa041ddcceab1cd4a97f08f0b43835eb05), [#25898](https://github.com/open-webui/open-webui/issues/25898) +- 📊 **Token usage and cost stats no longer wiped by background tasks.** A response's token usage and cost are now preserved when background tasks like title, tag, and follow-up generation run on the same chat, instead of being overwritten. [Commit](https://github.com/open-webui/open-webui/commit/95391221dfabbfcd9090ab472b1c02a4c75c0387) +- 🔗 **Model share link updated.** Sharing a model now opens the current community post page, fixing the link that pointed at the old endpoint. [#25801](https://github.com/open-webui/open-webui/pull/25801) + +### Changed + +- ⚠️ **Database Migrations**: This update contains database migrations. Please be sure to back up your database before updating, as downgrading after the migration is not supported. +- 🔔 **System events now fire automatically.** With the new event system, Open WebUI emits events for activity like startup, sign-ins, and configuration changes, so any webhook you already have configured may begin receiving calls for these newly emitted events after upgrading. Review your event and webhook settings after updating so you only receive the events you want. [Commit](https://github.com/open-webui/open-webui/commit/b5c43968db0ea1556b228d143ae5946dc4e944ba) +- 🔀 **Native tool calling is now the default.** Every chat and model that had not explicitly chosen a tool-calling mode now runs Native, which relies on a model's built-in tool support, while the old behavior has been renamed "Legacy" and made the explicit opt-out; if your models depend on the previous approach you must switch them back to "Legacy" per chat, per model, or globally in your default model parameters to preserve their behavior. [Commit](https://github.com/open-webui/open-webui/commit/b1d40f340921c27eb9a965b9feeb2563856e25e2) +- 🗂️ **Authentication settings moved to their own page.** LDAP, OAuth, and related authentication settings have moved out of the General settings page into a dedicated Authentication page in the admin panel. [Commit](https://github.com/open-webui/open-webui/commit/5cdcdbaeec9fc8156721c38c33ec37956962871c) +- 🎓 **Several features are no longer beta.** Memories, Notes, Channels, and High Contrast Mode have graduated out of beta and no longer carry a beta label. [Commit](https://github.com/open-webui/open-webui/commit/7b55a63fc7ee323e9114713ce1d2f3f688aa37e6) +- 🔧 **Local web fetch setting renamed.** The "ENABLE_RAG_LOCAL_WEB_FETCH" environment variable is now "ENABLE_LOCAL_WEB_FETCH", reflecting that it applies beyond retrieval; the old name still works as a deprecated alias. [Commit](https://github.com/open-webui/open-webui/commit/e3ba6984534898695b47ee4fc3d6b746e2865abc) +- 🔧 **You.com search key renamed.** You.com web search now prefers the "YDC_API_KEY" environment variable, with the previous "YOUCOM_API_KEY" still accepted as a fallback. [Commit](https://github.com/open-webui/open-webui/commit/df634bb64f5043b0292e43c69bd1d31676c89328), [#26316](https://github.com/open-webui/open-webui/pull/26316) +- 🧪 **Client-side Python now runs sandboxed.** Client-side Python (Pyodide) now runs in a sandboxed, opaque-origin iframe by default, isolating executed code from your session, cookies, local storage, and the app's own endpoints, while full Python, JavaScript, and external network access keep working. Code that relied on reaching same-origin Open WebUI endpoints from Pyodide will no longer be able to, and Pyodide is now marked legacy in the admin Code Execution settings. [Commit](https://github.com/open-webui/open-webui/commit/516051304e1b1f250c34438746ade673a79bd40c), [Commit](https://github.com/open-webui/open-webui/commit/c7be66626fd10c75ec35f662a709129ba1b020ec), [Commit](https://github.com/open-webui/open-webui/commit/62ae2069183109d878d72b9444a0e7c4f6c66caa), [Commit](https://github.com/open-webui/open-webui/commit/518702caae5a6484e71aa79e8ab908ec398290a7), [Commit](https://github.com/open-webui/open-webui/commit/03a8363583b7e0e04760d49f1e8d28dbbfefee4d) + ## [0.9.6] - 2026-06-01 ### Added diff --git a/Dockerfile b/Dockerfile index 36e29e7069..6074477637 100644 --- a/Dockerfile +++ b/Dockerfile @@ -126,7 +126,7 @@ RUN chown -R $UID:$GID /app $HOME # Install common system dependencies RUN apt-get update && \ apt-get install -y --no-install-recommends \ - git build-essential pandoc gcc netcat-openbsd curl jq \ + git build-essential pandoc gcc netcat-openbsd curl jq ca-certificates \ libmariadb-dev \ python3-dev \ ffmpeg libsm6 libxext6 zstd \ diff --git a/README.md b/README.md index 3c4bee98c9..66c49eb328 100644 --- a/README.md +++ b/README.md @@ -27,58 +27,84 @@ For more information, be sure to check out our [Open WebUI Documentation](https: ## Key Features of Open WebUI ⭐ -- 🚀 **Effortless Setup**: Install seamlessly using Docker or Kubernetes (kubectl, kustomize or helm) for a hassle-free experience with support for both `:ollama` and `:cuda` tagged images. +- 🚀 **Effortless Setup**: Install seamlessly via pip, uv, Docker, or Kubernetes (kubectl, kustomize, or helm), with `:ollama` and `:cuda` tagged images available for container deployments. -- 🤝 **Ollama/OpenAI API Integration**: Effortlessly integrate OpenAI-compatible APIs for versatile conversations alongside Ollama models. Customize the OpenAI API URL to link with **LMStudio, GroqCloud, Mistral, OpenRouter, and more**. +- 🤝 **Broad Model & API Integration**: Connect any OpenAI-compatible API alongside local Ollama models. Point the API URL at **LMStudio, GroqCloud, Mistral, OpenRouter, vLLM, and more** to mix and match providers freely. -- 🛡️ **Granular Permissions and User Groups**: By allowing administrators to create detailed user roles and permissions, we ensure a secure user environment. This granularity not only enhances security but also allows for customized user experiences, fostering a sense of ownership and responsibility amongst users. +- 🔐 **Granular RBAC & User Groups**: Administrators define detailed roles, groups, and permissions, giving each user exactly the access they need. Secure by default, with tailored experiences per group. -- 📱 **Responsive Design**: Enjoy a seamless experience across Desktop PC, Laptop, and Mobile devices. +- 🧩 **Plugin Support**: Extend Open WebUI with **Filters**, **Actions**, **Pipes**, **Tools**, and **Skills**. Connect external services through **MCP**, **MCPO**, and **OpenAPI tool servers**. Build custom integrations, rate limits, approval flows, data connections, and more. -- 📱 **Progressive Web App (PWA) for Mobile**: Enjoy a native app-like experience on your mobile device with our PWA, providing offline access on localhost and a seamless user interface. +- 🤖 **Models & Agents**: Wrap any base model with custom instructions, tools, and knowledge to build specialized agents. Supports dynamic variables, per-user/group access control, and community preset imports via [Open WebUI Community](https://openwebui.com/). -- ✒️🔢 **Full Markdown and LaTeX Support**: Elevate your LLM experience with comprehensive Markdown and LaTeX capabilities for enriched interaction. +- 📝 **Notes**: A dedicated workspace for content outside conversations. Draft with a rich editor, use AI to rewrite selected text, and attach notes to any chat for full-context injection. -- 🎤📹 **Hands-Free Voice/Video Call**: Experience seamless communication with integrated hands-free voice and video call features using multiple Speech-to-Text providers (Local Whisper, OpenAI, Deepgram, Azure) and Text-to-Speech engines (Azure, ElevenLabs, OpenAI, Transformers, WebAPI), allowing for dynamic and interactive chat environments. +- 📢 **Channels**: Real-time shared spaces where your team and AI models collaborate in one timeline. Tag models to draft or critique, with threads, reactions, pins, and access control. -- 🛠️ **Model Builder**: Easily create Ollama models via the Web UI. Create and add custom characters/agents, customize chat elements, and import models effortlessly through [Open WebUI Community](https://openwebui.com/) integration. +- 🧠 **Persistent Memory**: The AI remembers facts about you across conversations, carrying context from one chat to the next. -- 🐍 **Native Python Function Calling Tool**: Enhance your LLMs with built-in code editor support in the tools workspace. Bring Your Own Function (BYOF) by simply adding your pure Python functions, enabling seamless integration with LLMs. +- ✅ **Live Workflow & Message Flow**: Watch the AI build and work through checklists in real time. Queue messages while the AI is still responding; they send automatically when it's ready. -- 💾 **Persistent Artifact Storage**: Built-in key-value storage API for artifacts, enabling features like journals, trackers, leaderboards, and collaborative tools with both personal and shared data scopes across sessions. +- 📅 **Calendar & AI Scheduling**: Built-in personal and shared calendars with month/week/day views, recurring events, color coding, attendees, and reminders. Models manage your schedule conversationally through native function calling. -- 📚 **Local RAG Integration**: Dive into the future of chat interactions with groundbreaking Retrieval Augmented Generation (RAG) support using your choice of 9 vector databases and multiple content extraction engines (Tika, Docling, Document Intelligence, Mistral OCR, PaddleOCR-vl, External loaders). Load documents directly into chat or add files to your document library, effortlessly accessing them using the `#` command before a query. +- ⏱️ **Automations**: Schedule prompts to run on recurring schedules, with runs surfaced on your calendar and each completed run linking back to the chat it produced. -- 🔍 **Web Search for RAG**: Perform web searches using 15+ providers including `SearXNG`, `Google PSE`, `Brave Search`, `Kagi`, `Mojeek`, `Tavily`, `Perplexity`, `serpstack`, `serper`, `Serply`, `DuckDuckGo`, `SearchApi`, `SerpApi`, `Bing`, `Jina`, `Exa`, `Sougou`, `Azure AI Search`, and `Ollama Cloud`, injecting results directly into your chat experience. +- 📱 **Responsive Design & PWA**: Seamless experience across desktop, laptop, and mobile, with a Progressive Web App for native app-like feel and offline access on localhost. -- 🌐 **Web Browsing Capability**: Seamlessly integrate websites into your chat experience using the `#` command followed by a URL. This feature allows you to incorporate web content directly into your conversations, enhancing the richness and depth of your interactions. +- ✒️🔢 **Full Markdown and LaTeX Support**: Comprehensive Markdown and LaTeX capabilities for enriched interaction. -- 🎨 **Image Generation & Editing Integration**: Create and edit images using multiple engines including OpenAI's DALL-E, Gemini, ComfyUI (local), and AUTOMATIC1111 (local), with support for both generation and prompt-based editing workflows. +- 🎤📹 **Hands-Free Voice/Video Call**: Integrated voice and video calls with multiple Speech-to-Text providers (Local Whisper, OpenAI, Deepgram, Azure) and Text-to-Speech engines (Azure, ElevenLabs, OpenAI, Transformers, WebAPI). -- ⚙️ **Many Models Conversations**: Effortlessly engage with various models simultaneously, harnessing their unique strengths for optimal responses. Enhance your experience by leveraging a diverse set of models in parallel. +- 💾 **Persistent Artifact Storage**: Built-in key-value storage API for artifacts, enabling journals, trackers, leaderboards, and collaborative tools with personal and shared data scopes. -- 🔐 **Role-Based Access Control (RBAC)**: Ensure secure access with restricted permissions; only authorized individuals can access your Ollama, and exclusive model creation/pulling rights are reserved for administrators. +- 📚 **Local RAG Integration**: Retrieval Augmented Generation backed by 9 vector databases and multiple content-extraction engines (Tika, Docling, Document Intelligence, Mistral OCR, PaddleOCR-vl, external loaders). Supports hybrid search (BM25 + vector) with reranking and full-context mode. Load documents into chat or pull them from your library with the `#` command. -- 🗄️ **Flexible Database & Storage Options**: Choose from SQLite (with optional encryption), PostgreSQL, or configure cloud storage backends (S3, Google Cloud Storage, Azure Blob Storage) for scalable deployments. +- 🔍 **Web Search for RAG**: Search the web through dozens of providers including `SearXNG`, `Google PSE`, `Brave Search`, `Kagi`, `Mojeek`, `Tavily`, `Perplexity`, `Firecrawl`, `serpstack`, `serper`, `Serply`, `DuckDuckGo`, `SearchApi`, `SerpApi`, `Bing`, `Jina`, `Exa`, `Sougou`, `Azure AI Search`, and `Ollama Cloud`, injecting results directly into the conversation. -- 🔍 **Advanced Vector Database Support**: Select from 9 vector database options including ChromaDB, PGVector, Qdrant, Milvus, Elasticsearch, OpenSearch, Pinecone, S3Vector, and Oracle 23ai for optimal RAG performance. +- 🌐 **Web Browsing Capability**: Pull websites into chat with the `#` command followed by a URL, or let the model fetch them on its own when needed. -- 🔐 **Enterprise Authentication**: Full support for LDAP/Active Directory integration, SCIM 2.0 automated provisioning, and SSO via trusted headers alongside OAuth providers. Enterprise-grade user and group provisioning through SCIM 2.0 protocol, enabling seamless integration with identity providers like Okta, Azure AD, and Google Workspace for automated user lifecycle management. +- 🎨 **Image Generation & Editing**: Create and edit images with multiple engines including OpenAI DALL·E, Gemini, ComfyUI (local), and AUTOMATIC1111 (local), supporting both generation and prompt-based editing. -- ☁️ **Cloud-Native Integration**: Native support for Google Drive and OneDrive/SharePoint file picking, enabling seamless document import from enterprise cloud storage. +- ⚙️ **Multi-Model Conversations**: Engage several models at once, harnessing their individual strengths in parallel for the best possible responses. -- 📊 **Production Observability**: Built-in OpenTelemetry support for traces, metrics, and logs, enabling comprehensive monitoring with your existing observability stack. +- 📊 **Usage Analytics & Model Evaluation**: Admin dashboards track message volume, token consumption, and cost across users and models. Evaluate models with a built-in arena, A/B testing, and ELO-based leaderboards. -- ⚖️ **Horizontal Scalability**: Redis-backed session management and WebSocket support for multi-worker and multi-node deployments behind load balancers. +- 🗄️ **Flexible Database & Storage**: Choose SQLite (with optional encryption) or PostgreSQL, and store files locally or on S3, Google Cloud Storage, or Azure Blob Storage. -- 🌐🌍 **Multilingual Support**: Experience Open WebUI in your preferred language with our internationalization (i18n) support. Join us in expanding our supported languages! We're actively seeking contributors! +- 🧬 **Advanced Vector Database Support**: Pick from 9 vector databases: ChromaDB, PGVector, Qdrant, Milvus, Elasticsearch, OpenSearch, Pinecone, S3Vector, and Oracle 23ai. -- 🧩 **Pipelines, Open WebUI Plugin Support**: Seamlessly integrate custom logic and Python libraries into Open WebUI using [Pipelines Plugin Framework](https://github.com/open-webui/pipelines). Launch your Pipelines instance, set the OpenAI URL to the Pipelines URL, and explore endless possibilities. [Examples](https://github.com/open-webui/pipelines/tree/main/examples) include **Function Calling**, User **Rate Limiting** to control access, **Usage Monitoring** with tools like Langfuse, **Live Translation with LibreTranslate** for multilingual support, **Toxic Message Filtering** and much more. +- 🪪 **Enterprise Authentication & Provisioning**: Full LDAP/Active Directory integration, SSO via trusted headers and OAuth providers, and SCIM 2.0 automated provisioning for identity providers like Okta, Azure AD, and Google Workspace. -- 🌟 **Continuous Updates**: We are committed to improving Open WebUI with regular updates, fixes, and new features. +- ☁️ **Cloud-Native File Integration**: Native Google Drive and OneDrive/SharePoint file picking for seamless document import from enterprise cloud storage. + +- 🔭 **Production Observability**: Built-in OpenTelemetry support for traces, metrics, and logs, plugging into your existing monitoring stack. + +- ⚖️ **Horizontal Scalability**: Redis-backed session management and WebSocket support for multi-worker, multi-node deployments behind load balancers. + +- 🌐🌍 **Multilingual Support**: Use Open WebUI in your preferred language with i18n support. We're actively seeking contributors to expand language coverage! + +- 🌟 **Continuous Updates**: We're committed to improving Open WebUI with regular updates, fixes, and new features. + +- 🛡️ **Transparent Security Process**: Security reports are triaged, fixed, and published as open advisories through a documented responsible-disclosure process. See our [Security Policy](https://github.com/open-webui/open-webui/security). Want to learn more about Open WebUI's features? Check out our [Open WebUI documentation](https://docs.openwebui.com/features) for a comprehensive overview! +## The Open WebUI Ecosystem 🌐 + +Open WebUI is the core, surrounded by companion apps and infrastructure that extend what your AI can do, where it can reach, and how you run it: + +- ⚡ **Open Terminal** ([open-webui/open-terminal](https://github.com/open-webui/open-terminal)): A self-hosted computing environment that plugs into Open WebUI, giving the AI a place to write code, run it, read output, fix errors, and iterate inside the chat. + +- 🔒 **Terminals** · Enterprise ([open-webui/terminals](https://github.com/open-webui/terminals)): Per-user isolated containers with separate credentials, resource limits, and network rules. Automatic lifecycle management on Docker or Kubernetes. + +- 💻 **cptr** ([open-webui/computer](https://github.com/open-webui/computer)): A standalone, mobile-first computer and coding agent that runs on the machine you own. Files, terminal, and git in a browser tab, reachable from your phone. Connect it into Open WebUI as a model, or reach it from Telegram, WhatsApp, and more. + +- 🔄 **oikb** ([open-webui/oikb](https://github.com/open-webui/oikb)): Feed your Knowledge Bases from 45+ sources (GitHub, Confluence, ServiceNow, Salesforce, Jira, Slack, SharePoint, Notion, and more), keeping the tools your team already uses continuously in sync. + +- 🖥️ **Native Desktop App** ([open-webui/desktop](https://github.com/open-webui/desktop)): Run Open WebUI as a native app on macOS, Windows, and Linux. System-wide Spotlight chat bar with screenshot capture, push-to-talk voice, and optional fully-local inference via a built-in llama.cpp engine. + +Want to learn more? Check out our [Open WebUI documentation](https://docs.openwebui.com) for more details! + --- We are incredibly grateful for the generous support of our sponsors. Their contributions help us to maintain and improve our project, ensuring we can continue to deliver quality work to our community. Thank you! @@ -222,6 +248,10 @@ This project contains code under multiple licenses. The current codebase include If you have any questions, suggestions, or need assistance, please open an issue or join our [Open WebUI Discord community](https://discord.gg/5rJgQTnV4s) to connect with us! 🤝 +## Security 🛡️ + +If you believe you've found a security vulnerability, or something that shouldn't be disclosed publicly, please [reach out confidentially through our responsible disclosure program on GitHub](https://github.com/open-webui/open-webui/security). We accept reports only through GitHub, not through any other platform. Thank you for helping us keep Open WebUI secure! + ## Star History diff --git a/backend/open_webui/__init__.py b/backend/open_webui/__init__.py index 92cadefe7c..59817d7921 100644 --- a/backend/open_webui/__init__.py +++ b/backend/open_webui/__init__.py @@ -11,6 +11,7 @@ import uvicorn app = typer.Typer() KEY_FILE = Path.cwd() / '.webui_secret_key' +DEFAULT_SECRET_KEY_LENGTH = 24 def version_callback(value: bool) -> None: @@ -37,8 +38,11 @@ def serve( if os.getenv('WEBUI_SECRET_KEY') is None: typer.echo('Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.') if not KEY_FILE.exists(): + key_length = int(os.getenv('WEBUI_SECRET_KEY_LENGTH', DEFAULT_SECRET_KEY_LENGTH)) + if key_length < 1: + raise ValueError('WEBUI_SECRET_KEY_LENGTH must be a positive integer') typer.echo(f'Generating a new secret key and saving it to {KEY_FILE}') - KEY_FILE.write_bytes(base64.b64encode(random.randbytes(12))) + KEY_FILE.write_bytes(base64.b64encode(random.randbytes(key_length))) typer.echo(f'Loading WEBUI_SECRET_KEY from {KEY_FILE}') os.environ['WEBUI_SECRET_KEY'] = KEY_FILE.read_text() diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 57f4712027..7cadde33fe 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -34,70 +34,17 @@ from open_webui.env import ( WEBUI_NAME, log, ) -from open_webui.internal.config import ( - STATE as _state, -) -from open_webui.internal.config import ( - AppConfig, - ConfigVar, -) - -# ── Persistent configuration layer ────────────────────────────────────────── -from open_webui.internal.config import ( # noqa: F401 - ConfigTable as Config, -) -from open_webui.internal.config import ( - _all_configs as PERSISTENT_CONFIG_REGISTRY, -) -from open_webui.internal.config import ( - initialize as _initialize_config, -) +from open_webui.models.config import Config -def get_config(): - return _state.snapshot - - -def save_to_db(data): - _state.persist(data) - - -async def async_save_to_db(data): - await _state.persist_async(data) - - -def save_config(config): - try: - _state.persist(config) - for s in PERSISTENT_CONFIG_REGISTRY: - s.refresh() - except Exception: - log.exception('Failed to save config') - return False - return True - - -async def async_save_config(config): - try: - await _state.persist_async(config) - for s in PERSISTENT_CONFIG_REGISTRY: - s.refresh() - except Exception: - log.exception('Failed to save config') - return False - return True - - -def reset_config(): - _state.clear() +async def seed_registered_defaults(): + await Config.rename_prefix('rag.web', 'web') + await Config.repair_flattened_dict_configs() + await Config.seed_defaults(DEFAULT_CONFIG) async def async_reset_config(): - await _state.clear_async() - - -def get_config_value(config_path: str): - return _state.read(config_path) + await Config.clear() class EndpointFilter(logging.Filter): @@ -132,22 +79,15 @@ if ENABLE_DB_MIGRATIONS: run_migrations() -# Migrate legacy config.json → database on first run -if os.path.exists(f'{DATA_DIR}/config.json'): +async def import_legacy_config_json(): + """Migrate legacy config.json → database on first run.""" + if not os.path.exists(f'{DATA_DIR}/config.json'): + return with open(f'{DATA_DIR}/config.json', 'r') as _f: - save_to_db(json.load(_f)) + await Config.upsert(json.load(_f)) os.rename(f'{DATA_DIR}/config.json', f'{DATA_DIR}/old_config.json') -ENABLE_PERSISTENT_CONFIG = os.getenv('ENABLE_PERSISTENT_CONFIG', 'True').lower() == 'true' -ENABLE_OAUTH_PERSISTENT_CONFIG = os.getenv('ENABLE_OAUTH_PERSISTENT_CONFIG', 'False').lower() == 'true' - -# Bootstrap the persistent config subsystem -CONFIG_DATA = _initialize_config( - enable_persistent=ENABLE_PERSISTENT_CONFIG, - enable_oauth_persistent=ENABLE_OAUTH_PERSISTENT_CONFIG, -) - #################################### # Static DIR #################################### @@ -278,21 +218,13 @@ if CUSTOM_NAME: # DIRECT CONNECTIONS #################################### -ENABLE_DIRECT_CONNECTIONS = ConfigVar( - 'ENABLE_DIRECT_CONNECTIONS', - 'direct.enable', - os.getenv('ENABLE_DIRECT_CONNECTIONS', 'False').lower() == 'true', -) +ENABLE_DIRECT_CONNECTIONS = os.getenv('ENABLE_DIRECT_CONNECTIONS', 'False').lower() == 'true' #################################### # OLLAMA_BASE_URL #################################### -ENABLE_OLLAMA_API = ConfigVar( - 'ENABLE_OLLAMA_API', - 'ollama.enable', - os.getenv('ENABLE_OLLAMA_API', 'True').lower() == 'true', -) +ENABLE_OLLAMA_API = os.getenv('ENABLE_OLLAMA_API', 'True').lower() == 'true' OLLAMA_API_BASE_URL = os.getenv('OLLAMA_API_BASE_URL', 'http://localhost:11434/api') @@ -355,24 +287,16 @@ OLLAMA_BASE_URLS = os.getenv('OLLAMA_BASE_URLS', '') OLLAMA_BASE_URLS = OLLAMA_BASE_URLS if OLLAMA_BASE_URLS != '' else OLLAMA_BASE_URL OLLAMA_BASE_URLS = [url.strip() for url in OLLAMA_BASE_URLS.split(';')] -OLLAMA_BASE_URLS = ConfigVar('OLLAMA_BASE_URLS', 'ollama.base_urls', OLLAMA_BASE_URLS) +OLLAMA_BASE_URLS = OLLAMA_BASE_URLS -OLLAMA_API_CONFIGS = ConfigVar( - 'OLLAMA_API_CONFIGS', - 'ollama.api_configs', - {}, -) +OLLAMA_API_CONFIGS = {} #################################### # OPENAI_API #################################### -ENABLE_OPENAI_API = ConfigVar( - 'ENABLE_OPENAI_API', - 'openai.enable', - os.getenv('ENABLE_OPENAI_API', 'True').lower() == 'true', -) +ENABLE_OPENAI_API = os.getenv('ENABLE_OPENAI_API', 'True').lower() == 'true' OPENAI_API_KEY = os.getenv('OPENAI_API_KEY', '') @@ -392,7 +316,7 @@ OPENAI_API_KEYS = os.getenv('OPENAI_API_KEYS', '') OPENAI_API_KEYS = OPENAI_API_KEYS if OPENAI_API_KEYS != '' else OPENAI_API_KEY OPENAI_API_KEYS = [url.strip() for url in OPENAI_API_KEYS.split(';')] -OPENAI_API_KEYS = ConfigVar('OPENAI_API_KEYS', 'openai.api_keys', OPENAI_API_KEYS) +OPENAI_API_KEYS = OPENAI_API_KEYS OPENAI_API_BASE_URLS = os.getenv('OPENAI_API_BASE_URLS', '') OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS if OPENAI_API_BASE_URLS != '' else OPENAI_API_BASE_URL @@ -400,18 +324,14 @@ OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS if OPENAI_API_BASE_URLS != '' else O OPENAI_API_BASE_URLS = [ url.strip() if url != '' else 'https://api.openai.com/v1' for url in OPENAI_API_BASE_URLS.split(';') ] -OPENAI_API_BASE_URLS = ConfigVar('OPENAI_API_BASE_URLS', 'openai.api_base_urls', OPENAI_API_BASE_URLS) +OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS -OPENAI_API_CONFIGS = ConfigVar( - 'OPENAI_API_CONFIGS', - 'openai.api_configs', - {}, -) +OPENAI_API_CONFIGS = {} # Get the actual OpenAI API key based on the base URL OPENAI_API_KEY = '' try: - OPENAI_API_KEY = OPENAI_API_KEYS.value[OPENAI_API_BASE_URLS.value.index('https://api.openai.com/v1')] + OPENAI_API_KEY = OPENAI_API_KEYS[OPENAI_API_BASE_URLS.index('https://api.openai.com/v1')] except Exception: pass OPENAI_API_BASE_URL = 'https://api.openai.com/v1' @@ -421,11 +341,7 @@ OPENAI_API_BASE_URL = 'https://api.openai.com/v1' # MODELS #################################### -ENABLE_BASE_MODELS_CACHE = ConfigVar( - 'ENABLE_BASE_MODELS_CACHE', - 'models.base_models_cache', - os.getenv('ENABLE_BASE_MODELS_CACHE', 'False').lower() == 'true', -) +ENABLE_BASE_MODELS_CACHE = os.getenv('ENABLE_BASE_MODELS_CACHE', 'False').lower() == 'true' #################################### @@ -439,17 +355,9 @@ except Exception as e: tool_server_connections = [] -TOOL_SERVER_CONNECTIONS = ConfigVar( - 'TOOL_SERVER_CONNECTIONS', - 'tool_server.connections', - tool_server_connections, -) +TOOL_SERVER_CONNECTIONS = tool_server_connections -OAUTH_CLIENT_TIMEOUT = ConfigVar( - 'OAUTH_CLIENT_TIMEOUT', - 'oauth.client.timeout', - os.getenv('OAUTH_CLIENT_TIMEOUT', ''), -) +OAUTH_CLIENT_TIMEOUT = os.getenv('OAUTH_CLIENT_TIMEOUT', '') #################################### # TERMINAL_SERVER @@ -457,11 +365,7 @@ OAUTH_CLIENT_TIMEOUT = ConfigVar( terminal_server_connections = json.loads(os.getenv('TERMINAL_SERVER_CONNECTIONS', '[]')) -TERMINAL_SERVER_CONNECTIONS = ConfigVar( - 'TERMINAL_SERVER_CONNECTIONS', - 'terminal_server.connections', - terminal_server_connections, -) +TERMINAL_SERVER_CONNECTIONS = terminal_server_connections try: TERMINAL_PROXY_HEADERS = json.loads(os.getenv('TERMINAL_PROXY_HEADERS', '{}')) @@ -472,116 +376,56 @@ except Exception: # Code Interpreter #################################### -ENABLE_CODE_EXECUTION = ConfigVar( - 'ENABLE_CODE_EXECUTION', - 'code_execution.enable', - os.getenv('ENABLE_CODE_EXECUTION', 'True').lower() == 'true', -) +ENABLE_CODE_EXECUTION = os.getenv('ENABLE_CODE_EXECUTION', 'True').lower() == 'true' -CODE_EXECUTION_ENGINE = ConfigVar( - 'CODE_EXECUTION_ENGINE', - 'code_execution.engine', - os.getenv('CODE_EXECUTION_ENGINE', 'pyodide'), -) +CODE_EXECUTION_ENGINE = os.getenv('CODE_EXECUTION_ENGINE', 'pyodide') -CODE_EXECUTION_JUPYTER_URL = ConfigVar( - 'CODE_EXECUTION_JUPYTER_URL', - 'code_execution.jupyter.url', - os.getenv('CODE_EXECUTION_JUPYTER_URL', ''), -) +CODE_EXECUTION_JUPYTER_URL = os.getenv('CODE_EXECUTION_JUPYTER_URL', '') -CODE_EXECUTION_JUPYTER_AUTH = ConfigVar( - 'CODE_EXECUTION_JUPYTER_AUTH', - 'code_execution.jupyter.auth', +CODE_EXECUTION_JUPYTER_AUTH = os.getenv('CODE_EXECUTION_JUPYTER_AUTH', '') + +CODE_EXECUTION_JUPYTER_AUTH_TOKEN = os.getenv('CODE_EXECUTION_JUPYTER_AUTH_TOKEN', '') + + +CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = os.getenv('CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', '') + +CODE_EXECUTION_JUPYTER_TIMEOUT = int(os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60')) + +ENABLE_CODE_INTERPRETER = os.getenv('ENABLE_CODE_INTERPRETER', 'True').lower() == 'true' + +ENABLE_MEMORIES = os.getenv('ENABLE_MEMORIES', 'True').lower() == 'true' +ENABLE_MEMORY_BACKGROUND_REVIEW = os.getenv('ENABLE_MEMORY_BACKGROUND_REVIEW', 'False').lower() == 'true' +MEMORIES_REVIEW_INTERVAL_TURNS = int(os.getenv('MEMORIES_REVIEW_INTERVAL_TURNS', '10')) +MEMORIES_USER_CHAR_LIMIT = int(os.getenv('MEMORIES_USER_CHAR_LIMIT', '2000')) +MEMORIES_CONTEXT_CHAR_LIMIT = int(os.getenv('MEMORIES_CONTEXT_CHAR_LIMIT', '2000')) + +CODE_INTERPRETER_ENGINE = os.getenv('CODE_INTERPRETER_ENGINE', 'pyodide') + +CODE_INTERPRETER_PROMPT_TEMPLATE = os.getenv('CODE_INTERPRETER_PROMPT_TEMPLATE', '') + +CODE_INTERPRETER_JUPYTER_URL = os.getenv('CODE_INTERPRETER_JUPYTER_URL', os.getenv('CODE_EXECUTION_JUPYTER_URL', '')) + +CODE_INTERPRETER_JUPYTER_AUTH = os.getenv( + 'CODE_INTERPRETER_JUPYTER_AUTH', os.getenv('CODE_EXECUTION_JUPYTER_AUTH', ''), ) -CODE_EXECUTION_JUPYTER_AUTH_TOKEN = ConfigVar( - 'CODE_EXECUTION_JUPYTER_AUTH_TOKEN', - 'code_execution.jupyter.auth_token', +CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = os.getenv( + 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN', os.getenv('CODE_EXECUTION_JUPYTER_AUTH_TOKEN', ''), ) -CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = ConfigVar( - 'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', - 'code_execution.jupyter.auth_password', +CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = os.getenv( + 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD', os.getenv('CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', ''), ) -CODE_EXECUTION_JUPYTER_TIMEOUT = ConfigVar( - 'CODE_EXECUTION_JUPYTER_TIMEOUT', - 'code_execution.jupyter.timeout', - int(os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60')), -) - -ENABLE_CODE_INTERPRETER = ConfigVar( - 'ENABLE_CODE_INTERPRETER', - 'code_interpreter.enable', - os.getenv('ENABLE_CODE_INTERPRETER', 'True').lower() == 'true', -) - -ENABLE_MEMORIES = ConfigVar( - 'ENABLE_MEMORIES', - 'memories.enable', - os.getenv('ENABLE_MEMORIES', 'True').lower() == 'true', -) - -CODE_INTERPRETER_ENGINE = ConfigVar( - 'CODE_INTERPRETER_ENGINE', - 'code_interpreter.engine', - os.getenv('CODE_INTERPRETER_ENGINE', 'pyodide'), -) - -CODE_INTERPRETER_PROMPT_TEMPLATE = ConfigVar( - 'CODE_INTERPRETER_PROMPT_TEMPLATE', - 'code_interpreter.prompt_template', - os.getenv('CODE_INTERPRETER_PROMPT_TEMPLATE', ''), -) - -CODE_INTERPRETER_JUPYTER_URL = ConfigVar( - 'CODE_INTERPRETER_JUPYTER_URL', - 'code_interpreter.jupyter.url', - os.getenv('CODE_INTERPRETER_JUPYTER_URL', os.getenv('CODE_EXECUTION_JUPYTER_URL', '')), -) - -CODE_INTERPRETER_JUPYTER_AUTH = ConfigVar( - 'CODE_INTERPRETER_JUPYTER_AUTH', - 'code_interpreter.jupyter.auth', +CODE_INTERPRETER_JUPYTER_TIMEOUT = int( os.getenv( - 'CODE_INTERPRETER_JUPYTER_AUTH', - os.getenv('CODE_EXECUTION_JUPYTER_AUTH', ''), - ), -) - -CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = ConfigVar( - 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN', - 'code_interpreter.jupyter.auth_token', - os.getenv( - 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN', - os.getenv('CODE_EXECUTION_JUPYTER_AUTH_TOKEN', ''), - ), -) - - -CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = ConfigVar( - 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD', - 'code_interpreter.jupyter.auth_password', - os.getenv( - 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD', - os.getenv('CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', ''), - ), -) - -CODE_INTERPRETER_JUPYTER_TIMEOUT = ConfigVar( - 'CODE_INTERPRETER_JUPYTER_TIMEOUT', - 'code_interpreter.jupyter.timeout', - int( - os.getenv( - 'CODE_INTERPRETER_JUPYTER_TIMEOUT', - os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60'), - ) - ), + 'CODE_INTERPRETER_JUPYTER_TIMEOUT', + os.getenv('CODE_EXECUTION_JUPYTER_TIMEOUT', '60'), + ) ) CODE_INTERPRETER_BLOCKED_MODULES = [ @@ -961,29 +805,13 @@ VALKEY_HNSW_EF_RUNTIME = int(os.getenv('VALKEY_HNSW_EF_RUNTIME', '10')) # If configured, Google Drive will be available as an upload option. -ENABLE_GOOGLE_DRIVE_INTEGRATION = ConfigVar( - 'ENABLE_GOOGLE_DRIVE_INTEGRATION', - 'google_drive.enable', - os.getenv('ENABLE_GOOGLE_DRIVE_INTEGRATION', 'False').lower() == 'true', -) +ENABLE_GOOGLE_DRIVE_INTEGRATION = os.getenv('ENABLE_GOOGLE_DRIVE_INTEGRATION', 'False').lower() == 'true' -GOOGLE_DRIVE_CLIENT_ID = ConfigVar( - 'GOOGLE_DRIVE_CLIENT_ID', - 'google_drive.client_id', - os.getenv('GOOGLE_DRIVE_CLIENT_ID', ''), -) +GOOGLE_DRIVE_CLIENT_ID = os.getenv('GOOGLE_DRIVE_CLIENT_ID', '') -GOOGLE_DRIVE_API_KEY = ConfigVar( - 'GOOGLE_DRIVE_API_KEY', - 'google_drive.api_key', - os.getenv('GOOGLE_DRIVE_API_KEY', ''), -) +GOOGLE_DRIVE_API_KEY = os.getenv('GOOGLE_DRIVE_API_KEY', '') -ENABLE_ONEDRIVE_INTEGRATION = ConfigVar( - 'ENABLE_ONEDRIVE_INTEGRATION', - 'onedrive.enable', - os.getenv('ENABLE_ONEDRIVE_INTEGRATION', 'False').lower() == 'true', -) +ENABLE_ONEDRIVE_INTEGRATION = os.getenv('ENABLE_ONEDRIVE_INTEGRATION', 'False').lower() == 'true' ONEDRIVE_CLIENT_ID = os.getenv('ONEDRIVE_CLIENT_ID', '') @@ -997,114 +825,44 @@ ENABLE_ONEDRIVE_BUSINESS = os.getenv('ENABLE_ONEDRIVE_BUSINESS', 'True').lower() ONEDRIVE_CLIENT_ID_BUSINESS ) -ONEDRIVE_SHAREPOINT_URL = ConfigVar( - 'ONEDRIVE_SHAREPOINT_URL', - 'onedrive.sharepoint_url', - os.getenv('ONEDRIVE_SHAREPOINT_URL', ''), -) +ONEDRIVE_SHAREPOINT_URL = os.getenv('ONEDRIVE_SHAREPOINT_URL', '') -ONEDRIVE_SHAREPOINT_TENANT_ID = ConfigVar( - 'ONEDRIVE_SHAREPOINT_TENANT_ID', - 'onedrive.sharepoint_tenant_id', - os.getenv('ONEDRIVE_SHAREPOINT_TENANT_ID', ''), -) +ONEDRIVE_SHAREPOINT_TENANT_ID = os.getenv('ONEDRIVE_SHAREPOINT_TENANT_ID', '') # RAG Content Extraction -CONTENT_EXTRACTION_ENGINE = ConfigVar( - 'CONTENT_EXTRACTION_ENGINE', - 'rag.CONTENT_EXTRACTION_ENGINE', - os.getenv('CONTENT_EXTRACTION_ENGINE', '').lower(), +CONTENT_EXTRACTION_ENGINE = os.getenv('CONTENT_EXTRACTION_ENGINE', '').lower() + +DATALAB_MARKER_API_KEY = os.getenv('DATALAB_MARKER_API_KEY', '') + +DATALAB_MARKER_API_BASE_URL = os.getenv('DATALAB_MARKER_API_BASE_URL', '') + +DATALAB_MARKER_ADDITIONAL_CONFIG = os.getenv('DATALAB_MARKER_ADDITIONAL_CONFIG', '') + +DATALAB_MARKER_USE_LLM = os.getenv('DATALAB_MARKER_USE_LLM', 'false').lower() == 'true' + +DATALAB_MARKER_SKIP_CACHE = os.getenv('DATALAB_MARKER_SKIP_CACHE', 'false').lower() == 'true' + +DATALAB_MARKER_FORCE_OCR = os.getenv('DATALAB_MARKER_FORCE_OCR', 'false').lower() == 'true' + +DATALAB_MARKER_PAGINATE = os.getenv('DATALAB_MARKER_PAGINATE', 'false').lower() == 'true' + +DATALAB_MARKER_STRIP_EXISTING_OCR = os.getenv('DATALAB_MARKER_STRIP_EXISTING_OCR', 'false').lower() == 'true' + +DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = ( + os.getenv('DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION', 'false').lower() == 'true' ) -DATALAB_MARKER_API_KEY = ConfigVar( - 'DATALAB_MARKER_API_KEY', - 'rag.datalab_marker_api_key', - os.getenv('DATALAB_MARKER_API_KEY', ''), -) +DATALAB_MARKER_FORMAT_LINES = os.getenv('DATALAB_MARKER_FORMAT_LINES', 'false').lower() == 'true' -DATALAB_MARKER_API_BASE_URL = ConfigVar( - 'DATALAB_MARKER_API_BASE_URL', - 'rag.datalab_marker_api_base_url', - os.getenv('DATALAB_MARKER_API_BASE_URL', ''), -) +DATALAB_MARKER_OUTPUT_FORMAT = os.getenv('DATALAB_MARKER_OUTPUT_FORMAT', 'markdown') -DATALAB_MARKER_ADDITIONAL_CONFIG = ConfigVar( - 'DATALAB_MARKER_ADDITIONAL_CONFIG', - 'rag.datalab_marker_additional_config', - os.getenv('DATALAB_MARKER_ADDITIONAL_CONFIG', ''), -) +MINERU_API_MODE = os.getenv('MINERU_API_MODE', 'local') -DATALAB_MARKER_USE_LLM = ConfigVar( - 'DATALAB_MARKER_USE_LLM', - 'rag.DATALAB_MARKER_USE_LLM', - os.getenv('DATALAB_MARKER_USE_LLM', 'false').lower() == 'true', -) +MINERU_API_URL = os.getenv('MINERU_API_URL', 'http://localhost:8000') -DATALAB_MARKER_SKIP_CACHE = ConfigVar( - 'DATALAB_MARKER_SKIP_CACHE', - 'rag.datalab_marker_skip_cache', - os.getenv('DATALAB_MARKER_SKIP_CACHE', 'false').lower() == 'true', -) +MINERU_API_TIMEOUT = os.getenv('MINERU_API_TIMEOUT', '300') -DATALAB_MARKER_FORCE_OCR = ConfigVar( - 'DATALAB_MARKER_FORCE_OCR', - 'rag.datalab_marker_force_ocr', - os.getenv('DATALAB_MARKER_FORCE_OCR', 'false').lower() == 'true', -) - -DATALAB_MARKER_PAGINATE = ConfigVar( - 'DATALAB_MARKER_PAGINATE', - 'rag.datalab_marker_paginate', - os.getenv('DATALAB_MARKER_PAGINATE', 'false').lower() == 'true', -) - -DATALAB_MARKER_STRIP_EXISTING_OCR = ConfigVar( - 'DATALAB_MARKER_STRIP_EXISTING_OCR', - 'rag.datalab_marker_strip_existing_ocr', - os.getenv('DATALAB_MARKER_STRIP_EXISTING_OCR', 'false').lower() == 'true', -) - -DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = ConfigVar( - 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION', - 'rag.datalab_marker_disable_image_extraction', - os.getenv('DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION', 'false').lower() == 'true', -) - -DATALAB_MARKER_FORMAT_LINES = ConfigVar( - 'DATALAB_MARKER_FORMAT_LINES', - 'rag.datalab_marker_format_lines', - os.getenv('DATALAB_MARKER_FORMAT_LINES', 'false').lower() == 'true', -) - -DATALAB_MARKER_OUTPUT_FORMAT = ConfigVar( - 'DATALAB_MARKER_OUTPUT_FORMAT', - 'rag.datalab_marker_output_format', - os.getenv('DATALAB_MARKER_OUTPUT_FORMAT', 'markdown'), -) - -MINERU_API_MODE = ConfigVar( - 'MINERU_API_MODE', - 'rag.mineru_api_mode', - os.getenv('MINERU_API_MODE', 'local'), # "local" or "cloud" -) - -MINERU_API_URL = ConfigVar( - 'MINERU_API_URL', - 'rag.mineru_api_url', - os.getenv('MINERU_API_URL', 'http://localhost:8000'), -) - -MINERU_API_TIMEOUT = ConfigVar( - 'MINERU_API_TIMEOUT', - 'rag.mineru_api_timeout', - os.getenv('MINERU_API_TIMEOUT', '300'), -) - -MINERU_API_KEY = ConfigVar( - 'MINERU_API_KEY', - 'rag.mineru_api_key', - os.getenv('MINERU_API_KEY', ''), -) +MINERU_API_KEY = os.getenv('MINERU_API_KEY', '') mineru_params = os.getenv('MINERU_PARAMS', '') try: @@ -1112,47 +870,29 @@ try: except json.JSONDecodeError: mineru_params = {} -MINERU_PARAMS = ConfigVar( - 'MINERU_PARAMS', - 'rag.mineru_params', - mineru_params, -) +MINERU_PARAMS = mineru_params -MINERU_FILE_EXTENSIONS = ConfigVar( - 'MINERU_FILE_EXTENSIONS', - 'rag.mineru_file_extensions', - [ext.strip() for ext in os.getenv('MINERU_FILE_EXTENSIONS', 'pdf').split(',') if ext.strip()], -) +MINERU_FILE_EXTENSIONS = [ext.strip() for ext in os.getenv('MINERU_FILE_EXTENSIONS', 'pdf').split(',') if ext.strip()] -EXTERNAL_DOCUMENT_LOADER_URL = ConfigVar( - 'EXTERNAL_DOCUMENT_LOADER_URL', - 'rag.external_document_loader_url', - os.getenv('EXTERNAL_DOCUMENT_LOADER_URL', ''), -) +EXTERNAL_DOCUMENT_LOADER_URL = os.getenv('EXTERNAL_DOCUMENT_LOADER_URL', '') -EXTERNAL_DOCUMENT_LOADER_API_KEY = ConfigVar( - 'EXTERNAL_DOCUMENT_LOADER_API_KEY', - 'rag.external_document_loader_api_key', - os.getenv('EXTERNAL_DOCUMENT_LOADER_API_KEY', ''), -) +EXTERNAL_DOCUMENT_LOADER_API_KEY = os.getenv('EXTERNAL_DOCUMENT_LOADER_API_KEY', '') -TIKA_SERVER_URL = ConfigVar( - 'TIKA_SERVER_URL', - 'rag.tika_server_url', - os.getenv('TIKA_SERVER_URL', 'http://tika:9998'), # Default for sidecar deployment -) +external_document_loader_headers = os.getenv('EXTERNAL_DOCUMENT_LOADER_HEADERS', '') +try: + external_document_loader_headers = json.loads(external_document_loader_headers) +except json.JSONDecodeError: + external_document_loader_headers = {} +if not isinstance(external_document_loader_headers, dict): + external_document_loader_headers = {} -DOCLING_SERVER_URL = ConfigVar( - 'DOCLING_SERVER_URL', - 'rag.docling_server_url', - os.getenv('DOCLING_SERVER_URL', 'http://docling:5001'), -) +EXTERNAL_DOCUMENT_LOADER_HEADERS = external_document_loader_headers -DOCLING_API_KEY = ConfigVar( - 'DOCLING_API_KEY', - 'rag.docling_api_key', - os.getenv('DOCLING_API_KEY', ''), -) +TIKA_SERVER_URL = os.getenv('TIKA_SERVER_URL', 'http://tika:9998') + +DOCLING_SERVER_URL = os.getenv('DOCLING_SERVER_URL', 'http://docling:5001') + +DOCLING_API_KEY = os.getenv('DOCLING_API_KEY', '') docling_params = os.getenv('DOCLING_PARAMS', '') try: @@ -1160,151 +900,69 @@ try: except json.JSONDecodeError: docling_params = {} -DOCLING_PARAMS = ConfigVar( - 'DOCLING_PARAMS', - 'rag.docling_params', - docling_params, +DOCLING_PARAMS = docling_params + +DOCUMENT_INTELLIGENCE_ENDPOINT = os.getenv('DOCUMENT_INTELLIGENCE_ENDPOINT', '') + +DOCUMENT_INTELLIGENCE_KEY = os.getenv('DOCUMENT_INTELLIGENCE_KEY', '') + +DOCUMENT_INTELLIGENCE_MODEL = os.getenv('DOCUMENT_INTELLIGENCE_MODEL', 'prebuilt-layout') + +MISTRAL_OCR_API_BASE_URL = os.getenv('MISTRAL_OCR_API_BASE_URL', 'https://api.mistral.ai/v1') + +MISTRAL_OCR_API_KEY = os.getenv('MISTRAL_OCR_API_KEY', '') + +MISTRAL_OCR_USE_BASE64 = os.getenv('MISTRAL_OCR_USE_BASE64', 'False').lower() == 'true' + +PADDLEOCR_VL_BASE_URL = os.getenv('PADDLEOCR_VL_BASE_URL', 'http://localhost:8080') + +PADDLEOCR_VL_TOKEN = os.getenv('PADDLEOCR_VL_TOKEN', '') + +BYPASS_EMBEDDING_AND_RETRIEVAL = os.getenv('BYPASS_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true' + + +RAG_TOP_K = int(os.getenv('RAG_TOP_K', '3')) +RAG_TOP_K_RERANKER = int(os.getenv('RAG_TOP_K_RERANKER', '3')) +RAG_RELEVANCE_THRESHOLD = float(os.getenv('RAG_RELEVANCE_THRESHOLD', '0.0')) +RAG_HYBRID_BM25_WEIGHT = float(os.getenv('RAG_HYBRID_BM25_WEIGHT', '0.5')) + +ENABLE_RAG_HYBRID_SEARCH = os.getenv('ENABLE_RAG_HYBRID_SEARCH', '').lower() == 'true' + +ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ( + os.getenv('ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS', 'False').lower() == 'true' ) -DOCUMENT_INTELLIGENCE_ENDPOINT = ConfigVar( - 'DOCUMENT_INTELLIGENCE_ENDPOINT', - 'rag.document_intelligence_endpoint', - os.getenv('DOCUMENT_INTELLIGENCE_ENDPOINT', ''), +RAG_FULL_CONTEXT = os.getenv('RAG_FULL_CONTEXT', 'False').lower() == 'true' + +RAG_FILE_MAX_COUNT = int(os.getenv('RAG_FILE_MAX_COUNT')) if os.getenv('RAG_FILE_MAX_COUNT') else None + +RAG_FILE_MAX_SIZE = int(os.getenv('RAG_FILE_MAX_SIZE')) if os.getenv('RAG_FILE_MAX_SIZE') else None + +RAG_FILE_CONTENT_SEARCH_MAX_CHARS = int(os.getenv('RAG_FILE_CONTENT_SEARCH_MAX_CHARS', str(64 * 1024 * 1024))) + +FILE_IMAGE_COMPRESSION_WIDTH = ( + int(os.getenv('FILE_IMAGE_COMPRESSION_WIDTH')) if os.getenv('FILE_IMAGE_COMPRESSION_WIDTH') else None ) -DOCUMENT_INTELLIGENCE_KEY = ConfigVar( - 'DOCUMENT_INTELLIGENCE_KEY', - 'rag.document_intelligence_key', - os.getenv('DOCUMENT_INTELLIGENCE_KEY', ''), -) - -DOCUMENT_INTELLIGENCE_MODEL = ConfigVar( - 'DOCUMENT_INTELLIGENCE_MODEL', - 'rag.document_intelligence_model', - os.getenv('DOCUMENT_INTELLIGENCE_MODEL', 'prebuilt-layout'), -) - -MISTRAL_OCR_API_BASE_URL = ConfigVar( - 'MISTRAL_OCR_API_BASE_URL', - 'rag.MISTRAL_OCR_API_BASE_URL', - os.getenv('MISTRAL_OCR_API_BASE_URL', 'https://api.mistral.ai/v1'), -) - -MISTRAL_OCR_API_KEY = ConfigVar( - 'MISTRAL_OCR_API_KEY', - 'rag.mistral_ocr_api_key', - os.getenv('MISTRAL_OCR_API_KEY', ''), -) - -PADDLEOCR_VL_BASE_URL = ConfigVar( - 'PADDLEOCR_VL_BASE_URL', - 'rag.paddleocr_vl_base_url', - os.getenv('PADDLEOCR_VL_BASE_URL', 'http://localhost:8080'), -) - -PADDLEOCR_VL_TOKEN = ConfigVar( - 'PADDLEOCR_VL_TOKEN', - 'rag.paddleocr_vl_token', - os.getenv('PADDLEOCR_VL_TOKEN', ''), -) - -BYPASS_EMBEDDING_AND_RETRIEVAL = ConfigVar( - 'BYPASS_EMBEDDING_AND_RETRIEVAL', - 'rag.bypass_embedding_and_retrieval', - os.getenv('BYPASS_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true', +FILE_IMAGE_COMPRESSION_HEIGHT = ( + int(os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT')) if os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT') else None ) -RAG_TOP_K = ConfigVar('RAG_TOP_K', 'rag.top_k', int(os.getenv('RAG_TOP_K', '3'))) -RAG_TOP_K_RERANKER = ConfigVar( - 'RAG_TOP_K_RERANKER', - 'rag.top_k_reranker', - int(os.getenv('RAG_TOP_K_RERANKER', '3')), -) -RAG_RELEVANCE_THRESHOLD = ConfigVar( - 'RAG_RELEVANCE_THRESHOLD', - 'rag.relevance_threshold', - float(os.getenv('RAG_RELEVANCE_THRESHOLD', '0.0')), -) -RAG_HYBRID_BM25_WEIGHT = ConfigVar( - 'RAG_HYBRID_BM25_WEIGHT', - 'rag.hybrid_bm25_weight', - float(os.getenv('RAG_HYBRID_BM25_WEIGHT', '0.5')), -) +RAG_ALLOWED_FILE_EXTENSIONS = [ + ext.strip() for ext in os.getenv('RAG_ALLOWED_FILE_EXTENSIONS', '').split(',') if ext.strip() +] -ENABLE_RAG_HYBRID_SEARCH = ConfigVar( - 'ENABLE_RAG_HYBRID_SEARCH', - 'rag.enable_hybrid_search', - os.getenv('ENABLE_RAG_HYBRID_SEARCH', '').lower() == 'true', -) +RAG_EMBEDDING_ENGINE = os.getenv('RAG_EMBEDDING_ENGINE', '') -ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ConfigVar( - 'ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS', - 'rag.enable_hybrid_search_enriched_texts', - os.getenv('ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS', 'False').lower() == 'true', -) +PDF_EXTRACT_IMAGES = os.getenv('PDF_EXTRACT_IMAGES', 'False').lower() == 'true' -RAG_FULL_CONTEXT = ConfigVar( - 'RAG_FULL_CONTEXT', - 'rag.full_context', - os.getenv('RAG_FULL_CONTEXT', 'False').lower() == 'true', -) +PDF_LOADER_MODE = os.getenv('PDF_LOADER_MODE', 'page') -RAG_FILE_MAX_COUNT = ConfigVar( - 'RAG_FILE_MAX_COUNT', - 'rag.file.max_count', - (int(os.getenv('RAG_FILE_MAX_COUNT')) if os.getenv('RAG_FILE_MAX_COUNT') else None), -) +RAG_EMBEDDING_MODEL = os.getenv('RAG_EMBEDDING_MODEL', 'sentence-transformers/all-MiniLM-L6-v2') +log.info(f'Embedding model set: {RAG_EMBEDDING_MODEL}') -RAG_FILE_MAX_SIZE = ConfigVar( - 'RAG_FILE_MAX_SIZE', - 'rag.file.max_size', - (int(os.getenv('RAG_FILE_MAX_SIZE')) if os.getenv('RAG_FILE_MAX_SIZE') else None), -) - -FILE_IMAGE_COMPRESSION_WIDTH = ConfigVar( - 'FILE_IMAGE_COMPRESSION_WIDTH', - 'file.image_compression_width', - (int(os.getenv('FILE_IMAGE_COMPRESSION_WIDTH')) if os.getenv('FILE_IMAGE_COMPRESSION_WIDTH') else None), -) - -FILE_IMAGE_COMPRESSION_HEIGHT = ConfigVar( - 'FILE_IMAGE_COMPRESSION_HEIGHT', - 'file.image_compression_height', - (int(os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT')) if os.getenv('FILE_IMAGE_COMPRESSION_HEIGHT') else None), -) - - -RAG_ALLOWED_FILE_EXTENSIONS = ConfigVar( - 'RAG_ALLOWED_FILE_EXTENSIONS', - 'rag.file.allowed_extensions', - [ext.strip() for ext in os.getenv('RAG_ALLOWED_FILE_EXTENSIONS', '').split(',') if ext.strip()], -) - -RAG_EMBEDDING_ENGINE = ConfigVar( - 'RAG_EMBEDDING_ENGINE', - 'rag.embedding_engine', - os.getenv('RAG_EMBEDDING_ENGINE', ''), -) - -PDF_EXTRACT_IMAGES = ConfigVar( - 'PDF_EXTRACT_IMAGES', - 'rag.pdf_extract_images', - os.getenv('PDF_EXTRACT_IMAGES', 'False').lower() == 'true', -) - -PDF_LOADER_MODE = ConfigVar( - 'PDF_LOADER_MODE', - 'rag.pdf_loader_mode', - os.getenv('PDF_LOADER_MODE', 'page'), -) - -RAG_EMBEDDING_MODEL = ConfigVar( - 'RAG_EMBEDDING_MODEL', - 'rag.embedding_model', - os.getenv('RAG_EMBEDDING_MODEL', 'sentence-transformers/all-MiniLM-L6-v2'), -) -log.info(f'Embedding model set: {RAG_EMBEDDING_MODEL.value}') +RAG_TOKENIZER_MODEL = os.getenv('RAG_TOKENIZER_MODEL', '') RAG_EMBEDDING_MODEL_AUTO_UPDATE = ( not OFFLINE_MODE and os.getenv('RAG_EMBEDDING_MODEL_AUTO_UPDATE', 'True').lower() == 'true' @@ -1312,23 +970,13 @@ RAG_EMBEDDING_MODEL_AUTO_UPDATE = ( RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE = os.getenv('RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE', 'True').lower() == 'true' -RAG_EMBEDDING_BATCH_SIZE = ConfigVar( - 'RAG_EMBEDDING_BATCH_SIZE', - 'rag.embedding_batch_size', - int(os.getenv('RAG_EMBEDDING_BATCH_SIZE') or os.getenv('RAG_EMBEDDING_OPENAI_BATCH_SIZE', '1')), +RAG_EMBEDDING_BATCH_SIZE = int( + os.getenv('RAG_EMBEDDING_BATCH_SIZE') or os.getenv('RAG_EMBEDDING_OPENAI_BATCH_SIZE', '1') ) -ENABLE_ASYNC_EMBEDDING = ConfigVar( - 'ENABLE_ASYNC_EMBEDDING', - 'rag.enable_async_embedding', - os.getenv('ENABLE_ASYNC_EMBEDDING', 'True').lower() == 'true', -) +ENABLE_ASYNC_EMBEDDING = os.getenv('ENABLE_ASYNC_EMBEDDING', 'True').lower() == 'true' -RAG_EMBEDDING_CONCURRENT_REQUESTS = ConfigVar( - 'RAG_EMBEDDING_CONCURRENT_REQUESTS', - 'rag.embedding_concurrent_requests', - int(os.getenv('RAG_EMBEDDING_CONCURRENT_REQUESTS', '0')), -) +RAG_EMBEDDING_CONCURRENT_REQUESTS = int(os.getenv('RAG_EMBEDDING_CONCURRENT_REQUESTS', '0')) RAG_EMBEDDING_QUERY_PREFIX = os.getenv('RAG_EMBEDDING_QUERY_PREFIX', None) @@ -1336,19 +984,11 @@ RAG_EMBEDDING_CONTENT_PREFIX = os.getenv('RAG_EMBEDDING_CONTENT_PREFIX', None) RAG_EMBEDDING_PREFIX_FIELD_NAME = os.getenv('RAG_EMBEDDING_PREFIX_FIELD_NAME', None) -RAG_RERANKING_ENGINE = ConfigVar( - 'RAG_RERANKING_ENGINE', - 'rag.reranking_engine', - os.getenv('RAG_RERANKING_ENGINE', ''), -) +RAG_RERANKING_ENGINE = os.getenv('RAG_RERANKING_ENGINE', '') -RAG_RERANKING_MODEL = ConfigVar( - 'RAG_RERANKING_MODEL', - 'rag.reranking_model', - os.getenv('RAG_RERANKING_MODEL', ''), -) -if RAG_RERANKING_MODEL.value != '': - log.info(f'Reranking model set: {RAG_RERANKING_MODEL.value}') +RAG_RERANKING_MODEL = os.getenv('RAG_RERANKING_MODEL', '') +if RAG_RERANKING_MODEL != '': + log.info(f'Reranking model set: {RAG_RERANKING_MODEL}') RAG_RERANKING_MODEL_AUTO_UPDATE = ( @@ -1357,65 +997,29 @@ RAG_RERANKING_MODEL_AUTO_UPDATE = ( RAG_RERANKING_MODEL_TRUST_REMOTE_CODE = os.getenv('RAG_RERANKING_MODEL_TRUST_REMOTE_CODE', 'True').lower() == 'true' -RAG_RERANKING_BATCH_SIZE = ConfigVar( - 'RAG_RERANKING_BATCH_SIZE', - 'rag.reranking_batch_size', - int(os.getenv('RAG_RERANKING_BATCH_SIZE', '32')), -) +RAG_RERANKING_BATCH_SIZE = int(os.getenv('RAG_RERANKING_BATCH_SIZE', '32')) -RAG_EXTERNAL_RERANKER_URL = ConfigVar( - 'RAG_EXTERNAL_RERANKER_URL', - 'rag.external_reranker_url', - os.getenv('RAG_EXTERNAL_RERANKER_URL', ''), -) +RAG_EXTERNAL_RERANKER_URL = os.getenv('RAG_EXTERNAL_RERANKER_URL', '') -RAG_EXTERNAL_RERANKER_API_KEY = ConfigVar( - 'RAG_EXTERNAL_RERANKER_API_KEY', - 'rag.external_reranker_api_key', - os.getenv('RAG_EXTERNAL_RERANKER_API_KEY', ''), -) +RAG_EXTERNAL_RERANKER_API_KEY = os.getenv('RAG_EXTERNAL_RERANKER_API_KEY', '') -RAG_EXTERNAL_RERANKER_TIMEOUT = ConfigVar( - 'RAG_EXTERNAL_RERANKER_TIMEOUT', - 'rag.external_reranker_timeout', - os.getenv('RAG_EXTERNAL_RERANKER_TIMEOUT', ''), -) +RAG_EXTERNAL_RERANKER_TIMEOUT = os.getenv('RAG_EXTERNAL_RERANKER_TIMEOUT', '') -RAG_TEXT_SPLITTER = ConfigVar( - 'RAG_TEXT_SPLITTER', - 'rag.text_splitter', - os.getenv('RAG_TEXT_SPLITTER', ''), -) +RAG_TEXT_SPLITTER = os.getenv('RAG_TEXT_SPLITTER', '') -ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = ConfigVar( - 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER', - 'rag.enable_markdown_header_text_splitter', - os.getenv('ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER', 'True').lower() == 'true', -) +ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = os.getenv('ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER', 'True').lower() == 'true' TIKTOKEN_CACHE_DIR = os.getenv('TIKTOKEN_CACHE_DIR', f'{CACHE_DIR}/tiktoken') -TIKTOKEN_ENCODING_NAME = ConfigVar( - 'TIKTOKEN_ENCODING_NAME', - 'rag.tiktoken_encoding_name', - os.getenv('TIKTOKEN_ENCODING_NAME', 'cl100k_base'), -) +TIKTOKEN_ENCODING_NAME = os.getenv('TIKTOKEN_ENCODING_NAME', 'cl100k_base') -CHUNK_SIZE = ConfigVar('CHUNK_SIZE', 'rag.chunk_size', int(os.getenv('CHUNK_SIZE', '1000'))) +CHUNK_SIZE = int(os.getenv('CHUNK_SIZE', '1000')) -CHUNK_MIN_SIZE_TARGET = ConfigVar( - 'CHUNK_MIN_SIZE_TARGET', - 'rag.chunk_min_size_target', - int(os.getenv('CHUNK_MIN_SIZE_TARGET', '0')), -) +CHUNK_MIN_SIZE_TARGET = int(os.getenv('CHUNK_MIN_SIZE_TARGET', '0')) -CHUNK_OVERLAP = ConfigVar( - 'CHUNK_OVERLAP', - 'rag.chunk_overlap', - int(os.getenv('CHUNK_OVERLAP', '100')), -) +CHUNK_OVERLAP = int(os.getenv('CHUNK_OVERLAP', '100')) DEFAULT_RAG_TEMPLATE = """### Task: Respond to the user query using the provided context, incorporating inline citations in the format [id] **only when the tag includes an explicit id attribute** (e.g., ). @@ -1443,53 +1047,29 @@ Provide a clear and direct response to the user's query, including inline citati """ -RAG_TEMPLATE = ConfigVar( - 'RAG_TEMPLATE', - 'rag.template', - os.getenv('RAG_TEMPLATE', DEFAULT_RAG_TEMPLATE), -) +RAG_TEMPLATE = os.getenv('RAG_TEMPLATE', DEFAULT_RAG_TEMPLATE) -RAG_OPENAI_API_BASE_URL = ConfigVar( - 'RAG_OPENAI_API_BASE_URL', - 'rag.openai_api_base_url', - os.getenv('RAG_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL), -) -RAG_OPENAI_API_KEY = ConfigVar( - 'RAG_OPENAI_API_KEY', - 'rag.openai_api_key', - os.getenv('RAG_OPENAI_API_KEY', OPENAI_API_KEY), -) +RAG_OPENAI_API_BASE_URL = os.getenv('RAG_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) +RAG_OPENAI_API_KEY = os.getenv('RAG_OPENAI_API_KEY', OPENAI_API_KEY) -RAG_AZURE_OPENAI_BASE_URL = ConfigVar( - 'RAG_AZURE_OPENAI_BASE_URL', - 'rag.azure_openai.base_url', - os.getenv('RAG_AZURE_OPENAI_BASE_URL', ''), -) -RAG_AZURE_OPENAI_API_KEY = ConfigVar( - 'RAG_AZURE_OPENAI_API_KEY', - 'rag.azure_openai.api_key', - os.getenv('RAG_AZURE_OPENAI_API_KEY', ''), -) -RAG_AZURE_OPENAI_API_VERSION = ConfigVar( - 'RAG_AZURE_OPENAI_API_VERSION', - 'rag.azure_openai.api_version', - os.getenv('RAG_AZURE_OPENAI_API_VERSION', ''), -) +RAG_AZURE_OPENAI_BASE_URL = os.getenv('RAG_AZURE_OPENAI_BASE_URL', '') +RAG_AZURE_OPENAI_API_KEY = os.getenv('RAG_AZURE_OPENAI_API_KEY', '') +RAG_AZURE_OPENAI_API_VERSION = os.getenv('RAG_AZURE_OPENAI_API_VERSION', '') -RAG_OLLAMA_BASE_URL = ConfigVar( - 'RAG_OLLAMA_BASE_URL', - 'rag.ollama.url', - os.getenv('RAG_OLLAMA_BASE_URL', OLLAMA_BASE_URL), -) +RAG_OLLAMA_BASE_URL = os.getenv('RAG_OLLAMA_BASE_URL', OLLAMA_BASE_URL) -RAG_OLLAMA_API_KEY = ConfigVar( - 'RAG_OLLAMA_API_KEY', - 'rag.ollama.key', - os.getenv('RAG_OLLAMA_API_KEY', ''), -) +RAG_OLLAMA_API_KEY = os.getenv('RAG_OLLAMA_API_KEY', '') -ENABLE_RAG_LOCAL_WEB_FETCH = os.getenv('ENABLE_RAG_LOCAL_WEB_FETCH', 'False').lower() == 'true' +ENABLE_LOCAL_WEB_FETCH = ( + os.getenv( + 'ENABLE_LOCAL_WEB_FETCH', + os.getenv('ENABLE_RAG_LOCAL_WEB_FETCH', 'False'), + ).lower() + == 'true' +) +# Deprecated compatibility alias; use ENABLE_LOCAL_WEB_FETCH for new deployments. +ENABLE_RAG_LOCAL_WEB_FETCH = ENABLE_LOCAL_WEB_FETCH DEFAULT_WEB_FETCH_FILTER_LIST = [ @@ -1509,53 +1089,34 @@ else: WEB_FETCH_FILTER_LIST = list(set(DEFAULT_WEB_FETCH_FILTER_LIST + web_fetch_filter_list)) -YOUTUBE_LOADER_LANGUAGE = ConfigVar( - 'YOUTUBE_LOADER_LANGUAGE', - 'rag.youtube_loader_language', - os.getenv('YOUTUBE_LOADER_LANGUAGE', 'en').split(','), -) +YOUTUBE_LOADER_LANGUAGE = os.getenv('YOUTUBE_LOADER_LANGUAGE', 'en').split(',') -YOUTUBE_LOADER_PROXY_URL = ConfigVar( - 'YOUTUBE_LOADER_PROXY_URL', - 'rag.youtube_loader_proxy_url', - os.getenv('YOUTUBE_LOADER_PROXY_URL', ''), -) +YOUTUBE_LOADER_PROXY_URL = os.getenv('YOUTUBE_LOADER_PROXY_URL', '') #################################### -# Web Search (RAG) +# Web Search #################################### -ENABLE_WEB_SEARCH = ConfigVar( - 'ENABLE_WEB_SEARCH', - 'rag.web.search.enable', - os.getenv('ENABLE_WEB_SEARCH', 'False').lower() == 'true', +ENABLE_WEB_SEARCH = os.getenv('ENABLE_WEB_SEARCH', 'False').lower() == 'true' + +ENABLE_WEB_SEARCH_CONFIRMATION = os.getenv('ENABLE_WEB_SEARCH_CONFIRMATION', 'False').lower() == 'true' + +WEB_SEARCH_CONFIRMATION_CONTENT = os.getenv( + 'WEB_SEARCH_CONFIRMATION_CONTENT', + 'Your query will be sent to the configured web search provider.', ) -WEB_SEARCH_ENGINE = ConfigVar( - 'WEB_SEARCH_ENGINE', - 'rag.web.search.engine', - os.getenv('WEB_SEARCH_ENGINE', ''), -) +WEB_SEARCH_ENGINE = os.getenv('WEB_SEARCH_ENGINE', '') -BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = ConfigVar( - 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', - 'rag.web.search.bypass_embedding_and_retrieval', - os.getenv('BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true', +BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = ( + os.getenv('BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', 'False').lower() == 'true' ) -BYPASS_WEB_SEARCH_WEB_LOADER = ConfigVar( - 'BYPASS_WEB_SEARCH_WEB_LOADER', - 'rag.web.search.bypass_web_loader', - os.getenv('BYPASS_WEB_SEARCH_WEB_LOADER', 'False').lower() == 'true', -) +BYPASS_WEB_SEARCH_WEB_LOADER = os.getenv('BYPASS_WEB_SEARCH_WEB_LOADER', 'False').lower() == 'true' -WEB_SEARCH_RESULT_COUNT = ConfigVar( - 'WEB_SEARCH_RESULT_COUNT', - 'rag.web.search.result_count', - int(os.getenv('WEB_SEARCH_RESULT_COUNT', '3')), -) +WEB_SEARCH_RESULT_COUNT = int(os.getenv('WEB_SEARCH_RESULT_COUNT', '3')) try: @@ -1570,368 +1131,140 @@ except Exception as e: # You can provide a list of your own websites to filter after performing a web search. # This ensures the highest level of safety and reliability of the information sources. -WEB_SEARCH_DOMAIN_FILTER_LIST = ConfigVar( - 'WEB_SEARCH_DOMAIN_FILTER_LIST', - 'rag.web.search.domain.filter_list', - web_search_domain_filter_list, +WEB_SEARCH_DOMAIN_FILTER_LIST = web_search_domain_filter_list + +WEB_SEARCH_CONCURRENT_REQUESTS = int(os.getenv('WEB_SEARCH_CONCURRENT_REQUESTS', '0')) + +WEB_FETCH_MAX_CONTENT_LENGTH = ( + int(os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH')) if os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH') else None ) -WEB_SEARCH_CONCURRENT_REQUESTS = ConfigVar( - 'WEB_SEARCH_CONCURRENT_REQUESTS', - 'rag.web.search.concurrent_requests', - int(os.getenv('WEB_SEARCH_CONCURRENT_REQUESTS', '0')), -) - -WEB_FETCH_MAX_CONTENT_LENGTH = ConfigVar( - 'WEB_FETCH_MAX_CONTENT_LENGTH', - 'rag.web.fetch.max_content_length', - (int(os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH')) if os.getenv('WEB_FETCH_MAX_CONTENT_LENGTH') else None), -) - -WEB_LOADER_ENGINE = ConfigVar( - 'WEB_LOADER_ENGINE', - 'rag.web.loader.engine', - os.getenv('WEB_LOADER_ENGINE', ''), -) +WEB_LOADER_ENGINE = os.getenv('WEB_LOADER_ENGINE', '') -WEB_LOADER_CONCURRENT_REQUESTS = ConfigVar( - 'WEB_LOADER_CONCURRENT_REQUESTS', - 'rag.web.loader.concurrent_requests', - int(os.getenv('WEB_LOADER_CONCURRENT_REQUESTS', '10')), -) +WEB_LOADER_CONCURRENT_REQUESTS = int(os.getenv('WEB_LOADER_CONCURRENT_REQUESTS', '10')) -WEB_LOADER_TIMEOUT = ConfigVar( - 'WEB_LOADER_TIMEOUT', - 'rag.web.loader.timeout', - os.getenv('WEB_LOADER_TIMEOUT', ''), -) +WEB_LOADER_TIMEOUT = os.getenv('WEB_LOADER_TIMEOUT', '') -ENABLE_WEB_LOADER_SSL_VERIFICATION = ConfigVar( - 'ENABLE_WEB_LOADER_SSL_VERIFICATION', - 'rag.web.loader.ssl_verification', - os.getenv('ENABLE_WEB_LOADER_SSL_VERIFICATION', 'True').lower() == 'true', -) +ENABLE_WEB_LOADER_SSL_VERIFICATION = os.getenv('ENABLE_WEB_LOADER_SSL_VERIFICATION', 'True').lower() == 'true' -WEB_SEARCH_TRUST_ENV = ConfigVar( - 'WEB_SEARCH_TRUST_ENV', - 'rag.web.search.trust_env', - os.getenv('WEB_SEARCH_TRUST_ENV', 'True').lower() == 'true', -) +WEB_SEARCH_TRUST_ENV = os.getenv('WEB_SEARCH_TRUST_ENV', 'True').lower() == 'true' -OLLAMA_CLOUD_WEB_SEARCH_API_KEY = ConfigVar( - 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY', - 'rag.web.search.ollama_cloud_api_key', - os.getenv('OLLAMA_CLOUD_API_KEY', ''), -) +OLLAMA_CLOUD_WEB_SEARCH_API_KEY = os.getenv('OLLAMA_CLOUD_API_KEY', '') -SEARXNG_QUERY_URL = ConfigVar( - 'SEARXNG_QUERY_URL', - 'rag.web.search.searxng_query_url', - os.getenv('SEARXNG_QUERY_URL', ''), -) +SEARXNG_QUERY_URL = os.getenv('SEARXNG_QUERY_URL', '') -SEARXNG_LANGUAGE = ConfigVar( - 'SEARXNG_LANGUAGE', - 'rag.web.search.searxng_language', - os.getenv('SEARXNG_LANGUAGE', 'all'), -) +SEARXNG_LANGUAGE = os.getenv('SEARXNG_LANGUAGE', 'all') -YACY_QUERY_URL = ConfigVar( - 'YACY_QUERY_URL', - 'rag.web.search.yacy_query_url', - os.getenv('YACY_QUERY_URL', ''), -) +YACY_QUERY_URL = os.getenv('YACY_QUERY_URL', '') -YACY_USERNAME = ConfigVar( - 'YACY_USERNAME', - 'rag.web.search.yacy_username', - os.getenv('YACY_USERNAME', ''), -) +YACY_USERNAME = os.getenv('YACY_USERNAME', '') -YACY_PASSWORD = ConfigVar( - 'YACY_PASSWORD', - 'rag.web.search.yacy_password', - os.getenv('YACY_PASSWORD', ''), -) +YACY_PASSWORD = os.getenv('YACY_PASSWORD', '') -GOOGLE_PSE_API_KEY = ConfigVar( - 'GOOGLE_PSE_API_KEY', - 'rag.web.search.google_pse_api_key', - os.getenv('GOOGLE_PSE_API_KEY', ''), -) +GOOGLE_PSE_API_KEY = os.getenv('GOOGLE_PSE_API_KEY', '') -GOOGLE_PSE_ENGINE_ID = ConfigVar( - 'GOOGLE_PSE_ENGINE_ID', - 'rag.web.search.google_pse_engine_id', - os.getenv('GOOGLE_PSE_ENGINE_ID', ''), -) +GOOGLE_PSE_ENGINE_ID = os.getenv('GOOGLE_PSE_ENGINE_ID', '') -BRAVE_SEARCH_API_KEY = ConfigVar( - 'BRAVE_SEARCH_API_KEY', - 'rag.web.search.brave_search_api_key', - os.getenv('BRAVE_SEARCH_API_KEY', ''), -) +BRAVE_SEARCH_API_KEY = os.getenv('BRAVE_SEARCH_API_KEY', '') -BRAVE_SEARCH_CONTEXT_TOKENS = ConfigVar( - 'BRAVE_SEARCH_CONTEXT_TOKENS', - 'rag.web.search.brave_search_context_tokens', - int(os.getenv('BRAVE_SEARCH_CONTEXT_TOKENS', '8192')), -) +BRAVE_SEARCH_CONTEXT_TOKENS = int(os.getenv('BRAVE_SEARCH_CONTEXT_TOKENS', '8192')) -KAGI_SEARCH_API_KEY = ConfigVar( - 'KAGI_SEARCH_API_KEY', - 'rag.web.search.kagi_search_api_key', - os.getenv('KAGI_SEARCH_API_KEY', ''), -) +KAGI_SEARCH_API_KEY = os.getenv('KAGI_SEARCH_API_KEY', '') -MOJEEK_SEARCH_API_KEY = ConfigVar( - 'MOJEEK_SEARCH_API_KEY', - 'rag.web.search.mojeek_search_api_key', - os.getenv('MOJEEK_SEARCH_API_KEY', ''), -) +MOJEEK_SEARCH_API_KEY = os.getenv('MOJEEK_SEARCH_API_KEY', '') -BOCHA_SEARCH_API_KEY = ConfigVar( - 'BOCHA_SEARCH_API_KEY', - 'rag.web.search.bocha_search_api_key', - os.getenv('BOCHA_SEARCH_API_KEY', ''), -) +BOCHA_SEARCH_API_KEY = os.getenv('BOCHA_SEARCH_API_KEY', '') -SERPSTACK_API_KEY = ConfigVar( - 'SERPSTACK_API_KEY', - 'rag.web.search.serpstack_api_key', - os.getenv('SERPSTACK_API_KEY', ''), -) +SERPSTACK_API_KEY = os.getenv('SERPSTACK_API_KEY', '') -SERPSTACK_HTTPS = ConfigVar( - 'SERPSTACK_HTTPS', - 'rag.web.search.serpstack_https', - os.getenv('SERPSTACK_HTTPS', 'True').lower() == 'true', -) +SERPSTACK_HTTPS = os.getenv('SERPSTACK_HTTPS', 'True').lower() == 'true' -SERPER_API_KEY = ConfigVar( - 'SERPER_API_KEY', - 'rag.web.search.serper_api_key', - os.getenv('SERPER_API_KEY', ''), -) +SERPER_API_KEY = os.getenv('SERPER_API_KEY', '') -SERPLY_API_KEY = ConfigVar( - 'SERPLY_API_KEY', - 'rag.web.search.serply_api_key', - os.getenv('SERPLY_API_KEY', ''), -) +SERPLY_API_KEY = os.getenv('SERPLY_API_KEY', '') -DDGS_BACKEND = ConfigVar( - 'DDGS_BACKEND', - 'rag.web.search.ddgs_backend', - os.getenv('DDGS_BACKEND', 'auto'), -) +SERPHOUSE_API_KEY = os.getenv('SERPHOUSE_API_KEY', '') -JINA_API_KEY = ConfigVar( - 'JINA_API_KEY', - 'rag.web.search.jina_api_key', - os.getenv('JINA_API_KEY', ''), -) +SERPHOUSE_DOMAIN = os.getenv('SERPHOUSE_DOMAIN', 'google.com') -JINA_API_BASE_URL = ConfigVar( - 'JINA_API_BASE_URL', - 'rag.web.search.jina_api_base_url', - os.getenv('JINA_API_BASE_URL', ''), -) +DDGS_BACKEND = os.getenv('DDGS_BACKEND', 'auto') -SEARCHAPI_API_KEY = ConfigVar( - 'SEARCHAPI_API_KEY', - 'rag.web.search.searchapi_api_key', - os.getenv('SEARCHAPI_API_KEY', ''), -) +JINA_API_KEY = os.getenv('JINA_API_KEY', '') -SEARCHAPI_ENGINE = ConfigVar( - 'SEARCHAPI_ENGINE', - 'rag.web.search.searchapi_engine', - os.getenv('SEARCHAPI_ENGINE', ''), -) +JINA_API_BASE_URL = os.getenv('JINA_API_BASE_URL', '') -SERPAPI_API_KEY = ConfigVar( - 'SERPAPI_API_KEY', - 'rag.web.search.serpapi_api_key', - os.getenv('SERPAPI_API_KEY', ''), -) +SEARCHAPI_API_KEY = os.getenv('SEARCHAPI_API_KEY', '') -SERPAPI_ENGINE = ConfigVar( - 'SERPAPI_ENGINE', - 'rag.web.search.serpapi_engine', - os.getenv('SERPAPI_ENGINE', ''), -) +SEARCHAPI_ENGINE = os.getenv('SEARCHAPI_ENGINE', '') -BING_SEARCH_V7_ENDPOINT = ConfigVar( - 'BING_SEARCH_V7_ENDPOINT', - 'rag.web.search.bing_search_v7_endpoint', - os.getenv('BING_SEARCH_V7_ENDPOINT', 'https://api.bing.microsoft.com/v7.0/search'), -) +SERPAPI_API_KEY = os.getenv('SERPAPI_API_KEY', '') -BING_SEARCH_V7_SUBSCRIPTION_KEY = ConfigVar( - 'BING_SEARCH_V7_SUBSCRIPTION_KEY', - 'rag.web.search.bing_search_v7_subscription_key', - os.getenv('BING_SEARCH_V7_SUBSCRIPTION_KEY', ''), -) +SERPAPI_ENGINE = os.getenv('SERPAPI_ENGINE', '') -AZURE_AI_SEARCH_API_KEY = ConfigVar( - 'AZURE_AI_SEARCH_API_KEY', - 'rag.web.search.azure_ai_search_api_key', - os.getenv('AZURE_AI_SEARCH_API_KEY', ''), -) +BING_SEARCH_V7_ENDPOINT = os.getenv('BING_SEARCH_V7_ENDPOINT', 'https://api.bing.microsoft.com/v7.0/search') -AZURE_AI_SEARCH_ENDPOINT = ConfigVar( - 'AZURE_AI_SEARCH_ENDPOINT', - 'rag.web.search.azure_ai_search_endpoint', - os.getenv('AZURE_AI_SEARCH_ENDPOINT', ''), -) +BING_SEARCH_V7_SUBSCRIPTION_KEY = os.getenv('BING_SEARCH_V7_SUBSCRIPTION_KEY', '') -AZURE_AI_SEARCH_INDEX_NAME = ConfigVar( - 'AZURE_AI_SEARCH_INDEX_NAME', - 'rag.web.search.azure_ai_search_index_name', - os.getenv('AZURE_AI_SEARCH_INDEX_NAME', ''), -) +AZURE_AI_SEARCH_API_KEY = os.getenv('AZURE_AI_SEARCH_API_KEY', '') -EXA_API_KEY = ConfigVar( - 'EXA_API_KEY', - 'rag.web.search.exa_api_key', - os.getenv('EXA_API_KEY', ''), -) +AZURE_AI_SEARCH_ENDPOINT = os.getenv('AZURE_AI_SEARCH_ENDPOINT', '') -PERPLEXITY_API_KEY = ConfigVar( - 'PERPLEXITY_API_KEY', - 'rag.web.search.perplexity_api_key', - os.getenv('PERPLEXITY_API_KEY', ''), -) +AZURE_AI_SEARCH_INDEX_NAME = os.getenv('AZURE_AI_SEARCH_INDEX_NAME', '') -PERPLEXITY_MODEL = ConfigVar( - 'PERPLEXITY_MODEL', - 'rag.web.search.perplexity_model', - os.getenv('PERPLEXITY_MODEL', 'sonar'), -) +EXA_API_KEY = os.getenv('EXA_API_KEY', '') -PERPLEXITY_SEARCH_CONTEXT_USAGE = ConfigVar( - 'PERPLEXITY_SEARCH_CONTEXT_USAGE', - 'rag.web.search.perplexity_search_context_usage', - os.getenv('PERPLEXITY_SEARCH_CONTEXT_USAGE', 'medium'), -) +PERPLEXITY_API_KEY = os.getenv('PERPLEXITY_API_KEY', '') -PERPLEXITY_SEARCH_API_URL = ConfigVar( - 'PERPLEXITY_SEARCH_API_URL', - 'rag.web.search.perplexity_search_api_url', - os.getenv('PERPLEXITY_SEARCH_API_URL', 'https://api.perplexity.ai/search'), -) +PERPLEXITY_MODEL = os.getenv('PERPLEXITY_MODEL', 'sonar') -SOUGOU_API_SID = ConfigVar( - 'SOUGOU_API_SID', - 'rag.web.search.sougou_api_sid', - os.getenv('SOUGOU_API_SID', ''), -) +PERPLEXITY_SEARCH_CONTEXT_USAGE = os.getenv('PERPLEXITY_SEARCH_CONTEXT_USAGE', 'medium') -SOUGOU_API_SK = ConfigVar( - 'SOUGOU_API_SK', - 'rag.web.search.sougou_api_sk', - os.getenv('SOUGOU_API_SK', ''), -) +PERPLEXITY_SEARCH_API_URL = os.getenv('PERPLEXITY_SEARCH_API_URL', 'https://api.perplexity.ai/search') -TAVILY_API_KEY = ConfigVar( - 'TAVILY_API_KEY', - 'rag.web.search.tavily_api_key', - os.getenv('TAVILY_API_KEY', ''), -) +MICROSOFT_WEB_IQ_API_BASE_URL = os.getenv('MICROSOFT_WEB_IQ_API_BASE_URL', 'https://api.microsoft.ai/v3') -TAVILY_EXTRACT_DEPTH = ConfigVar( - 'TAVILY_EXTRACT_DEPTH', - 'rag.web.search.tavily_extract_depth', - os.getenv('TAVILY_EXTRACT_DEPTH', 'basic'), -) +MICROSOFT_WEB_IQ_API_KEY = os.getenv('MICROSOFT_WEB_IQ_API_KEY', '') -PLAYWRIGHT_WS_URL = ConfigVar( - 'PLAYWRIGHT_WS_URL', - 'rag.web.loader.playwright_ws_url', - os.getenv('PLAYWRIGHT_WS_URL', ''), -) +MICROSOFT_WEB_IQ_LANGUAGE = os.getenv('MICROSOFT_WEB_IQ_LANGUAGE', 'en') -PLAYWRIGHT_TIMEOUT = ConfigVar( - 'PLAYWRIGHT_TIMEOUT', - 'rag.web.loader.playwright_timeout', - int(os.getenv('PLAYWRIGHT_TIMEOUT', '10000')), -) +SOUGOU_API_SID = os.getenv('SOUGOU_API_SID', '') -FIRECRAWL_API_KEY = ConfigVar( - 'FIRECRAWL_API_KEY', - 'rag.web.loader.firecrawl_api_key', - os.getenv('FIRECRAWL_API_KEY', ''), -) +SOUGOU_API_SK = os.getenv('SOUGOU_API_SK', '') -FIRECRAWL_API_BASE_URL = ConfigVar( - 'FIRECRAWL_API_BASE_URL', - 'rag.web.loader.firecrawl_api_url', - os.getenv('FIRECRAWL_API_BASE_URL', 'https://api.firecrawl.dev'), -) +TAVILY_API_KEY = os.getenv('TAVILY_API_KEY', '') -FIRECRAWL_TIMEOUT = ConfigVar( - 'FIRECRAWL_TIMEOUT', - 'rag.web.loader.firecrawl_timeout', - os.getenv('FIRECRAWL_TIMEOUT', ''), -) +TAVILY_EXTRACT_DEPTH = os.getenv('TAVILY_EXTRACT_DEPTH', 'basic') -EXTERNAL_WEB_SEARCH_URL = ConfigVar( - 'EXTERNAL_WEB_SEARCH_URL', - 'rag.web.search.external_web_search_url', - os.getenv('EXTERNAL_WEB_SEARCH_URL', ''), -) +PLAYWRIGHT_WS_URL = os.getenv('PLAYWRIGHT_WS_URL', '') -EXTERNAL_WEB_SEARCH_API_KEY = ConfigVar( - 'EXTERNAL_WEB_SEARCH_API_KEY', - 'rag.web.search.external_web_search_api_key', - os.getenv('EXTERNAL_WEB_SEARCH_API_KEY', ''), -) +PLAYWRIGHT_TIMEOUT = int(os.getenv('PLAYWRIGHT_TIMEOUT', '10000')) -EXTERNAL_WEB_LOADER_URL = ConfigVar( - 'EXTERNAL_WEB_LOADER_URL', - 'rag.web.loader.external_web_loader_url', - os.getenv('EXTERNAL_WEB_LOADER_URL', ''), -) +FIRECRAWL_API_KEY = os.getenv('FIRECRAWL_API_KEY', '') -EXTERNAL_WEB_LOADER_API_KEY = ConfigVar( - 'EXTERNAL_WEB_LOADER_API_KEY', - 'rag.web.loader.external_web_loader_api_key', - os.getenv('EXTERNAL_WEB_LOADER_API_KEY', ''), -) +FIRECRAWL_API_BASE_URL = os.getenv('FIRECRAWL_API_BASE_URL', 'https://api.firecrawl.dev') -YANDEX_WEB_SEARCH_URL = ConfigVar( - 'YANDEX_WEB_SEARCH_URL', - 'rag.web.search.yandex_web_search_url', - os.getenv('YANDEX_WEB_SEARCH_URL', ''), -) +FIRECRAWL_TIMEOUT = os.getenv('FIRECRAWL_TIMEOUT', '') -YANDEX_WEB_SEARCH_API_KEY = ConfigVar( - 'YANDEX_WEB_SEARCH_API_KEY', - 'rag.web.search.yandex_web_search_api_key', - os.getenv('YANDEX_WEB_SEARCH_API_KEY', ''), -) +EXTERNAL_WEB_SEARCH_URL = os.getenv('EXTERNAL_WEB_SEARCH_URL', '') -YANDEX_WEB_SEARCH_CONFIG = ConfigVar( - 'YANDEX_WEB_SEARCH_CONFIG', - 'rag.web.search.yandex_web_search_config', - os.getenv('YANDEX_WEB_SEARCH_CONFIG', ''), -) +EXTERNAL_WEB_SEARCH_API_KEY = os.getenv('EXTERNAL_WEB_SEARCH_API_KEY', '') -YOUCOM_API_KEY = ConfigVar( - 'YOUCOM_API_KEY', - 'rag.web.search.youcom_api_key', - os.getenv('YOUCOM_API_KEY', ''), -) +EXTERNAL_WEB_LOADER_URL = os.getenv('EXTERNAL_WEB_LOADER_URL', '') -LINKUP_API_KEY = ConfigVar( - 'LINKUP_API_KEY', - 'rag.web.search.linkup_api_key', - os.getenv('LINKUP_API_KEY', ''), -) +EXTERNAL_WEB_LOADER_API_KEY = os.getenv('EXTERNAL_WEB_LOADER_API_KEY', '') + +YANDEX_WEB_SEARCH_URL = os.getenv('YANDEX_WEB_SEARCH_URL', '') + +YANDEX_WEB_SEARCH_API_KEY = os.getenv('YANDEX_WEB_SEARCH_API_KEY', '') + +YANDEX_WEB_SEARCH_CONFIG = os.getenv('YANDEX_WEB_SEARCH_CONFIG', '') + +YOUCOM_API_KEY = os.getenv('YOUCOM_API_KEY', os.getenv('YDC_API_KEY', '')) + +LINKUP_API_KEY = os.getenv('LINKUP_API_KEY', '') linkup_search_params = os.getenv('LINKUP_SEARCH_PARAMS', '') try: @@ -1939,33 +1272,17 @@ try: except json.JSONDecodeError: linkup_search_params = {} -LINKUP_SEARCH_PARAMS = ConfigVar( - 'LINKUP_SEARCH_PARAMS', - 'rag.web.search.linkup_search_params', - linkup_search_params, -) +LINKUP_SEARCH_PARAMS = linkup_search_params #################################### # Images #################################### -ENABLE_IMAGE_GENERATION = ConfigVar( - 'ENABLE_IMAGE_GENERATION', - 'image_generation.enable', - os.getenv('ENABLE_IMAGE_GENERATION', '').lower() == 'true', -) +ENABLE_IMAGE_GENERATION = os.getenv('ENABLE_IMAGE_GENERATION', '').lower() == 'true' -IMAGE_GENERATION_ENGINE = ConfigVar( - 'IMAGE_GENERATION_ENGINE', - 'image_generation.engine', - os.getenv('IMAGE_GENERATION_ENGINE', 'openai'), -) +IMAGE_GENERATION_ENGINE = os.getenv('IMAGE_GENERATION_ENGINE', 'openai') -IMAGE_GENERATION_MODEL = ConfigVar( - 'IMAGE_GENERATION_MODEL', - 'image_generation.model', - os.getenv('IMAGE_GENERATION_MODEL', ''), -) +IMAGE_GENERATION_MODEL = os.getenv('IMAGE_GENERATION_MODEL', '') # Regex pattern for models that support IMAGE_SIZE = "auto". IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN = os.getenv('IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN', '^gpt-image') @@ -1973,26 +1290,14 @@ IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN = os.getenv('IMAGE_AUTO_SIZE_MODELS_REGEX_P # Regex pattern for models that return URLs instead of base64 data. IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN = os.getenv('IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN', '^gpt-image') -IMAGE_SIZE = ConfigVar('IMAGE_SIZE', 'image_generation.size', os.getenv('IMAGE_SIZE', '512x512')) +IMAGE_SIZE = os.getenv('IMAGE_SIZE', '512x512') -IMAGE_STEPS = ConfigVar('IMAGE_STEPS', 'image_generation.steps', int(os.getenv('IMAGE_STEPS', 50))) +IMAGE_STEPS = int(os.getenv('IMAGE_STEPS', 50)) -ENABLE_IMAGE_PROMPT_GENERATION = ConfigVar( - 'ENABLE_IMAGE_PROMPT_GENERATION', - 'image_generation.prompt.enable', - os.getenv('ENABLE_IMAGE_PROMPT_GENERATION', 'true').lower() == 'true', -) +ENABLE_IMAGE_PROMPT_GENERATION = os.getenv('ENABLE_IMAGE_PROMPT_GENERATION', 'true').lower() == 'true' -AUTOMATIC1111_BASE_URL = ConfigVar( - 'AUTOMATIC1111_BASE_URL', - 'image_generation.automatic1111.base_url', - os.getenv('AUTOMATIC1111_BASE_URL', ''), -) -AUTOMATIC1111_API_AUTH = ConfigVar( - 'AUTOMATIC1111_API_AUTH', - 'image_generation.automatic1111.api_auth', - os.getenv('AUTOMATIC1111_API_AUTH', ''), -) +AUTOMATIC1111_BASE_URL = os.getenv('AUTOMATIC1111_BASE_URL', '') +AUTOMATIC1111_API_AUTH = os.getenv('AUTOMATIC1111_API_AUTH', '') automatic1111_params = os.getenv('AUTOMATIC1111_PARAMS', '') try: @@ -2000,23 +1305,11 @@ try: except json.JSONDecodeError: automatic1111_params = {} -AUTOMATIC1111_PARAMS = ConfigVar( - 'AUTOMATIC1111_PARAMS', - 'image_generation.automatic1111.api_params', - automatic1111_params, -) +AUTOMATIC1111_PARAMS = automatic1111_params -COMFYUI_BASE_URL = ConfigVar( - 'COMFYUI_BASE_URL', - 'image_generation.comfyui.base_url', - os.getenv('COMFYUI_BASE_URL', ''), -) +COMFYUI_BASE_URL = os.getenv('COMFYUI_BASE_URL', '') -COMFYUI_API_KEY = ConfigVar( - 'COMFYUI_API_KEY', - 'image_generation.comfyui.api_key', - os.getenv('COMFYUI_API_KEY', ''), -) +COMFYUI_API_KEY = os.getenv('COMFYUI_API_KEY', '') COMFYUI_DEFAULT_WORKFLOW = """ { @@ -2129,11 +1422,7 @@ COMFYUI_DEFAULT_WORKFLOW = """ """ -COMFYUI_WORKFLOW = ConfigVar( - 'COMFYUI_WORKFLOW', - 'image_generation.comfyui.workflow', - os.getenv('COMFYUI_WORKFLOW', COMFYUI_DEFAULT_WORKFLOW), -) +COMFYUI_WORKFLOW = os.getenv('COMFYUI_WORKFLOW', COMFYUI_DEFAULT_WORKFLOW) comfyui_workflow_nodes = os.getenv('COMFYUI_WORKFLOW_NODES', '') try: @@ -2141,28 +1430,12 @@ try: except json.JSONDecodeError: comfyui_workflow_nodes = [] -COMFYUI_WORKFLOW_NODES = ConfigVar( - 'COMFYUI_WORKFLOW_NODES', - 'image_generation.comfyui.nodes', - comfyui_workflow_nodes, -) +COMFYUI_WORKFLOW_NODES = comfyui_workflow_nodes -IMAGES_OPENAI_API_BASE_URL = ConfigVar( - 'IMAGES_OPENAI_API_BASE_URL', - 'image_generation.openai.api_base_url', - os.getenv('IMAGES_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL), -) -IMAGES_OPENAI_API_VERSION = ConfigVar( - 'IMAGES_OPENAI_API_VERSION', - 'image_generation.openai.api_version', - os.getenv('IMAGES_OPENAI_API_VERSION', ''), -) +IMAGES_OPENAI_API_BASE_URL = os.getenv('IMAGES_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) +IMAGES_OPENAI_API_VERSION = os.getenv('IMAGES_OPENAI_API_VERSION', '') -IMAGES_OPENAI_API_KEY = ConfigVar( - 'IMAGES_OPENAI_API_KEY', - 'image_generation.openai.api_key', - os.getenv('IMAGES_OPENAI_API_KEY', OPENAI_API_KEY), -) +IMAGES_OPENAI_API_KEY = os.getenv('IMAGES_OPENAI_API_KEY', OPENAI_API_KEY) images_openai_params = os.getenv('IMAGES_OPENAI_PARAMS', '') try: @@ -2171,91 +1444,37 @@ except json.JSONDecodeError: images_openai_params = {} -IMAGES_OPENAI_API_PARAMS = ConfigVar('IMAGES_OPENAI_API_PARAMS', 'image_generation.openai.params', images_openai_params) +IMAGES_OPENAI_API_PARAMS = images_openai_params -IMAGES_GEMINI_API_BASE_URL = ConfigVar( - 'IMAGES_GEMINI_API_BASE_URL', - 'image_generation.gemini.api_base_url', - os.getenv('IMAGES_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL), -) -IMAGES_GEMINI_API_KEY = ConfigVar( - 'IMAGES_GEMINI_API_KEY', - 'image_generation.gemini.api_key', - os.getenv('IMAGES_GEMINI_API_KEY', GEMINI_API_KEY), -) +IMAGES_GEMINI_API_BASE_URL = os.getenv('IMAGES_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL) +IMAGES_GEMINI_API_KEY = os.getenv('IMAGES_GEMINI_API_KEY', GEMINI_API_KEY) -IMAGES_GEMINI_ENDPOINT_METHOD = ConfigVar( - 'IMAGES_GEMINI_ENDPOINT_METHOD', - 'image_generation.gemini.endpoint_method', - os.getenv('IMAGES_GEMINI_ENDPOINT_METHOD', ''), -) +IMAGES_GEMINI_ENDPOINT_METHOD = os.getenv('IMAGES_GEMINI_ENDPOINT_METHOD', '') -ENABLE_IMAGE_EDIT = ConfigVar( - 'ENABLE_IMAGE_EDIT', - 'images.edit.enable', - os.getenv('ENABLE_IMAGE_EDIT', '').lower() == 'true', -) +ENABLE_IMAGE_EDIT = os.getenv('ENABLE_IMAGE_EDIT', '').lower() == 'true' -IMAGE_EDIT_ENGINE = ConfigVar( - 'IMAGE_EDIT_ENGINE', - 'images.edit.engine', - os.getenv('IMAGE_EDIT_ENGINE', 'openai'), -) +IMAGE_EDIT_ENGINE = os.getenv('IMAGE_EDIT_ENGINE', 'openai') -IMAGE_EDIT_MODEL = ConfigVar( - 'IMAGE_EDIT_MODEL', - 'images.edit.model', - os.getenv('IMAGE_EDIT_MODEL', ''), -) +IMAGE_EDIT_MODEL = os.getenv('IMAGE_EDIT_MODEL', '') -IMAGE_EDIT_SIZE = ConfigVar('IMAGE_EDIT_SIZE', 'images.edit.size', os.getenv('IMAGE_EDIT_SIZE', '')) +IMAGE_EDIT_SIZE = os.getenv('IMAGE_EDIT_SIZE', '') -IMAGES_EDIT_OPENAI_API_BASE_URL = ConfigVar( - 'IMAGES_EDIT_OPENAI_API_BASE_URL', - 'images.edit.openai.api_base_url', - os.getenv('IMAGES_EDIT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL), -) -IMAGES_EDIT_OPENAI_API_VERSION = ConfigVar( - 'IMAGES_EDIT_OPENAI_API_VERSION', - 'images.edit.openai.api_version', - os.getenv('IMAGES_EDIT_OPENAI_API_VERSION', ''), -) +ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION = os.getenv('ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION', 'true').lower() == 'true' -IMAGES_EDIT_OPENAI_API_KEY = ConfigVar( - 'IMAGES_EDIT_OPENAI_API_KEY', - 'images.edit.openai.api_key', - os.getenv('IMAGES_EDIT_OPENAI_API_KEY', OPENAI_API_KEY), -) +IMAGES_EDIT_OPENAI_API_BASE_URL = os.getenv('IMAGES_EDIT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) +IMAGES_EDIT_OPENAI_API_VERSION = os.getenv('IMAGES_EDIT_OPENAI_API_VERSION', '') -IMAGES_EDIT_GEMINI_API_BASE_URL = ConfigVar( - 'IMAGES_EDIT_GEMINI_API_BASE_URL', - 'images.edit.gemini.api_base_url', - os.getenv('IMAGES_EDIT_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL), -) -IMAGES_EDIT_GEMINI_API_KEY = ConfigVar( - 'IMAGES_EDIT_GEMINI_API_KEY', - 'images.edit.gemini.api_key', - os.getenv('IMAGES_EDIT_GEMINI_API_KEY', GEMINI_API_KEY), -) +IMAGES_EDIT_OPENAI_API_KEY = os.getenv('IMAGES_EDIT_OPENAI_API_KEY', OPENAI_API_KEY) + +IMAGES_EDIT_GEMINI_API_BASE_URL = os.getenv('IMAGES_EDIT_GEMINI_API_BASE_URL', GEMINI_API_BASE_URL) +IMAGES_EDIT_GEMINI_API_KEY = os.getenv('IMAGES_EDIT_GEMINI_API_KEY', GEMINI_API_KEY) -IMAGES_EDIT_COMFYUI_BASE_URL = ConfigVar( - 'IMAGES_EDIT_COMFYUI_BASE_URL', - 'images.edit.comfyui.base_url', - os.getenv('IMAGES_EDIT_COMFYUI_BASE_URL', ''), -) -IMAGES_EDIT_COMFYUI_API_KEY = ConfigVar( - 'IMAGES_EDIT_COMFYUI_API_KEY', - 'images.edit.comfyui.api_key', - os.getenv('IMAGES_EDIT_COMFYUI_API_KEY', ''), -) +IMAGES_EDIT_COMFYUI_BASE_URL = os.getenv('IMAGES_EDIT_COMFYUI_BASE_URL', '') +IMAGES_EDIT_COMFYUI_API_KEY = os.getenv('IMAGES_EDIT_COMFYUI_API_KEY', '') -IMAGES_EDIT_COMFYUI_WORKFLOW = ConfigVar( - 'IMAGES_EDIT_COMFYUI_WORKFLOW', - 'images.edit.comfyui.workflow', - os.getenv('IMAGES_EDIT_COMFYUI_WORKFLOW', ''), -) +IMAGES_EDIT_COMFYUI_WORKFLOW = os.getenv('IMAGES_EDIT_COMFYUI_WORKFLOW', '') images_edit_comfyui_workflow_nodes = os.getenv('IMAGES_EDIT_COMFYUI_WORKFLOW_NODES', '') try: @@ -2263,22 +1482,14 @@ try: except json.JSONDecodeError: images_edit_comfyui_workflow_nodes = [] -IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = ConfigVar( - 'IMAGES_EDIT_COMFYUI_WORKFLOW_NODES', - 'images.edit.comfyui.nodes', - images_edit_comfyui_workflow_nodes, -) +IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = images_edit_comfyui_workflow_nodes #################################### # Audio #################################### # Transcription -WHISPER_MODEL = ConfigVar( - 'WHISPER_MODEL', - 'audio.stt.whisper_model', - os.getenv('WHISPER_MODEL', 'base'), -) +WHISPER_MODEL = os.getenv('WHISPER_MODEL', 'base') WHISPER_COMPUTE_TYPE = os.getenv('WHISPER_COMPUTE_TYPE', 'int8') WHISPER_MODEL_DIR = os.getenv('WHISPER_MODEL_DIR', f'{CACHE_DIR}/whisper/models') @@ -2291,120 +1502,52 @@ WHISPER_MULTILINGUAL = os.getenv('WHISPER_MULTILINGUAL', 'False').lower() == 'tr WHISPER_LANGUAGE = os.getenv('WHISPER_LANGUAGE', '').lower() or None # Add Deepgram configuration -DEEPGRAM_API_KEY = ConfigVar( - 'DEEPGRAM_API_KEY', - 'audio.stt.deepgram.api_key', - os.getenv('DEEPGRAM_API_KEY', ''), -) +DEEPGRAM_API_KEY = os.getenv('DEEPGRAM_API_KEY', '') # ElevenLabs configuration ELEVENLABS_API_BASE_URL = os.getenv('ELEVENLABS_API_BASE_URL', 'https://api.elevenlabs.io') -AUDIO_STT_OPENAI_API_BASE_URL = ConfigVar( - 'AUDIO_STT_OPENAI_API_BASE_URL', - 'audio.stt.openai.api_base_url', - os.getenv('AUDIO_STT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL), -) +AUDIO_STT_OPENAI_API_BASE_URL = os.getenv('AUDIO_STT_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) -AUDIO_STT_OPENAI_API_KEY = ConfigVar( - 'AUDIO_STT_OPENAI_API_KEY', - 'audio.stt.openai.api_key', - os.getenv('AUDIO_STT_OPENAI_API_KEY', OPENAI_API_KEY), -) +AUDIO_STT_OPENAI_API_KEY = os.getenv('AUDIO_STT_OPENAI_API_KEY', OPENAI_API_KEY) -AUDIO_STT_ENGINE = ConfigVar( - 'AUDIO_STT_ENGINE', - 'audio.stt.engine', - os.getenv('AUDIO_STT_ENGINE', ''), -) +AUDIO_STT_ENGINE = os.getenv('AUDIO_STT_ENGINE', '') -AUDIO_STT_MODEL = ConfigVar( - 'AUDIO_STT_MODEL', - 'audio.stt.model', - os.getenv('AUDIO_STT_MODEL', ''), -) +AUDIO_STT_MODEL = os.getenv('AUDIO_STT_MODEL', '') -AUDIO_STT_SUPPORTED_CONTENT_TYPES = ConfigVar( - 'AUDIO_STT_SUPPORTED_CONTENT_TYPES', - 'audio.stt.supported_content_types', - [ - content_type.strip() - for content_type in os.getenv('AUDIO_STT_SUPPORTED_CONTENT_TYPES', '').split(',') - if content_type.strip() - ], -) +AUDIO_STT_SUPPORTED_CONTENT_TYPES = [ + content_type.strip() + for content_type in os.getenv('AUDIO_STT_SUPPORTED_CONTENT_TYPES', '').split(',') + if content_type.strip() +] -AUDIO_STT_ALLOWED_EXTENSIONS = ConfigVar( - 'AUDIO_STT_ALLOWED_EXTENSIONS', - 'audio.stt.allowed_extensions', - [ - ext.strip() - for ext in os.getenv( - 'AUDIO_STT_ALLOWED_EXTENSIONS', - 'mp3,wav,m4a,webm,ogg,flac,mp4,mpga,mpeg', - ).split(',') - if ext.strip() - ], -) +AUDIO_STT_ALLOWED_EXTENSIONS = [ + ext.strip() + for ext in os.getenv( + 'AUDIO_STT_ALLOWED_EXTENSIONS', + 'mp3,wav,m4a,webm,ogg,flac,mp4,mpga,mpeg', + ).split(',') + if ext.strip() +] -AUDIO_STT_AZURE_API_KEY = ConfigVar( - 'AUDIO_STT_AZURE_API_KEY', - 'audio.stt.azure.api_key', - os.getenv('AUDIO_STT_AZURE_API_KEY', ''), -) +AUDIO_STT_AZURE_API_KEY = os.getenv('AUDIO_STT_AZURE_API_KEY', '') -AUDIO_STT_AZURE_REGION = ConfigVar( - 'AUDIO_STT_AZURE_REGION', - 'audio.stt.azure.region', - os.getenv('AUDIO_STT_AZURE_REGION', ''), -) +AUDIO_STT_AZURE_REGION = os.getenv('AUDIO_STT_AZURE_REGION', '') -AUDIO_STT_AZURE_LOCALES = ConfigVar( - 'AUDIO_STT_AZURE_LOCALES', - 'audio.stt.azure.locales', - os.getenv('AUDIO_STT_AZURE_LOCALES', ''), -) +AUDIO_STT_AZURE_LOCALES = os.getenv('AUDIO_STT_AZURE_LOCALES', '') -AUDIO_STT_AZURE_BASE_URL = ConfigVar( - 'AUDIO_STT_AZURE_BASE_URL', - 'audio.stt.azure.base_url', - os.getenv('AUDIO_STT_AZURE_BASE_URL', ''), -) +AUDIO_STT_AZURE_BASE_URL = os.getenv('AUDIO_STT_AZURE_BASE_URL', '') -AUDIO_STT_AZURE_MAX_SPEAKERS = ConfigVar( - 'AUDIO_STT_AZURE_MAX_SPEAKERS', - 'audio.stt.azure.max_speakers', - os.getenv('AUDIO_STT_AZURE_MAX_SPEAKERS', ''), -) +AUDIO_STT_AZURE_MAX_SPEAKERS = os.getenv('AUDIO_STT_AZURE_MAX_SPEAKERS', '') -AUDIO_STT_MISTRAL_API_KEY = ConfigVar( - 'AUDIO_STT_MISTRAL_API_KEY', - 'audio.stt.mistral.api_key', - os.getenv('AUDIO_STT_MISTRAL_API_KEY', ''), -) +AUDIO_STT_MISTRAL_API_KEY = os.getenv('AUDIO_STT_MISTRAL_API_KEY', '') -AUDIO_STT_MISTRAL_API_BASE_URL = ConfigVar( - 'AUDIO_STT_MISTRAL_API_BASE_URL', - 'audio.stt.mistral.api_base_url', - os.getenv('AUDIO_STT_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1'), -) +AUDIO_STT_MISTRAL_API_BASE_URL = os.getenv('AUDIO_STT_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1') -AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = ConfigVar( - 'AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS', - 'audio.stt.mistral.use_chat_completions', - os.getenv('AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS', 'false').lower() == 'true', -) +AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = os.getenv('AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS', 'false').lower() == 'true' -AUDIO_TTS_OPENAI_API_BASE_URL = ConfigVar( - 'AUDIO_TTS_OPENAI_API_BASE_URL', - 'audio.tts.openai.api_base_url', - os.getenv('AUDIO_TTS_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL), -) -AUDIO_TTS_OPENAI_API_KEY = ConfigVar( - 'AUDIO_TTS_OPENAI_API_KEY', - 'audio.tts.openai.api_key', - os.getenv('AUDIO_TTS_OPENAI_API_KEY', OPENAI_API_KEY), -) +AUDIO_TTS_OPENAI_API_BASE_URL = os.getenv('AUDIO_TTS_OPENAI_API_BASE_URL', OPENAI_API_BASE_URL) +AUDIO_TTS_OPENAI_API_KEY = os.getenv('AUDIO_TTS_OPENAI_API_KEY', OPENAI_API_KEY) audio_tts_openai_params = os.getenv('AUDIO_TTS_OPENAI_PARAMS', '') try: @@ -2412,115 +1555,53 @@ try: except json.JSONDecodeError: audio_tts_openai_params = {} -AUDIO_TTS_OPENAI_PARAMS = ConfigVar( - 'AUDIO_TTS_OPENAI_PARAMS', - 'audio.tts.openai.params', - audio_tts_openai_params, +AUDIO_TTS_OPENAI_PARAMS = audio_tts_openai_params + + +AUDIO_TTS_API_KEY = os.getenv('AUDIO_TTS_API_KEY', '') + +AUDIO_TTS_ENGINE = os.getenv('AUDIO_TTS_ENGINE', '') + + +AUDIO_TTS_MODEL = os.getenv('AUDIO_TTS_MODEL', 'tts-1') + +AUDIO_TTS_VOICE = os.getenv('AUDIO_TTS_VOICE', 'alloy') + +AUDIO_TTS_SPLIT_ON = os.getenv('AUDIO_TTS_SPLIT_ON', 'punctuation') + +AUDIO_TTS_AZURE_SPEECH_REGION = os.getenv('AUDIO_TTS_AZURE_SPEECH_REGION', '') + +AUDIO_TTS_AZURE_SPEECH_BASE_URL = os.getenv('AUDIO_TTS_AZURE_SPEECH_BASE_URL', '') + +AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT = os.getenv( + 'AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT', 'audio-24khz-160kbitrate-mono-mp3' ) +AUDIO_TTS_MISTRAL_API_KEY = os.getenv('AUDIO_TTS_MISTRAL_API_KEY', '') -AUDIO_TTS_API_KEY = ConfigVar( - 'AUDIO_TTS_API_KEY', - 'audio.tts.api_key', - os.getenv('AUDIO_TTS_API_KEY', ''), -) - -AUDIO_TTS_ENGINE = ConfigVar( - 'AUDIO_TTS_ENGINE', - 'audio.tts.engine', - os.getenv('AUDIO_TTS_ENGINE', ''), -) - - -AUDIO_TTS_MODEL = ConfigVar( - 'AUDIO_TTS_MODEL', - 'audio.tts.model', - os.getenv('AUDIO_TTS_MODEL', 'tts-1'), # OpenAI default model -) - -AUDIO_TTS_VOICE = ConfigVar( - 'AUDIO_TTS_VOICE', - 'audio.tts.voice', - os.getenv('AUDIO_TTS_VOICE', 'alloy'), # OpenAI default voice -) - -AUDIO_TTS_SPLIT_ON = ConfigVar( - 'AUDIO_TTS_SPLIT_ON', - 'audio.tts.split_on', - os.getenv('AUDIO_TTS_SPLIT_ON', 'punctuation'), -) - -AUDIO_TTS_AZURE_SPEECH_REGION = ConfigVar( - 'AUDIO_TTS_AZURE_SPEECH_REGION', - 'audio.tts.azure.speech_region', - os.getenv('AUDIO_TTS_AZURE_SPEECH_REGION', ''), -) - -AUDIO_TTS_AZURE_SPEECH_BASE_URL = ConfigVar( - 'AUDIO_TTS_AZURE_SPEECH_BASE_URL', - 'audio.tts.azure.speech_base_url', - os.getenv('AUDIO_TTS_AZURE_SPEECH_BASE_URL', ''), -) - -AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT = ConfigVar( - 'AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT', - 'audio.tts.azure.speech_output_format', - os.getenv('AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT', 'audio-24khz-160kbitrate-mono-mp3'), -) - -AUDIO_TTS_MISTRAL_API_KEY = ConfigVar( - 'AUDIO_TTS_MISTRAL_API_KEY', - 'audio.tts.mistral.api_key', - os.getenv('AUDIO_TTS_MISTRAL_API_KEY', ''), -) - -AUDIO_TTS_MISTRAL_API_BASE_URL = ConfigVar( - 'AUDIO_TTS_MISTRAL_API_BASE_URL', - 'audio.tts.mistral.api_base_url', - os.getenv('AUDIO_TTS_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1'), -) +AUDIO_TTS_MISTRAL_API_BASE_URL = os.getenv('AUDIO_TTS_MISTRAL_API_BASE_URL', 'https://api.mistral.ai/v1') #################################### # WEBUI #################################### -WEBUI_URL = ConfigVar('WEBUI_URL', 'webui.url', os.getenv('WEBUI_URL', '')) +WEBUI_URL = os.getenv('WEBUI_URL', '') -ENABLE_SIGNUP = ConfigVar( - 'ENABLE_SIGNUP', - 'ui.enable_signup', - (False if not WEBUI_AUTH else os.getenv('ENABLE_SIGNUP', 'True').lower() == 'true'), -) +ENABLE_SIGNUP = False if not WEBUI_AUTH else os.getenv('ENABLE_SIGNUP', 'True').lower() == 'true' -ENABLE_LOGIN_FORM = ConfigVar( - 'ENABLE_LOGIN_FORM', - 'ui.enable_login_form', - os.getenv('ENABLE_LOGIN_FORM', 'True').lower() == 'true', -) +ENABLE_LOGIN_FORM = os.getenv('ENABLE_LOGIN_FORM', 'True').lower() == 'true' -ENABLE_PASSWORD_CHANGE_FORM = ConfigVar( - 'ENABLE_PASSWORD_CHANGE_FORM', - 'ui.enable_password_change_form', - os.getenv('ENABLE_PASSWORD_CHANGE_FORM', 'True').lower() == 'true', -) +ENABLE_PASSWORD_CHANGE_FORM = os.getenv('ENABLE_PASSWORD_CHANGE_FORM', 'True').lower() == 'true' ENABLE_PASSWORD_AUTH = os.getenv('ENABLE_PASSWORD_AUTH', 'True').lower() == 'true' -DEFAULT_LOCALE = ConfigVar( - 'DEFAULT_LOCALE', - 'ui.default_locale', - os.getenv('DEFAULT_LOCALE', ''), -) +DEFAULT_LOCALE = os.getenv('DEFAULT_LOCALE', '') -DEFAULT_MODELS = ConfigVar('DEFAULT_MODELS', 'ui.default_models', os.getenv('DEFAULT_MODELS', None)) +DEFAULT_MODELS = os.getenv('DEFAULT_MODELS', None) -DEFAULT_PINNED_MODELS = ConfigVar( - 'DEFAULT_PINNED_MODELS', - 'ui.default_pinned_models', - os.getenv('DEFAULT_PINNED_MODELS', None), -) +DEFAULT_PINNED_MODELS = os.getenv('DEFAULT_PINNED_MODELS', None) try: default_prompt_suggestions = json.loads(os.getenv('DEFAULT_PROMPT_SUGGESTIONS', '[]')) @@ -2558,17 +1639,9 @@ if default_prompt_suggestions == []: }, ] -DEFAULT_PROMPT_SUGGESTIONS = ConfigVar( - 'DEFAULT_PROMPT_SUGGESTIONS', - 'ui.prompt_suggestions', - default_prompt_suggestions, -) +DEFAULT_PROMPT_SUGGESTIONS = default_prompt_suggestions -MODEL_ORDER_LIST = ConfigVar( - 'MODEL_ORDER_LIST', - 'ui.model_order_list', - [], -) +MODEL_ORDER_LIST = [] try: default_model_metadata = json.loads(os.getenv('DEFAULT_MODEL_METADATA', '{}')) @@ -2576,11 +1649,7 @@ except Exception as e: log.exception(f'Error loading DEFAULT_MODEL_METADATA: {e}') default_model_metadata = {} -DEFAULT_MODEL_METADATA = ConfigVar( - 'DEFAULT_MODEL_METADATA', - 'models.default_metadata', - default_model_metadata, -) +DEFAULT_MODEL_METADATA = default_model_metadata try: default_model_params = json.loads(os.getenv('DEFAULT_MODEL_PARAMS', '{}')) @@ -2588,42 +1657,18 @@ except Exception as e: log.exception(f'Error loading DEFAULT_MODEL_PARAMS: {e}') default_model_params = {} -DEFAULT_MODEL_PARAMS = ConfigVar( - 'DEFAULT_MODEL_PARAMS', - 'models.default_params', - default_model_params, -) +DEFAULT_MODEL_PARAMS = default_model_params -DEFAULT_USER_ROLE = ConfigVar( - 'DEFAULT_USER_ROLE', - 'ui.default_user_role', - os.getenv('DEFAULT_USER_ROLE', 'pending'), -) +DEFAULT_USER_ROLE = os.getenv('DEFAULT_USER_ROLE', 'pending') -DEFAULT_GROUP_ID = ConfigVar( - 'DEFAULT_GROUP_ID', - 'ui.default_group_id', - os.getenv('DEFAULT_GROUP_ID', ''), -) +DEFAULT_GROUP_ID = os.getenv('DEFAULT_GROUP_ID', '') -PENDING_USER_OVERLAY_TITLE = ConfigVar( - 'PENDING_USER_OVERLAY_TITLE', - 'ui.pending_user_overlay_title', - os.getenv('PENDING_USER_OVERLAY_TITLE', ''), -) +PENDING_USER_OVERLAY_TITLE = os.getenv('PENDING_USER_OVERLAY_TITLE', '') -PENDING_USER_OVERLAY_CONTENT = ConfigVar( - 'PENDING_USER_OVERLAY_CONTENT', - 'ui.pending_user_overlay_content', - os.getenv('PENDING_USER_OVERLAY_CONTENT', ''), -) +PENDING_USER_OVERLAY_CONTENT = os.getenv('PENDING_USER_OVERLAY_CONTENT', '') -RESPONSE_WATERMARK = ConfigVar( - 'RESPONSE_WATERMARK', - 'ui.watermark', - os.getenv('RESPONSE_WATERMARK', ''), -) +RESPONSE_WATERMARK = os.getenv('RESPONSE_WATERMARK', '') IFRAME_CSP = os.getenv('IFRAME_CSP', '') @@ -2671,6 +1716,14 @@ USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT = ( os.getenv('USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT', 'False').lower() == 'true' ) +USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT = ( + os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT', 'False').lower() == 'true' +) + +USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT = ( + os.getenv('USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT', 'False').lower() == 'true' +) + USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING = ( os.getenv('USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING', 'False').lower() == 'true' @@ -2720,6 +1773,9 @@ USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING = ( os.getenv('USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' ) +USER_PERMISSIONS_FOLDERS_ALLOW_SHARING = os.getenv('USER_PERMISSIONS_FOLDERS_ALLOW_SHARING', 'False').lower() == 'true' + + USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING = ( os.getenv('USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING', 'False').lower() == 'true' ) @@ -2763,6 +1819,8 @@ USER_PERMISSIONS_CHAT_ALLOW_PUBLIC_SHARING = ( USER_PERMISSIONS_CHAT_EXPORT = os.getenv('USER_PERMISSIONS_CHAT_EXPORT', 'True').lower() == 'true' +USER_PERMISSIONS_CHAT_IMPORT = os.getenv('USER_PERMISSIONS_CHAT_IMPORT', 'True').lower() == 'true' + USER_PERMISSIONS_CHAT_STT = os.getenv('USER_PERMISSIONS_CHAT_STT', 'True').lower() == 'true' USER_PERMISSIONS_CHAT_TTS = os.getenv('USER_PERMISSIONS_CHAT_TTS', 'True').lower() == 'true' @@ -2806,6 +1864,10 @@ USER_PERMISSIONS_FEATURES_AUTOMATIONS = os.getenv('USER_PERMISSIONS_FEATURES_AUT USER_PERMISSIONS_FEATURES_CALENDAR = os.getenv('USER_PERMISSIONS_FEATURES_CALENDAR', 'True').lower() == 'true' +USER_PERMISSIONS_FEATURES_USER_WEBHOOKS = ( + os.getenv('USER_PERMISSIONS_FEATURES_USER_WEBHOOKS', 'False').lower() == 'true' +) + USER_PERMISSIONS_SETTINGS_INTERFACE = os.getenv('USER_PERMISSIONS_SETTINGS_INTERFACE', 'True').lower() == 'true' @@ -2823,6 +1885,8 @@ DEFAULT_USER_PERMISSIONS = { 'prompts_export': USER_PERMISSIONS_WORKSPACE_PROMPTS_EXPORT, 'tools_import': USER_PERMISSIONS_WORKSPACE_TOOLS_IMPORT, 'tools_export': USER_PERMISSIONS_WORKSPACE_TOOLS_EXPORT, + 'skills_import': USER_PERMISSIONS_WORKSPACE_SKILLS_IMPORT, + 'skills_export': USER_PERMISSIONS_WORKSPACE_SKILLS_EXPORT, }, 'sharing': { 'models': USER_PERMISSIONS_WORKSPACE_MODELS_ALLOW_SHARING, @@ -2837,6 +1901,7 @@ DEFAULT_USER_PERMISSIONS = { 'public_skills': USER_PERMISSIONS_WORKSPACE_SKILLS_ALLOW_PUBLIC_SHARING, 'notes': USER_PERMISSIONS_NOTES_ALLOW_SHARING, 'public_notes': USER_PERMISSIONS_NOTES_ALLOW_PUBLIC_SHARING, + 'folders': USER_PERMISSIONS_FOLDERS_ALLOW_SHARING, 'public_chats': USER_PERMISSIONS_CHAT_ALLOW_PUBLIC_SHARING, 'public_calendars': USER_PERMISSIONS_CALENDAR_ALLOW_PUBLIC_SHARING, }, @@ -2858,6 +1923,7 @@ DEFAULT_USER_PERMISSIONS = { 'edit': USER_PERMISSIONS_CHAT_EDIT, 'share': USER_PERMISSIONS_CHAT_SHARE, 'export': USER_PERMISSIONS_CHAT_EXPORT, + 'import': USER_PERMISSIONS_CHAT_IMPORT, 'stt': USER_PERMISSIONS_CHAT_STT, 'tts': USER_PERMISSIONS_CHAT_TTS, 'call': USER_PERMISSIONS_CHAT_CALL, @@ -2879,82 +1945,47 @@ DEFAULT_USER_PERMISSIONS = { 'memories': USER_PERMISSIONS_FEATURES_MEMORIES, 'automations': USER_PERMISSIONS_FEATURES_AUTOMATIONS, 'calendar': USER_PERMISSIONS_FEATURES_CALENDAR, + 'webhooks': USER_PERMISSIONS_FEATURES_USER_WEBHOOKS, }, 'settings': { 'interface': USER_PERMISSIONS_SETTINGS_INTERFACE, }, } -USER_PERMISSIONS = ConfigVar( - 'USER_PERMISSIONS', - 'user.permissions', - DEFAULT_USER_PERMISSIONS, -) +USER_PERMISSIONS = DEFAULT_USER_PERMISSIONS -ENABLE_FOLDERS = ConfigVar( - 'ENABLE_FOLDERS', - 'folders.enable', - os.getenv('ENABLE_FOLDERS', 'True').lower() == 'true', -) +ENABLE_FOLDERS = os.getenv('ENABLE_FOLDERS', 'True').lower() == 'true' -FOLDER_MAX_FILE_COUNT = ConfigVar( - 'FOLDER_MAX_FILE_COUNT', - 'folders.max_file_count', - os.getenv('FOLDER_MAX_FILE_COUNT', ''), -) +FOLDER_MAX_FILE_COUNT = os.getenv('FOLDER_MAX_FILE_COUNT', '') -ENABLE_CHANNELS = ConfigVar( - 'ENABLE_CHANNELS', - 'channels.enable', - os.getenv('ENABLE_CHANNELS', 'False').lower() == 'true', -) +ENABLE_CHANNELS = os.getenv('ENABLE_CHANNELS', 'False').lower() == 'true' -ENABLE_CALENDAR = ConfigVar( - 'ENABLE_CALENDAR', - 'calendar.enable', - os.getenv('ENABLE_CALENDAR', 'True').lower() == 'true', -) +ENABLE_CALENDAR = os.getenv('ENABLE_CALENDAR', 'True').lower() == 'true' -ENABLE_AUTOMATIONS = ConfigVar( - 'ENABLE_AUTOMATIONS', - 'automations.enable', - os.getenv('ENABLE_AUTOMATIONS', 'True').lower() == 'true', -) +ENABLE_AUTOMATIONS = os.getenv('ENABLE_AUTOMATIONS', 'True').lower() == 'true' -AUTOMATION_MAX_COUNT = ConfigVar( - 'AUTOMATION_MAX_COUNT', - 'automations.max_count', - os.getenv('AUTOMATION_MAX_COUNT', ''), -) +AUTOMATION_MAX_COUNT = os.getenv('AUTOMATION_MAX_COUNT', '') -AUTOMATION_MIN_INTERVAL = ConfigVar( - 'AUTOMATION_MIN_INTERVAL', - 'automations.min_interval', - os.getenv('AUTOMATION_MIN_INTERVAL', ''), -) +AUTOMATION_MIN_INTERVAL = os.getenv('AUTOMATION_MIN_INTERVAL', '') -ENABLE_NOTES = ConfigVar( - 'ENABLE_NOTES', - 'notes.enable', - os.getenv('ENABLE_NOTES', 'True').lower() == 'true', -) +AUTOMATION_AUTH_TOKEN_EXPIRES_IN = os.getenv('AUTOMATION_AUTH_TOKEN_EXPIRES_IN', '1h') -ENABLE_USER_STATUS = ConfigVar( - 'ENABLE_USER_STATUS', - 'users.enable_status', - os.getenv('ENABLE_USER_STATUS', 'True').lower() == 'true', -) +ENABLE_NOTES = os.getenv('ENABLE_NOTES', 'True').lower() == 'true' -ENABLE_EVALUATION_ARENA_MODELS = ConfigVar( - 'ENABLE_EVALUATION_ARENA_MODELS', - 'evaluation.arena.enable', - os.getenv('ENABLE_EVALUATION_ARENA_MODELS', 'True').lower() == 'true', -) -EVALUATION_ARENA_MODELS = ConfigVar( - 'EVALUATION_ARENA_MODELS', - 'evaluation.arena.models', - [], -) +ENABLE_USER_STATUS = os.getenv('ENABLE_USER_STATUS', 'True').lower() == 'true' + +ENABLE_EVALUATION_ARENA_MODELS = os.getenv('ENABLE_EVALUATION_ARENA_MODELS', 'True').lower() == 'true' +try: + evaluation_arena_models = json.loads(os.getenv('EVALUATION_ARENA_MODELS', '[]')) + if not isinstance(evaluation_arena_models, list) or not all( + isinstance(model, dict) for model in evaluation_arena_models + ): + raise ValueError('EVALUATION_ARENA_MODELS must be a JSON list of objects') +except Exception as e: + log.exception(f'Error loading EVALUATION_ARENA_MODELS: {e}') + evaluation_arena_models = [] + +EVALUATION_ARENA_MODELS = evaluation_arena_models DEFAULT_ARENA_MODEL = { 'id': 'arena-model', @@ -2966,7 +1997,7 @@ DEFAULT_ARENA_MODEL = { }, } -WEBHOOK_URL = ConfigVar('WEBHOOK_URL', 'webhook_url', os.getenv('WEBHOOK_URL', '')) +WEBHOOK_URL = os.getenv('WEBHOOK_URL', '') ENABLE_ADMIN_EXPORT = os.getenv('ENABLE_ADMIN_EXPORT', 'True').lower() == 'true' @@ -2984,23 +2015,11 @@ ENABLE_ADMIN_CHAT_ACCESS = os.getenv('ENABLE_ADMIN_CHAT_ACCESS', 'True').lower() ENABLE_ADMIN_ANALYTICS = os.getenv('ENABLE_ADMIN_ANALYTICS', 'True').lower() == 'true' -ENABLE_COMMUNITY_SHARING = ConfigVar( - 'ENABLE_COMMUNITY_SHARING', - 'ui.enable_community_sharing', - os.getenv('ENABLE_COMMUNITY_SHARING', 'True').lower() == 'true', -) +ENABLE_COMMUNITY_SHARING = os.getenv('ENABLE_COMMUNITY_SHARING', 'True').lower() == 'true' -ENABLE_MESSAGE_RATING = ConfigVar( - 'ENABLE_MESSAGE_RATING', - 'ui.enable_message_rating', - os.getenv('ENABLE_MESSAGE_RATING', 'True').lower() == 'true', -) +ENABLE_MESSAGE_RATING = os.getenv('ENABLE_MESSAGE_RATING', 'True').lower() == 'true' -ENABLE_USER_WEBHOOKS = ConfigVar( - 'ENABLE_USER_WEBHOOKS', - 'ui.enable_user_webhooks', - os.getenv('ENABLE_USER_WEBHOOKS', 'False').lower() == 'true', -) +ENABLE_USER_WEBHOOKS = os.getenv('ENABLE_USER_WEBHOOKS', 'False').lower() == 'true' # FastAPI / AnyIO settings THREAD_POOL_SIZE = os.getenv('THREAD_POOL_SIZE', None) @@ -3065,20 +2084,12 @@ except Exception as e: log.exception(f'Error loading WEBUI_BANNERS: {e}') banners = [] -WEBUI_BANNERS = ConfigVar('WEBUI_BANNERS', 'ui.banners', banners) +WEBUI_BANNERS = banners -SHOW_ADMIN_DETAILS = ConfigVar( - 'SHOW_ADMIN_DETAILS', - 'auth.admin.show', - os.getenv('SHOW_ADMIN_DETAILS', 'true').lower() == 'true', -) +SHOW_ADMIN_DETAILS = os.getenv('SHOW_ADMIN_DETAILS', 'true').lower() == 'true' -ADMIN_EMAIL = ConfigVar( - 'ADMIN_EMAIL', - 'auth.admin.email', - os.getenv('ADMIN_EMAIL', None), -) +ADMIN_EMAIL = os.getenv('ADMIN_EMAIL', None) #################################### @@ -3086,23 +2097,17 @@ ADMIN_EMAIL = ConfigVar( #################################### -TASK_MODEL = ConfigVar( - 'TASK_MODEL', - 'task.model.default', - os.getenv('TASK_MODEL', ''), -) +TASK_MODEL = os.getenv('TASK_MODEL', '') -TASK_MODEL_EXTERNAL = ConfigVar( - 'TASK_MODEL_EXTERNAL', - 'task.model.external', - os.getenv('TASK_MODEL_EXTERNAL', ''), -) +TASK_MODEL_EXTERNAL = os.getenv('TASK_MODEL_EXTERNAL', '') -TITLE_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'TITLE_GENERATION_PROMPT_TEMPLATE', - 'task.title.prompt_template', - os.getenv('TITLE_GENERATION_PROMPT_TEMPLATE', ''), -) +ENABLE_CONTEXT_COMPACTION = os.getenv('ENABLE_CONTEXT_COMPACTION', 'False').lower() == 'true' + +CONTEXT_COMPACTION_TOKEN_THRESHOLD = int(os.getenv('CONTEXT_COMPACTION_TOKEN_THRESHOLD', '80000')) + +CONTEXT_COMPACTION_PROMPT_TEMPLATE = os.getenv('CONTEXT_COMPACTION_PROMPT_TEMPLATE', '') + +TITLE_GENERATION_PROMPT_TEMPLATE = os.getenv('TITLE_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE = """### Task: Generate a concise, 3-5 word title with an emoji summarizing the chat history. @@ -3128,11 +2133,7 @@ JSON format: { "title": "your concise title here" } {{MESSAGES:END:2}} """ -TAGS_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'TAGS_GENERATION_PROMPT_TEMPLATE', - 'task.tags.prompt_template', - os.getenv('TAGS_GENERATION_PROMPT_TEMPLATE', ''), -) +TAGS_GENERATION_PROMPT_TEMPLATE = os.getenv('TAGS_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE = """### Task: Generate 1-3 broad tags categorizing the main themes of the chat history, along with 1-3 more specific subtopic tags. @@ -3152,11 +2153,7 @@ JSON format: { "tags": ["tag1", "tag2", "tag3"] } {{MESSAGES:END:6}} """ -IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE', - 'task.image.prompt_template', - os.getenv('IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE', ''), -) +IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = os.getenv('IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = """### Task: Generate a detailed prompt for am image generation task based on the given language and context. Describe the image as if you were explaining it to someone who cannot see it. Include relevant details, colors, shapes, and any other important elements. @@ -3179,11 +2176,7 @@ Strictly return in JSON format: """ -FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'FOLLOW_UP_GENERATION_PROMPT_TEMPLATE', - 'task.follow_up.prompt_template', - os.getenv('FOLLOW_UP_GENERATION_PROMPT_TEMPLATE', ''), -) +FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = os.getenv('FOLLOW_UP_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = """### Task: Suggest 3-5 relevant follow-up questions or prompts that the user might naturally ask next in this conversation as a **user**, based on the chat history, to help continue or deepen the discussion. @@ -3201,43 +2194,19 @@ JSON format: { "follow_ups": ["Question 1?", "Question 2?", "Question 3?"] } {{MESSAGES:END:6}} """ -ENABLE_FOLLOW_UP_GENERATION = ConfigVar( - 'ENABLE_FOLLOW_UP_GENERATION', - 'task.follow_up.enable', - os.getenv('ENABLE_FOLLOW_UP_GENERATION', 'True').lower() == 'true', -) +ENABLE_FOLLOW_UP_GENERATION = os.getenv('ENABLE_FOLLOW_UP_GENERATION', 'True').lower() == 'true' -ENABLE_TAGS_GENERATION = ConfigVar( - 'ENABLE_TAGS_GENERATION', - 'task.tags.enable', - os.getenv('ENABLE_TAGS_GENERATION', 'True').lower() == 'true', -) +ENABLE_TAGS_GENERATION = os.getenv('ENABLE_TAGS_GENERATION', 'True').lower() == 'true' -ENABLE_TITLE_GENERATION = ConfigVar( - 'ENABLE_TITLE_GENERATION', - 'task.title.enable', - os.getenv('ENABLE_TITLE_GENERATION', 'True').lower() == 'true', -) +ENABLE_TITLE_GENERATION = os.getenv('ENABLE_TITLE_GENERATION', 'True').lower() == 'true' -ENABLE_SEARCH_QUERY_GENERATION = ConfigVar( - 'ENABLE_SEARCH_QUERY_GENERATION', - 'task.query.search.enable', - os.getenv('ENABLE_SEARCH_QUERY_GENERATION', 'True').lower() == 'true', -) +ENABLE_SEARCH_QUERY_GENERATION = os.getenv('ENABLE_SEARCH_QUERY_GENERATION', 'True').lower() == 'true' -ENABLE_RETRIEVAL_QUERY_GENERATION = ConfigVar( - 'ENABLE_RETRIEVAL_QUERY_GENERATION', - 'task.query.retrieval.enable', - os.getenv('ENABLE_RETRIEVAL_QUERY_GENERATION', 'True').lower() == 'true', -) +ENABLE_RETRIEVAL_QUERY_GENERATION = os.getenv('ENABLE_RETRIEVAL_QUERY_GENERATION', 'True').lower() == 'true' -QUERY_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'QUERY_GENERATION_PROMPT_TEMPLATE', - 'task.query.prompt_template', - os.getenv('QUERY_GENERATION_PROMPT_TEMPLATE', ''), -) +QUERY_GENERATION_PROMPT_TEMPLATE = os.getenv('QUERY_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE = """### Task: Analyze the chat history to determine the necessity of generating search queries, in the given language. By default, **prioritize generating 1-3 broad and relevant search queries** unless it is absolutely certain that no additional information is required. The aim is to retrieve comprehensive, updated, and valuable information even with minimal uncertainty. If no search is unequivocally needed, return an empty list. @@ -3263,23 +2232,11 @@ Strictly return in JSON format: """ -ENABLE_AUTOCOMPLETE_GENERATION = ConfigVar( - 'ENABLE_AUTOCOMPLETE_GENERATION', - 'task.autocomplete.enable', - os.getenv('ENABLE_AUTOCOMPLETE_GENERATION', 'False').lower() == 'true', -) +ENABLE_AUTOCOMPLETE_GENERATION = os.getenv('ENABLE_AUTOCOMPLETE_GENERATION', 'False').lower() == 'true' -AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = ConfigVar( - 'AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH', - 'task.autocomplete.input_max_length', - int(os.getenv('AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH', '-1')), -) +AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = int(os.getenv('AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH', '-1')) -AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = ConfigVar( - 'AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE', - 'task.autocomplete.prompt_template', - os.getenv('AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE', ''), -) +AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = os.getenv('AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE', '') DEFAULT_AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = """### Task: @@ -3325,17 +2282,9 @@ Output: """ -VOICE_MODE_PROMPT_TEMPLATE = ConfigVar( - 'VOICE_MODE_PROMPT_TEMPLATE', - 'task.voice.prompt_template', - os.getenv('VOICE_MODE_PROMPT_TEMPLATE', ''), -) +VOICE_MODE_PROMPT_TEMPLATE = os.getenv('VOICE_MODE_PROMPT_TEMPLATE', '') -ENABLE_VOICE_MODE_PROMPT = ConfigVar( - 'ENABLE_VOICE_MODE_PROMPT', - 'task.voice.prompt.enable', - os.getenv('ENABLE_VOICE_MODE_PROMPT', 'True').lower() == 'true', -) +ENABLE_VOICE_MODE_PROMPT = os.getenv('ENABLE_VOICE_MODE_PROMPT', 'True').lower() == 'true' DEFAULT_VOICE_MODE_PROMPT_TEMPLATE = """You are a friendly, concise voice assistant. @@ -3362,11 +2311,7 @@ ERROR HANDLING: Stay consistent, helpful, and easy to listen to.""" -TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = ConfigVar( - 'TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE', - 'task.tools.prompt_template', - os.getenv('TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE', ''), -) +TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = os.getenv('TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE', '') DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = """Available Tools: {{TOOLS}} @@ -3408,31 +2353,21 @@ Responses from models: {{responses}}""" # Auth #################################### -ENABLE_API_KEYS = ConfigVar( - 'ENABLE_API_KEYS', - 'auth.enable_api_keys', - os.getenv('ENABLE_API_KEYS', 'False').lower() == 'true', -) +ENABLE_API_KEYS = os.getenv('ENABLE_API_KEYS', 'False').lower() == 'true' -ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS = ConfigVar( - 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS', - 'auth.api_key.endpoint_restrictions', +ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS = ( os.getenv( 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS', os.getenv('ENABLE_API_KEY_ENDPOINT_RESTRICTIONS', 'False'), ).lower() - == 'true', + == 'true' ) -API_KEYS_ALLOWED_ENDPOINTS = ConfigVar( - 'API_KEYS_ALLOWED_ENDPOINTS', - 'auth.api_key.allowed_endpoints', - os.getenv('API_KEYS_ALLOWED_ENDPOINTS', os.getenv('API_KEY_ALLOWED_ENDPOINTS', '')), -) +API_KEYS_ALLOWED_ENDPOINTS = os.getenv('API_KEYS_ALLOWED_ENDPOINTS', os.getenv('API_KEY_ALLOWED_ENDPOINTS', '')) -JWT_EXPIRES_IN = ConfigVar('JWT_EXPIRES_IN', 'auth.jwt_expiry', os.getenv('JWT_EXPIRES_IN', '4w')) +JWT_EXPIRES_IN = os.getenv('JWT_EXPIRES_IN', '4w') -if JWT_EXPIRES_IN.value == '-1': +if JWT_EXPIRES_IN == '-1': log.warning( "⚠️ SECURITY WARNING: JWT_EXPIRES_IN is set to '-1'\n" ' See: https://docs.openwebui.com/reference/env-configuration\n' @@ -3442,57 +2377,25 @@ if JWT_EXPIRES_IN.value == '-1': # OAuth config #################################### -ENABLE_OAUTH_SIGNUP = ConfigVar( - 'ENABLE_OAUTH_SIGNUP', - 'oauth.enable_signup', - os.getenv('ENABLE_OAUTH_SIGNUP', 'False').lower() == 'true', -) +ENABLE_OAUTH_SIGNUP = os.getenv('ENABLE_OAUTH_SIGNUP', 'False').lower() == 'true' -OAUTH_AUTO_REDIRECT = ConfigVar( - 'OAUTH_AUTO_REDIRECT', - 'oauth.auto_redirect', - os.getenv('OAUTH_AUTO_REDIRECT', 'False').lower() == 'true', -) +OAUTH_AUTO_REDIRECT = os.getenv('OAUTH_AUTO_REDIRECT', 'False').lower() == 'true' -OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = ConfigVar( - 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', - 'oauth.refresh_token_include_scope', - os.getenv('OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', 'False').lower() == 'true', -) +OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = os.getenv('OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', 'False').lower() == 'true' -OAUTH_MERGE_ACCOUNTS_BY_EMAIL = ConfigVar( - 'OAUTH_MERGE_ACCOUNTS_BY_EMAIL', - 'oauth.merge_accounts_by_email', - os.getenv('OAUTH_MERGE_ACCOUNTS_BY_EMAIL', 'False').lower() == 'true', -) +OAUTH_MERGE_ACCOUNTS_BY_EMAIL = os.getenv('OAUTH_MERGE_ACCOUNTS_BY_EMAIL', 'False').lower() == 'true' OAUTH_PROVIDERS = {} -GOOGLE_CLIENT_ID = ConfigVar( - 'GOOGLE_CLIENT_ID', - 'oauth.google.client_id', - os.getenv('GOOGLE_CLIENT_ID', ''), -) +GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '') -GOOGLE_CLIENT_SECRET = ConfigVar( - 'GOOGLE_CLIENT_SECRET', - 'oauth.google.client_secret', - os.getenv('GOOGLE_CLIENT_SECRET', ''), -) +GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '') -GOOGLE_OAUTH_SCOPE = ConfigVar( - 'GOOGLE_OAUTH_SCOPE', - 'oauth.google.scope', - os.getenv('GOOGLE_OAUTH_SCOPE', 'openid email profile'), -) +GOOGLE_OAUTH_SCOPE = os.getenv('GOOGLE_OAUTH_SCOPE', 'openid email profile') -GOOGLE_REDIRECT_URI = ConfigVar( - 'GOOGLE_REDIRECT_URI', - 'oauth.google.redirect_uri', - os.getenv('GOOGLE_REDIRECT_URI', ''), -) +GOOGLE_REDIRECT_URI = os.getenv('GOOGLE_REDIRECT_URI', '') GOOGLE_OAUTH_AUTHORIZE_PARAMS = {} _google_oauth_authorize_params = os.getenv('GOOGLE_OAUTH_AUTHORIZE_PARAMS', '') @@ -3506,283 +2409,113 @@ if _google_oauth_authorize_params: except (json.JSONDecodeError, TypeError): log.warning('GOOGLE_OAUTH_AUTHORIZE_PARAMS is not valid JSON, ignoring') -MICROSOFT_CLIENT_ID = ConfigVar( - 'MICROSOFT_CLIENT_ID', - 'oauth.microsoft.client_id', - os.getenv('MICROSOFT_CLIENT_ID', ''), -) +MICROSOFT_CLIENT_ID = os.getenv('MICROSOFT_CLIENT_ID', '') -MICROSOFT_CLIENT_SECRET = ConfigVar( - 'MICROSOFT_CLIENT_SECRET', - 'oauth.microsoft.client_secret', - os.getenv('MICROSOFT_CLIENT_SECRET', ''), -) +MICROSOFT_CLIENT_SECRET = os.getenv('MICROSOFT_CLIENT_SECRET', '') -MICROSOFT_CLIENT_TENANT_ID = ConfigVar( - 'MICROSOFT_CLIENT_TENANT_ID', - 'oauth.microsoft.tenant_id', - os.getenv('MICROSOFT_CLIENT_TENANT_ID', ''), -) +MICROSOFT_CLIENT_TENANT_ID = os.getenv('MICROSOFT_CLIENT_TENANT_ID', '') -MICROSOFT_CLIENT_LOGIN_BASE_URL = ConfigVar( - 'MICROSOFT_CLIENT_LOGIN_BASE_URL', - 'oauth.microsoft.login_base_url', - os.getenv('MICROSOFT_CLIENT_LOGIN_BASE_URL', 'https://login.microsoftonline.com'), -) +MICROSOFT_CLIENT_LOGIN_BASE_URL = os.getenv('MICROSOFT_CLIENT_LOGIN_BASE_URL', 'https://login.microsoftonline.com') -MICROSOFT_CLIENT_PICTURE_URL = ConfigVar( +MICROSOFT_CLIENT_PICTURE_URL = os.getenv( 'MICROSOFT_CLIENT_PICTURE_URL', - 'oauth.microsoft.picture_url', - os.getenv( - 'MICROSOFT_CLIENT_PICTURE_URL', - 'https://graph.microsoft.com/v1.0/me/photo/$value', - ), + 'https://graph.microsoft.com/v1.0/me/photo/$value', ) -MICROSOFT_OAUTH_SCOPE = ConfigVar( - 'MICROSOFT_OAUTH_SCOPE', - 'oauth.microsoft.scope', - os.getenv('MICROSOFT_OAUTH_SCOPE', 'openid email profile'), -) +MICROSOFT_OAUTH_SCOPE = os.getenv('MICROSOFT_OAUTH_SCOPE', 'openid email profile') -MICROSOFT_REDIRECT_URI = ConfigVar( - 'MICROSOFT_REDIRECT_URI', - 'oauth.microsoft.redirect_uri', - os.getenv('MICROSOFT_REDIRECT_URI', ''), -) +MICROSOFT_REDIRECT_URI = os.getenv('MICROSOFT_REDIRECT_URI', '') -GITHUB_CLIENT_ID = ConfigVar( - 'GITHUB_CLIENT_ID', - 'oauth.github.client_id', - os.getenv('GITHUB_CLIENT_ID', ''), -) +GITHUB_CLIENT_ID = os.getenv('GITHUB_CLIENT_ID', '') -GITHUB_CLIENT_SECRET = ConfigVar( - 'GITHUB_CLIENT_SECRET', - 'oauth.github.client_secret', - os.getenv('GITHUB_CLIENT_SECRET', ''), -) +GITHUB_CLIENT_SECRET = os.getenv('GITHUB_CLIENT_SECRET', '') -GITHUB_CLIENT_SCOPE = ConfigVar( - 'GITHUB_CLIENT_SCOPE', - 'oauth.github.scope', - os.getenv('GITHUB_CLIENT_SCOPE', 'user:email'), -) +GITHUB_CLIENT_SCOPE = os.getenv('GITHUB_CLIENT_SCOPE', 'user:email') -GITHUB_CLIENT_REDIRECT_URI = ConfigVar( - 'GITHUB_CLIENT_REDIRECT_URI', - 'oauth.github.redirect_uri', - os.getenv('GITHUB_CLIENT_REDIRECT_URI', ''), -) +GITHUB_CLIENT_REDIRECT_URI = os.getenv('GITHUB_CLIENT_REDIRECT_URI', '') -OAUTH_CLIENT_ID = ConfigVar( - 'OAUTH_CLIENT_ID', - 'oauth.oidc.client_id', - os.getenv('OAUTH_CLIENT_ID', ''), -) +OAUTH_CLIENT_ID = os.getenv('OAUTH_CLIENT_ID', '') -OAUTH_CLIENT_SECRET = ConfigVar( - 'OAUTH_CLIENT_SECRET', - 'oauth.oidc.client_secret', - os.getenv('OAUTH_CLIENT_SECRET', ''), -) +OAUTH_CLIENT_SECRET = os.getenv('OAUTH_CLIENT_SECRET', '') -OPENID_PROVIDER_URL = ConfigVar( - 'OPENID_PROVIDER_URL', - 'oauth.oidc.provider_url', - os.getenv('OPENID_PROVIDER_URL', ''), -) +OPENID_PROVIDER_URL = os.getenv('OPENID_PROVIDER_URL', '') -OPENID_END_SESSION_ENDPOINT = ConfigVar( - 'OPENID_END_SESSION_ENDPOINT', - 'oauth.oidc.end_session_endpoint', - os.getenv('OPENID_END_SESSION_ENDPOINT', ''), -) +OPENID_END_SESSION_ENDPOINT = os.getenv('OPENID_END_SESSION_ENDPOINT', '') -OPENID_REDIRECT_URI = ConfigVar( - 'OPENID_REDIRECT_URI', - 'oauth.oidc.redirect_uri', - os.getenv('OPENID_REDIRECT_URI', ''), -) +OPENID_REDIRECT_URI = os.getenv('OPENID_REDIRECT_URI', '') -OAUTH_SCOPES = ConfigVar( - 'OAUTH_SCOPES', - 'oauth.oidc.scopes', - os.getenv('OAUTH_SCOPES', 'openid email profile'), -) +OAUTH_SCOPES = os.getenv('OAUTH_SCOPES', 'openid email profile') -OAUTH_TIMEOUT = ConfigVar( - 'OAUTH_TIMEOUT', - 'oauth.oidc.oauth_timeout', - os.getenv('OAUTH_TIMEOUT', ''), -) +OAUTH_TIMEOUT = os.getenv('OAUTH_TIMEOUT', '') -OAUTH_TOKEN_ENDPOINT_AUTH_METHOD = ConfigVar( - 'OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', - 'oauth.oidc.token_endpoint_auth_method', - os.getenv('OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', None), -) +OAUTH_TOKEN_ENDPOINT_AUTH_METHOD = os.getenv('OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', None) -OAUTH_CODE_CHALLENGE_METHOD = ConfigVar( - 'OAUTH_CODE_CHALLENGE_METHOD', - 'oauth.oidc.code_challenge_method', - os.getenv('OAUTH_CODE_CHALLENGE_METHOD', None), -) +OAUTH_CODE_CHALLENGE_METHOD = os.getenv('OAUTH_CODE_CHALLENGE_METHOD', None) -OAUTH_PROVIDER_NAME = ConfigVar( - 'OAUTH_PROVIDER_NAME', - 'oauth.oidc.provider_name', - os.getenv('OAUTH_PROVIDER_NAME', 'SSO'), -) +OAUTH_PROVIDER_NAME = os.getenv('OAUTH_PROVIDER_NAME', 'SSO') -OAUTH_SUB_CLAIM = ConfigVar( - 'OAUTH_SUB_CLAIM', - 'oauth.oidc.sub_claim', - os.getenv('OAUTH_SUB_CLAIM', None), -) +OAUTH_SUB_CLAIM = os.getenv('OAUTH_SUB_CLAIM', None) -OAUTH_USERNAME_CLAIM = ConfigVar( - 'OAUTH_USERNAME_CLAIM', - 'oauth.oidc.username_claim', - os.getenv('OAUTH_USERNAME_CLAIM', 'name'), -) +OAUTH_USERNAME_CLAIM = os.getenv('OAUTH_USERNAME_CLAIM', 'name') -OAUTH_PICTURE_CLAIM = ConfigVar( - 'OAUTH_PICTURE_CLAIM', - 'oauth.oidc.avatar_claim', - os.getenv('OAUTH_PICTURE_CLAIM', 'picture'), -) +OAUTH_PICTURE_CLAIM = os.getenv('OAUTH_PICTURE_CLAIM', 'picture') -OAUTH_EMAIL_CLAIM = ConfigVar( - 'OAUTH_EMAIL_CLAIM', - 'oauth.oidc.email_claim', - os.getenv('OAUTH_EMAIL_CLAIM', 'email'), -) +OAUTH_EMAIL_CLAIM = os.getenv('OAUTH_EMAIL_CLAIM', 'email') -OAUTH_GROUPS_CLAIM = ConfigVar( - 'OAUTH_GROUPS_CLAIM', - 'oauth.oidc.group_claim', - os.getenv('OAUTH_GROUPS_CLAIM', os.getenv('OAUTH_GROUP_CLAIM', 'groups')), -) +OAUTH_GROUPS_CLAIM = os.getenv('OAUTH_GROUPS_CLAIM', os.getenv('OAUTH_GROUP_CLAIM', 'groups')) -FEISHU_CLIENT_ID = ConfigVar( - 'FEISHU_CLIENT_ID', - 'oauth.feishu.client_id', - os.getenv('FEISHU_CLIENT_ID', ''), -) +FEISHU_CLIENT_ID = os.getenv('FEISHU_CLIENT_ID', '') -FEISHU_CLIENT_SECRET = ConfigVar( - 'FEISHU_CLIENT_SECRET', - 'oauth.feishu.client_secret', - os.getenv('FEISHU_CLIENT_SECRET', ''), -) +FEISHU_CLIENT_SECRET = os.getenv('FEISHU_CLIENT_SECRET', '') -FEISHU_OAUTH_SCOPE = ConfigVar( - 'FEISHU_OAUTH_SCOPE', - 'oauth.feishu.scope', - os.getenv('FEISHU_OAUTH_SCOPE', 'contact:user.base:readonly'), -) +FEISHU_OAUTH_SCOPE = os.getenv('FEISHU_OAUTH_SCOPE', 'contact:user.base:readonly') -FEISHU_REDIRECT_URI = ConfigVar( - 'FEISHU_REDIRECT_URI', - 'oauth.feishu.redirect_uri', - os.getenv('FEISHU_REDIRECT_URI', ''), -) +FEISHU_REDIRECT_URI = os.getenv('FEISHU_REDIRECT_URI', '') -ENABLE_OAUTH_ROLE_MANAGEMENT = ConfigVar( - 'ENABLE_OAUTH_ROLE_MANAGEMENT', - 'oauth.enable_role_mapping', - os.getenv('ENABLE_OAUTH_ROLE_MANAGEMENT', 'False').lower() == 'true', -) +ENABLE_OAUTH_ROLE_MANAGEMENT = os.getenv('ENABLE_OAUTH_ROLE_MANAGEMENT', 'False').lower() == 'true' -ENABLE_OAUTH_GROUP_MANAGEMENT = ConfigVar( - 'ENABLE_OAUTH_GROUP_MANAGEMENT', - 'oauth.enable_group_mapping', - os.getenv('ENABLE_OAUTH_GROUP_MANAGEMENT', 'False').lower() == 'true', -) +ENABLE_OAUTH_GROUP_MANAGEMENT = os.getenv('ENABLE_OAUTH_GROUP_MANAGEMENT', 'False').lower() == 'true' -ENABLE_OAUTH_GROUP_CREATION = ConfigVar( - 'ENABLE_OAUTH_GROUP_CREATION', - 'oauth.enable_group_creation', - os.getenv('ENABLE_OAUTH_GROUP_CREATION', 'False').lower() == 'true', -) +ENABLE_OAUTH_GROUP_CREATION = os.getenv('ENABLE_OAUTH_GROUP_CREATION', 'False').lower() == 'true' oauth_group_default_share = os.getenv('OAUTH_GROUP_DEFAULT_SHARE', 'true').strip().lower() -OAUTH_GROUP_DEFAULT_SHARE = ConfigVar( - 'OAUTH_GROUP_DEFAULT_SHARE', - 'oauth.group_default_share', - ('members' if oauth_group_default_share == 'members' else oauth_group_default_share == 'true'), -) +OAUTH_GROUP_DEFAULT_SHARE = 'members' if oauth_group_default_share == 'members' else oauth_group_default_share == 'true' -OAUTH_BLOCKED_GROUPS = ConfigVar( - 'OAUTH_BLOCKED_GROUPS', - 'oauth.blocked_groups', - os.getenv('OAUTH_BLOCKED_GROUPS', '[]'), -) +OAUTH_BLOCKED_GROUPS = os.getenv('OAUTH_BLOCKED_GROUPS', '[]') OAUTH_GROUPS_SEPARATOR = os.getenv('OAUTH_GROUPS_SEPARATOR', ';') -OAUTH_ROLES_CLAIM = ConfigVar( - 'OAUTH_ROLES_CLAIM', - 'oauth.roles_claim', - os.getenv('OAUTH_ROLES_CLAIM', 'roles'), -) +OAUTH_ROLES_CLAIM = os.getenv('OAUTH_ROLES_CLAIM', 'roles') OAUTH_ROLES_SEPARATOR = os.getenv('OAUTH_ROLES_SEPARATOR', ',') -OAUTH_ALLOWED_ROLES = ConfigVar( - 'OAUTH_ALLOWED_ROLES', - 'oauth.allowed_roles', - [ - role.strip() - for role in os.getenv('OAUTH_ALLOWED_ROLES', f'user{OAUTH_ROLES_SEPARATOR}admin').split(OAUTH_ROLES_SEPARATOR) - if role - ], -) +OAUTH_ALLOWED_ROLES = [ + role.strip() + for role in os.getenv('OAUTH_ALLOWED_ROLES', f'user{OAUTH_ROLES_SEPARATOR}admin').split(OAUTH_ROLES_SEPARATOR) + if role +] -OAUTH_ADMIN_ROLES = ConfigVar( - 'OAUTH_ADMIN_ROLES', - 'oauth.admin_roles', - [role.strip() for role in os.getenv('OAUTH_ADMIN_ROLES', 'admin').split(OAUTH_ROLES_SEPARATOR) if role], -) +OAUTH_ADMIN_ROLES = [ + role.strip() for role in os.getenv('OAUTH_ADMIN_ROLES', 'admin').split(OAUTH_ROLES_SEPARATOR) if role +] -OAUTH_ALLOWED_DOMAINS = ConfigVar( - 'OAUTH_ALLOWED_DOMAINS', - 'oauth.allowed_domains', - [domain.strip() for domain in os.getenv('OAUTH_ALLOWED_DOMAINS', '*').split(',')], -) +OAUTH_ALLOWED_DOMAINS = [domain.strip() for domain in os.getenv('OAUTH_ALLOWED_DOMAINS', '*').split(',')] -OAUTH_UPDATE_PICTURE_ON_LOGIN = ConfigVar( - 'OAUTH_UPDATE_PICTURE_ON_LOGIN', - 'oauth.update_picture_on_login', - os.getenv('OAUTH_UPDATE_PICTURE_ON_LOGIN', 'False').lower() == 'true', -) +OAUTH_UPDATE_PICTURE_ON_LOGIN = os.getenv('OAUTH_UPDATE_PICTURE_ON_LOGIN', 'False').lower() == 'true' -OAUTH_UPDATE_NAME_ON_LOGIN = ConfigVar( - 'OAUTH_UPDATE_NAME_ON_LOGIN', - 'oauth.update_name_on_login', - os.getenv('OAUTH_UPDATE_NAME_ON_LOGIN', 'False').lower() == 'true', -) +OAUTH_UPDATE_NAME_ON_LOGIN = os.getenv('OAUTH_UPDATE_NAME_ON_LOGIN', 'False').lower() == 'true' -OAUTH_UPDATE_EMAIL_ON_LOGIN = ConfigVar( - 'OAUTH_UPDATE_EMAIL_ON_LOGIN', - 'oauth.update_email_on_login', - os.getenv('OAUTH_UPDATE_EMAIL_ON_LOGIN', 'False').lower() == 'true', -) +OAUTH_UPDATE_EMAIL_ON_LOGIN = os.getenv('OAUTH_UPDATE_EMAIL_ON_LOGIN', 'False').lower() == 'true' OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID = ( os.getenv('OAUTH_ACCESS_TOKEN_REQUEST_INCLUDE_CLIENT_ID', 'False').lower() == 'true' ) -OAUTH_AUDIENCE = ConfigVar( - 'OAUTH_AUDIENCE', - 'oauth.audience', - os.getenv('OAUTH_AUDIENCE', ''), -) +OAUTH_AUDIENCE = os.getenv('OAUTH_AUDIENCE', '') OAUTH_AUTHORIZE_PARAMS = {} _oauth_authorize_params = os.getenv('OAUTH_AUTHORIZE_PARAMS', '') @@ -3799,19 +2532,19 @@ if _oauth_authorize_params: def load_oauth_providers(): OAUTH_PROVIDERS.clear() - if GOOGLE_CLIENT_ID.value and GOOGLE_CLIENT_SECRET.value: + if GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET: def google_oauth_register(oauth: OAuth): client = oauth.register( name='google', - client_id=GOOGLE_CLIENT_ID.value, - client_secret=GOOGLE_CLIENT_SECRET.value, + client_id=GOOGLE_CLIENT_ID, + client_secret=GOOGLE_CLIENT_SECRET, server_metadata_url='https://accounts.google.com/.well-known/openid-configuration', client_kwargs={ - 'scope': GOOGLE_OAUTH_SCOPE.value, - **({'timeout': int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}), + 'scope': GOOGLE_OAUTH_SCOPE, + **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), }, - redirect_uri=GOOGLE_REDIRECT_URI.value, + redirect_uri=GOOGLE_REDIRECT_URI, **({'authorize_params': GOOGLE_OAUTH_AUTHORIZE_PARAMS} if GOOGLE_OAUTH_AUTHORIZE_PARAMS else {}), ) return client @@ -3820,43 +2553,43 @@ def load_oauth_providers(): 'register': google_oauth_register, } - if MICROSOFT_CLIENT_ID.value and MICROSOFT_CLIENT_SECRET.value and MICROSOFT_CLIENT_TENANT_ID.value: + if MICROSOFT_CLIENT_ID and MICROSOFT_CLIENT_SECRET and MICROSOFT_CLIENT_TENANT_ID: def microsoft_oauth_register(oauth: OAuth): client = oauth.register( name='microsoft', - client_id=MICROSOFT_CLIENT_ID.value, - client_secret=MICROSOFT_CLIENT_SECRET.value, - server_metadata_url=f'{MICROSOFT_CLIENT_LOGIN_BASE_URL.value}/{MICROSOFT_CLIENT_TENANT_ID.value}/v2.0/.well-known/openid-configuration?appid={MICROSOFT_CLIENT_ID.value}', + client_id=MICROSOFT_CLIENT_ID, + client_secret=MICROSOFT_CLIENT_SECRET, + server_metadata_url=f'{MICROSOFT_CLIENT_LOGIN_BASE_URL}/{MICROSOFT_CLIENT_TENANT_ID}/v2.0/.well-known/openid-configuration?appid={MICROSOFT_CLIENT_ID}', client_kwargs={ - 'scope': MICROSOFT_OAUTH_SCOPE.value, - **({'timeout': int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}), + 'scope': MICROSOFT_OAUTH_SCOPE, + **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), }, - redirect_uri=MICROSOFT_REDIRECT_URI.value, + redirect_uri=MICROSOFT_REDIRECT_URI, ) return client OAUTH_PROVIDERS['microsoft'] = { - 'picture_url': MICROSOFT_CLIENT_PICTURE_URL.value, + 'picture_url': MICROSOFT_CLIENT_PICTURE_URL, 'register': microsoft_oauth_register, } - if GITHUB_CLIENT_ID.value and GITHUB_CLIENT_SECRET.value: + if GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET: def github_oauth_register(oauth: OAuth): client = oauth.register( name='github', - client_id=GITHUB_CLIENT_ID.value, - client_secret=GITHUB_CLIENT_SECRET.value, + client_id=GITHUB_CLIENT_ID, + client_secret=GITHUB_CLIENT_SECRET, access_token_url='https://github.com/login/oauth/access_token', authorize_url='https://github.com/login/oauth/authorize', api_base_url='https://api.github.com', userinfo_endpoint='https://api.github.com/user', client_kwargs={ - 'scope': GITHUB_CLIENT_SCOPE.value, - **({'timeout': int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}), + 'scope': GITHUB_CLIENT_SCOPE, + **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), }, - redirect_uri=GITHUB_CLIENT_REDIRECT_URI.value, + redirect_uri=GITHUB_CLIENT_REDIRECT_URI, ) return client @@ -3865,62 +2598,58 @@ def load_oauth_providers(): 'sub_claim': 'id', } - if ( - OAUTH_CLIENT_ID.value - and (OAUTH_CLIENT_SECRET.value or OAUTH_CODE_CHALLENGE_METHOD.value) - and OPENID_PROVIDER_URL.value - ): + if OAUTH_CLIENT_ID and (OAUTH_CLIENT_SECRET or OAUTH_CODE_CHALLENGE_METHOD) and OPENID_PROVIDER_URL: def oidc_oauth_register(oauth: OAuth): client_kwargs = { - 'scope': OAUTH_SCOPES.value, + 'scope': OAUTH_SCOPES, **( - {'token_endpoint_auth_method': OAUTH_TOKEN_ENDPOINT_AUTH_METHOD.value} - if OAUTH_TOKEN_ENDPOINT_AUTH_METHOD.value + {'token_endpoint_auth_method': OAUTH_TOKEN_ENDPOINT_AUTH_METHOD} + if OAUTH_TOKEN_ENDPOINT_AUTH_METHOD else {} ), - **({'timeout': int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}), + **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), } - if OAUTH_CODE_CHALLENGE_METHOD.value and OAUTH_CODE_CHALLENGE_METHOD.value == 'S256': + if OAUTH_CODE_CHALLENGE_METHOD and OAUTH_CODE_CHALLENGE_METHOD == 'S256': client_kwargs['code_challenge_method'] = 'S256' - elif OAUTH_CODE_CHALLENGE_METHOD.value: + elif OAUTH_CODE_CHALLENGE_METHOD: raise Exception( 'Code challenge methods other than "%s" not supported. Given: "%s"' - % ('S256', OAUTH_CODE_CHALLENGE_METHOD.value) + % ('S256', OAUTH_CODE_CHALLENGE_METHOD) ) client = oauth.register( name='oidc', - client_id=OAUTH_CLIENT_ID.value, - client_secret=OAUTH_CLIENT_SECRET.value, - server_metadata_url=OPENID_PROVIDER_URL.value, + client_id=OAUTH_CLIENT_ID, + client_secret=OAUTH_CLIENT_SECRET, + server_metadata_url=OPENID_PROVIDER_URL, client_kwargs=client_kwargs, - redirect_uri=OPENID_REDIRECT_URI.value, + redirect_uri=OPENID_REDIRECT_URI, ) return client OAUTH_PROVIDERS['oidc'] = { - 'name': OAUTH_PROVIDER_NAME.value, + 'name': OAUTH_PROVIDER_NAME, 'register': oidc_oauth_register, } - if FEISHU_CLIENT_ID.value and FEISHU_CLIENT_SECRET.value: + if FEISHU_CLIENT_ID and FEISHU_CLIENT_SECRET: def feishu_oauth_register(oauth: OAuth): client = oauth.register( name='feishu', - client_id=FEISHU_CLIENT_ID.value, - client_secret=FEISHU_CLIENT_SECRET.value, + client_id=FEISHU_CLIENT_ID, + client_secret=FEISHU_CLIENT_SECRET, access_token_url='https://open.feishu.cn/open-apis/authen/v2/oauth/token', authorize_url='https://accounts.feishu.cn/open-apis/authen/v1/authorize', api_base_url='https://open.feishu.cn/open-apis', userinfo_endpoint='https://open.feishu.cn/open-apis/authen/v1/user_info', client_kwargs={ - 'scope': FEISHU_OAUTH_SCOPE.value, - **({'timeout': int(OAUTH_TIMEOUT.value)} if OAUTH_TIMEOUT.value else {}), + 'scope': FEISHU_OAUTH_SCOPE, + **({'timeout': int(OAUTH_TIMEOUT)} if OAUTH_TIMEOUT else {}), }, - redirect_uri=FEISHU_REDIRECT_URI.value, + redirect_uri=FEISHU_REDIRECT_URI, ) return client @@ -3930,16 +2659,16 @@ def load_oauth_providers(): } configured_providers = [] - if GOOGLE_CLIENT_ID.value: + if GOOGLE_CLIENT_ID: configured_providers.append('Google') - if MICROSOFT_CLIENT_ID.value: + if MICROSOFT_CLIENT_ID: configured_providers.append('Microsoft') - if GITHUB_CLIENT_ID.value: + if GITHUB_CLIENT_ID: configured_providers.append('GitHub') - if FEISHU_CLIENT_ID.value: + if FEISHU_CLIENT_ID: configured_providers.append('Feishu') - if configured_providers and not OPENID_PROVIDER_URL.value and not OPENID_END_SESSION_ENDPOINT.value: + if configured_providers and not OPENID_PROVIDER_URL and not OPENID_END_SESSION_ENDPOINT: provider_list = ', '.join(configured_providers) log.warning( f'⚠️ OAuth providers configured ({provider_list}) but OPENID_PROVIDER_URL not set - logout will not work!' @@ -3956,92 +2685,427 @@ load_oauth_providers() # LDAP #################################### -ENABLE_LDAP = ConfigVar( - 'ENABLE_LDAP', - 'ldap.enable', - os.getenv('ENABLE_LDAP', 'false').lower() == 'true', -) - -LDAP_SERVER_LABEL = ConfigVar( - 'LDAP_SERVER_LABEL', - 'ldap.server.label', - os.getenv('LDAP_SERVER_LABEL', 'LDAP Server'), -) - -LDAP_SERVER_HOST = ConfigVar( - 'LDAP_SERVER_HOST', - 'ldap.server.host', - os.getenv('LDAP_SERVER_HOST', 'localhost'), -) - -LDAP_SERVER_PORT = ConfigVar( - 'LDAP_SERVER_PORT', - 'ldap.server.port', - int(os.getenv('LDAP_SERVER_PORT', '389')), -) - -LDAP_ATTRIBUTE_FOR_MAIL = ConfigVar( - 'LDAP_ATTRIBUTE_FOR_MAIL', - 'ldap.server.attribute_for_mail', - os.getenv('LDAP_ATTRIBUTE_FOR_MAIL', 'mail'), -) - -LDAP_ATTRIBUTE_FOR_USERNAME = ConfigVar( - 'LDAP_ATTRIBUTE_FOR_USERNAME', - 'ldap.server.attribute_for_username', - os.getenv('LDAP_ATTRIBUTE_FOR_USERNAME', 'uid'), -) - -LDAP_APP_DN = ConfigVar('LDAP_APP_DN', 'ldap.server.app_dn', os.getenv('LDAP_APP_DN', '')) - -LDAP_APP_PASSWORD = ConfigVar( - 'LDAP_APP_PASSWORD', - 'ldap.server.app_password', - os.getenv('LDAP_APP_PASSWORD', ''), -) - -LDAP_SEARCH_BASE = ConfigVar('LDAP_SEARCH_BASE', 'ldap.server.users_dn', os.getenv('LDAP_SEARCH_BASE', '')) - -LDAP_SEARCH_FILTERS = ConfigVar( - 'LDAP_SEARCH_FILTER', - 'ldap.server.search_filter', - os.getenv('LDAP_SEARCH_FILTER', os.getenv('LDAP_SEARCH_FILTERS', '')), -) - -LDAP_USE_TLS = ConfigVar( - 'LDAP_USE_TLS', - 'ldap.server.use_tls', - os.getenv('LDAP_USE_TLS', 'True').lower() == 'true', -) - -LDAP_CA_CERT_FILE = ConfigVar( - 'LDAP_CA_CERT_FILE', - 'ldap.server.ca_cert_file', - os.getenv('LDAP_CA_CERT_FILE', ''), -) - -LDAP_VALIDATE_CERT = ConfigVar( - 'LDAP_VALIDATE_CERT', - 'ldap.server.validate_cert', - os.getenv('LDAP_VALIDATE_CERT', 'True').lower() == 'true', -) - -LDAP_CIPHERS = ConfigVar('LDAP_CIPHERS', 'ldap.server.ciphers', os.getenv('LDAP_CIPHERS', 'ALL')) - -ENABLE_LDAP_GROUP_MANAGEMENT = ConfigVar( - 'ENABLE_LDAP_GROUP_MANAGEMENT', - 'ldap.group.enable_management', - os.getenv('ENABLE_LDAP_GROUP_MANAGEMENT', 'False').lower() == 'true', -) - -ENABLE_LDAP_GROUP_CREATION = ConfigVar( - 'ENABLE_LDAP_GROUP_CREATION', - 'ldap.group.enable_creation', - os.getenv('ENABLE_LDAP_GROUP_CREATION', 'False').lower() == 'true', -) - -LDAP_ATTRIBUTE_FOR_GROUPS = ConfigVar( - 'LDAP_ATTRIBUTE_FOR_GROUPS', - 'ldap.server.attribute_for_groups', - os.getenv('LDAP_ATTRIBUTE_FOR_GROUPS', 'memberOf'), +ENABLE_LDAP = os.getenv('ENABLE_LDAP', 'false').lower() == 'true' + +LDAP_SERVER_LABEL = os.getenv('LDAP_SERVER_LABEL', 'LDAP Server') + +LDAP_SERVER_HOST = os.getenv('LDAP_SERVER_HOST', 'localhost') + +LDAP_SERVER_PORT = int(os.getenv('LDAP_SERVER_PORT', '389')) + +LDAP_ATTRIBUTE_FOR_MAIL = os.getenv('LDAP_ATTRIBUTE_FOR_MAIL', 'mail') + +LDAP_ATTRIBUTE_FOR_USERNAME = os.getenv('LDAP_ATTRIBUTE_FOR_USERNAME', 'uid') + +LDAP_APP_DN = os.getenv('LDAP_APP_DN', '') + +LDAP_APP_PASSWORD = os.getenv('LDAP_APP_PASSWORD', '') + +LDAP_SEARCH_BASE = os.getenv('LDAP_SEARCH_BASE', '') + +LDAP_SEARCH_FILTERS = os.getenv('LDAP_SEARCH_FILTER', os.getenv('LDAP_SEARCH_FILTERS', '')) + +LDAP_USE_TLS = os.getenv('LDAP_USE_TLS', 'True').lower() == 'true' + +LDAP_CA_CERT_FILE = os.getenv('LDAP_CA_CERT_FILE', '') + +LDAP_VALIDATE_CERT = os.getenv('LDAP_VALIDATE_CERT', 'True').lower() == 'true' + +LDAP_CIPHERS = os.getenv('LDAP_CIPHERS', 'ALL') + +ENABLE_LDAP_GROUP_MANAGEMENT = os.getenv('ENABLE_LDAP_GROUP_MANAGEMENT', 'False').lower() == 'true' + +ENABLE_LDAP_GROUP_CREATION = os.getenv('ENABLE_LDAP_GROUP_CREATION', 'False').lower() == 'true' + +LDAP_ATTRIBUTE_FOR_GROUPS = os.getenv('LDAP_ATTRIBUTE_FOR_GROUPS', 'memberOf') + +DEFAULT_CONFIG = { + 'direct.enable': ENABLE_DIRECT_CONNECTIONS, + 'ollama.enable': ENABLE_OLLAMA_API, + 'ollama.base_urls': OLLAMA_BASE_URLS, + 'ollama.api_configs': OLLAMA_API_CONFIGS, + 'openai.enable': ENABLE_OPENAI_API, + 'openai.api_keys': OPENAI_API_KEYS, + 'openai.api_base_urls': OPENAI_API_BASE_URLS, + 'openai.api_configs': OPENAI_API_CONFIGS, + 'models.base_models_cache': ENABLE_BASE_MODELS_CACHE, + 'tool_server.connections': TOOL_SERVER_CONNECTIONS, + 'oauth.client.timeout': OAUTH_CLIENT_TIMEOUT, + 'terminal_server.connections': TERMINAL_SERVER_CONNECTIONS, + 'code_execution.enable': ENABLE_CODE_EXECUTION, + 'code_execution.engine': CODE_EXECUTION_ENGINE, + 'code_execution.jupyter.url': CODE_EXECUTION_JUPYTER_URL, + 'code_execution.jupyter.auth': CODE_EXECUTION_JUPYTER_AUTH, + 'code_execution.jupyter.auth_token': CODE_EXECUTION_JUPYTER_AUTH_TOKEN, + 'code_execution.jupyter.auth_password': CODE_EXECUTION_JUPYTER_AUTH_PASSWORD, + 'code_execution.jupyter.timeout': CODE_EXECUTION_JUPYTER_TIMEOUT, + 'code_interpreter.enable': ENABLE_CODE_INTERPRETER, + 'memories.enable': ENABLE_MEMORIES, + 'memories.background_review.enable': ENABLE_MEMORY_BACKGROUND_REVIEW, + 'memories.review_interval_turns': MEMORIES_REVIEW_INTERVAL_TURNS, + 'memories.user_char_limit': MEMORIES_USER_CHAR_LIMIT, + 'memories.context_char_limit': MEMORIES_CONTEXT_CHAR_LIMIT, + 'code_interpreter.engine': CODE_INTERPRETER_ENGINE, + 'code_interpreter.prompt_template': CODE_INTERPRETER_PROMPT_TEMPLATE, + 'code_interpreter.jupyter.url': CODE_INTERPRETER_JUPYTER_URL, + 'code_interpreter.jupyter.auth': CODE_INTERPRETER_JUPYTER_AUTH, + 'code_interpreter.jupyter.auth_token': CODE_INTERPRETER_JUPYTER_AUTH_TOKEN, + 'code_interpreter.jupyter.auth_password': CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD, + 'code_interpreter.jupyter.timeout': CODE_INTERPRETER_JUPYTER_TIMEOUT, + 'google_drive.enable': ENABLE_GOOGLE_DRIVE_INTEGRATION, + 'google_drive.client_id': GOOGLE_DRIVE_CLIENT_ID, + 'google_drive.api_key': GOOGLE_DRIVE_API_KEY, + 'onedrive.enable': ENABLE_ONEDRIVE_INTEGRATION, + 'onedrive.sharepoint_url': ONEDRIVE_SHAREPOINT_URL, + 'onedrive.sharepoint_tenant_id': ONEDRIVE_SHAREPOINT_TENANT_ID, + 'rag.content_extraction_engine': CONTENT_EXTRACTION_ENGINE, + 'rag.datalab_marker_api_key': DATALAB_MARKER_API_KEY, + 'rag.datalab_marker_api_base_url': DATALAB_MARKER_API_BASE_URL, + 'rag.datalab_marker_additional_config': DATALAB_MARKER_ADDITIONAL_CONFIG, + 'rag.datalab_marker_use_llm': DATALAB_MARKER_USE_LLM, + 'rag.datalab_marker_skip_cache': DATALAB_MARKER_SKIP_CACHE, + 'rag.datalab_marker_force_ocr': DATALAB_MARKER_FORCE_OCR, + 'rag.datalab_marker_paginate': DATALAB_MARKER_PAGINATE, + 'rag.datalab_marker_strip_existing_ocr': DATALAB_MARKER_STRIP_EXISTING_OCR, + 'rag.datalab_marker_disable_image_extraction': DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, + 'rag.datalab_marker_format_lines': DATALAB_MARKER_FORMAT_LINES, + 'rag.datalab_marker_output_format': DATALAB_MARKER_OUTPUT_FORMAT, + 'rag.mineru_api_mode': MINERU_API_MODE, + 'rag.mineru_api_url': MINERU_API_URL, + 'rag.mineru_api_timeout': MINERU_API_TIMEOUT, + 'rag.mineru_api_key': MINERU_API_KEY, + 'rag.mineru_params': MINERU_PARAMS, + 'rag.mineru_file_extensions': MINERU_FILE_EXTENSIONS, + 'rag.external_document_loader_url': EXTERNAL_DOCUMENT_LOADER_URL, + 'rag.external_document_loader_api_key': EXTERNAL_DOCUMENT_LOADER_API_KEY, + 'rag.external_document_loader_headers': EXTERNAL_DOCUMENT_LOADER_HEADERS, + 'rag.tika_server_url': TIKA_SERVER_URL, + 'rag.docling_server_url': DOCLING_SERVER_URL, + 'rag.docling_api_key': DOCLING_API_KEY, + 'rag.docling_params': DOCLING_PARAMS, + 'rag.document_intelligence_endpoint': DOCUMENT_INTELLIGENCE_ENDPOINT, + 'rag.document_intelligence_key': DOCUMENT_INTELLIGENCE_KEY, + 'rag.document_intelligence_model': DOCUMENT_INTELLIGENCE_MODEL, + 'rag.mistral_ocr_api_base_url': MISTRAL_OCR_API_BASE_URL, + 'rag.mistral_ocr_api_key': MISTRAL_OCR_API_KEY, + 'rag.mistral_ocr_use_base64': MISTRAL_OCR_USE_BASE64, + 'rag.paddleocr_vl_base_url': PADDLEOCR_VL_BASE_URL, + 'rag.paddleocr_vl_token': PADDLEOCR_VL_TOKEN, + 'rag.bypass_embedding_and_retrieval': BYPASS_EMBEDDING_AND_RETRIEVAL, + 'rag.top_k': RAG_TOP_K, + 'rag.top_k_reranker': RAG_TOP_K_RERANKER, + 'rag.relevance_threshold': RAG_RELEVANCE_THRESHOLD, + 'rag.hybrid_bm25_weight': RAG_HYBRID_BM25_WEIGHT, + 'rag.enable_hybrid_search': ENABLE_RAG_HYBRID_SEARCH, + 'rag.enable_hybrid_search_enriched_texts': ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, + 'rag.full_context': RAG_FULL_CONTEXT, + 'rag.file.max_count': RAG_FILE_MAX_COUNT, + 'rag.file.max_size': RAG_FILE_MAX_SIZE, + 'file.image_compression_width': FILE_IMAGE_COMPRESSION_WIDTH, + 'file.image_compression_height': FILE_IMAGE_COMPRESSION_HEIGHT, + 'rag.file.allowed_extensions': RAG_ALLOWED_FILE_EXTENSIONS, + 'rag.embedding_engine': RAG_EMBEDDING_ENGINE, + 'rag.pdf_extract_images': PDF_EXTRACT_IMAGES, + 'rag.pdf_loader_mode': PDF_LOADER_MODE, + 'rag.embedding_model': RAG_EMBEDDING_MODEL, + 'rag.tokenizer_model': RAG_TOKENIZER_MODEL, + 'rag.embedding_batch_size': RAG_EMBEDDING_BATCH_SIZE, + 'rag.enable_async_embedding': ENABLE_ASYNC_EMBEDDING, + 'rag.embedding_concurrent_requests': RAG_EMBEDDING_CONCURRENT_REQUESTS, + 'rag.reranking_engine': RAG_RERANKING_ENGINE, + 'rag.reranking_model': RAG_RERANKING_MODEL, + 'rag.reranking_batch_size': RAG_RERANKING_BATCH_SIZE, + 'rag.external_reranker_url': RAG_EXTERNAL_RERANKER_URL, + 'rag.external_reranker_api_key': RAG_EXTERNAL_RERANKER_API_KEY, + 'rag.external_reranker_timeout': RAG_EXTERNAL_RERANKER_TIMEOUT, + 'rag.text_splitter': RAG_TEXT_SPLITTER, + 'rag.enable_markdown_header_text_splitter': ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, + 'rag.tiktoken_encoding_name': TIKTOKEN_ENCODING_NAME, + 'rag.chunk_size': CHUNK_SIZE, + 'rag.chunk_min_size_target': CHUNK_MIN_SIZE_TARGET, + 'rag.chunk_overlap': CHUNK_OVERLAP, + 'rag.template': RAG_TEMPLATE, + 'rag.openai.api_base_url': RAG_OPENAI_API_BASE_URL, + 'rag.openai.api_key': RAG_OPENAI_API_KEY, + 'rag.azure_openai.base_url': RAG_AZURE_OPENAI_BASE_URL, + 'rag.azure_openai.api_key': RAG_AZURE_OPENAI_API_KEY, + 'rag.azure_openai.api_version': RAG_AZURE_OPENAI_API_VERSION, + 'rag.ollama.base_url': RAG_OLLAMA_BASE_URL, + 'rag.ollama.api_key': RAG_OLLAMA_API_KEY, + 'rag.youtube_loader_language': YOUTUBE_LOADER_LANGUAGE, + 'rag.youtube_loader_proxy_url': YOUTUBE_LOADER_PROXY_URL, + 'web.search.enable': ENABLE_WEB_SEARCH, + 'web.search.confirmation.enable': ENABLE_WEB_SEARCH_CONFIRMATION, + 'web.search.confirmation.content': WEB_SEARCH_CONFIRMATION_CONTENT, + 'web.search.engine': WEB_SEARCH_ENGINE, + 'web.search.bypass_embedding_and_retrieval': BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, + 'web.search.bypass_web_loader': BYPASS_WEB_SEARCH_WEB_LOADER, + 'web.search.result_count': WEB_SEARCH_RESULT_COUNT, + 'web.search.domain.filter_list': WEB_SEARCH_DOMAIN_FILTER_LIST, + 'web.search.concurrent_requests': WEB_SEARCH_CONCURRENT_REQUESTS, + 'web.fetch.max_content_length': WEB_FETCH_MAX_CONTENT_LENGTH, + 'web.loader.engine': WEB_LOADER_ENGINE, + 'web.loader.concurrent_requests': WEB_LOADER_CONCURRENT_REQUESTS, + 'web.loader.timeout': WEB_LOADER_TIMEOUT, + 'web.loader.ssl_verification': ENABLE_WEB_LOADER_SSL_VERIFICATION, + 'web.search.trust_env': WEB_SEARCH_TRUST_ENV, + 'web.search.ollama_cloud_api_key': OLLAMA_CLOUD_WEB_SEARCH_API_KEY, + 'web.search.searxng_query_url': SEARXNG_QUERY_URL, + 'web.search.searxng_language': SEARXNG_LANGUAGE, + 'web.search.yacy_query_url': YACY_QUERY_URL, + 'web.search.yacy_username': YACY_USERNAME, + 'web.search.yacy_password': YACY_PASSWORD, + 'web.search.google_pse_api_key': GOOGLE_PSE_API_KEY, + 'web.search.google_pse_engine_id': GOOGLE_PSE_ENGINE_ID, + 'web.search.brave_search_api_key': BRAVE_SEARCH_API_KEY, + 'web.search.brave_search_context_tokens': BRAVE_SEARCH_CONTEXT_TOKENS, + 'web.search.kagi_search_api_key': KAGI_SEARCH_API_KEY, + 'web.search.mojeek_search_api_key': MOJEEK_SEARCH_API_KEY, + 'web.search.bocha_search_api_key': BOCHA_SEARCH_API_KEY, + 'web.search.serpstack_api_key': SERPSTACK_API_KEY, + 'web.search.serpstack_https': SERPSTACK_HTTPS, + 'web.search.serper_api_key': SERPER_API_KEY, + 'web.search.serply_api_key': SERPLY_API_KEY, + 'web.search.serphouse_api_key': SERPHOUSE_API_KEY, + 'web.search.serphouse_domain': SERPHOUSE_DOMAIN, + 'web.search.ddgs_backend': DDGS_BACKEND, + 'web.search.jina_api_key': JINA_API_KEY, + 'web.search.jina_api_base_url': JINA_API_BASE_URL, + 'web.search.searchapi_api_key': SEARCHAPI_API_KEY, + 'web.search.searchapi_engine': SEARCHAPI_ENGINE, + 'web.search.serpapi_api_key': SERPAPI_API_KEY, + 'web.search.serpapi_engine': SERPAPI_ENGINE, + 'web.search.bing_search_v7_endpoint': BING_SEARCH_V7_ENDPOINT, + 'web.search.bing_search_v7_subscription_key': BING_SEARCH_V7_SUBSCRIPTION_KEY, + 'web.search.azure_ai_search_api_key': AZURE_AI_SEARCH_API_KEY, + 'web.search.azure_ai_search_endpoint': AZURE_AI_SEARCH_ENDPOINT, + 'web.search.azure_ai_search_index_name': AZURE_AI_SEARCH_INDEX_NAME, + 'web.search.exa_api_key': EXA_API_KEY, + 'web.search.perplexity_api_key': PERPLEXITY_API_KEY, + 'web.search.perplexity_model': PERPLEXITY_MODEL, + 'web.search.perplexity_search_context_usage': PERPLEXITY_SEARCH_CONTEXT_USAGE, + 'web.search.perplexity_search_api_url': PERPLEXITY_SEARCH_API_URL, + 'web.search.microsoft_web_iq_api_base_url': MICROSOFT_WEB_IQ_API_BASE_URL, + 'web.search.microsoft_web_iq_api_key': MICROSOFT_WEB_IQ_API_KEY, + 'web.search.microsoft_web_iq_language': MICROSOFT_WEB_IQ_LANGUAGE, + 'web.search.sougou_api_sid': SOUGOU_API_SID, + 'web.search.sougou_api_sk': SOUGOU_API_SK, + 'web.search.tavily_api_key': TAVILY_API_KEY, + 'web.search.tavily_extract_depth': TAVILY_EXTRACT_DEPTH, + 'web.loader.playwright_ws_url': PLAYWRIGHT_WS_URL, + 'web.loader.playwright_timeout': PLAYWRIGHT_TIMEOUT, + 'web.loader.firecrawl_api_key': FIRECRAWL_API_KEY, + 'web.loader.firecrawl_api_url': FIRECRAWL_API_BASE_URL, + 'web.loader.firecrawl_timeout': FIRECRAWL_TIMEOUT, + 'web.search.external_web_search_url': EXTERNAL_WEB_SEARCH_URL, + 'web.search.external_web_search_api_key': EXTERNAL_WEB_SEARCH_API_KEY, + 'web.loader.external_web_loader_url': EXTERNAL_WEB_LOADER_URL, + 'web.loader.external_web_loader_api_key': EXTERNAL_WEB_LOADER_API_KEY, + 'web.search.yandex_web_search_url': YANDEX_WEB_SEARCH_URL, + 'web.search.yandex_web_search_api_key': YANDEX_WEB_SEARCH_API_KEY, + 'web.search.yandex_web_search_config': YANDEX_WEB_SEARCH_CONFIG, + 'web.search.youcom_api_key': YOUCOM_API_KEY, + 'web.search.linkup_api_key': LINKUP_API_KEY, + 'web.search.linkup_search_params': LINKUP_SEARCH_PARAMS, + 'image_generation.enable': ENABLE_IMAGE_GENERATION, + 'image_generation.engine': IMAGE_GENERATION_ENGINE, + 'image_generation.model': IMAGE_GENERATION_MODEL, + 'image_generation.size': IMAGE_SIZE, + 'image_generation.steps': IMAGE_STEPS, + 'image_generation.prompt.enable': ENABLE_IMAGE_PROMPT_GENERATION, + 'image_generation.automatic1111.base_url': AUTOMATIC1111_BASE_URL, + 'image_generation.automatic1111.api_auth': AUTOMATIC1111_API_AUTH, + 'image_generation.automatic1111.api_params': AUTOMATIC1111_PARAMS, + 'image_generation.comfyui.base_url': COMFYUI_BASE_URL, + 'image_generation.comfyui.api_key': COMFYUI_API_KEY, + 'image_generation.comfyui.workflow': COMFYUI_WORKFLOW, + 'image_generation.comfyui.nodes': COMFYUI_WORKFLOW_NODES, + 'image_generation.openai.api_base_url': IMAGES_OPENAI_API_BASE_URL, + 'image_generation.openai.api_version': IMAGES_OPENAI_API_VERSION, + 'image_generation.openai.api_key': IMAGES_OPENAI_API_KEY, + 'image_generation.openai.params': IMAGES_OPENAI_API_PARAMS, + 'image_generation.gemini.api_base_url': IMAGES_GEMINI_API_BASE_URL, + 'image_generation.gemini.api_key': IMAGES_GEMINI_API_KEY, + 'image_generation.gemini.endpoint_method': IMAGES_GEMINI_ENDPOINT_METHOD, + 'images.edit.enable': ENABLE_IMAGE_EDIT, + 'images.edit.engine': IMAGE_EDIT_ENGINE, + 'images.edit.model': IMAGE_EDIT_MODEL, + 'images.edit.size': IMAGE_EDIT_SIZE, + 'images.edit.openai.api_base_url': IMAGES_EDIT_OPENAI_API_BASE_URL, + 'images.edit.openai.api_version': IMAGES_EDIT_OPENAI_API_VERSION, + 'images.edit.openai.api_key': IMAGES_EDIT_OPENAI_API_KEY, + 'images.edit.gemini.api_base_url': IMAGES_EDIT_GEMINI_API_BASE_URL, + 'images.edit.gemini.api_key': IMAGES_EDIT_GEMINI_API_KEY, + 'images.edit.comfyui.base_url': IMAGES_EDIT_COMFYUI_BASE_URL, + 'images.edit.comfyui.api_key': IMAGES_EDIT_COMFYUI_API_KEY, + 'images.edit.comfyui.workflow': IMAGES_EDIT_COMFYUI_WORKFLOW, + 'images.edit.comfyui.nodes': IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, + 'audio.stt.whisper_model': WHISPER_MODEL, + 'audio.stt.deepgram.api_key': DEEPGRAM_API_KEY, + 'audio.stt.openai.api_base_url': AUDIO_STT_OPENAI_API_BASE_URL, + 'audio.stt.openai.api_key': AUDIO_STT_OPENAI_API_KEY, + 'audio.stt.engine': AUDIO_STT_ENGINE, + 'audio.stt.model': AUDIO_STT_MODEL, + 'audio.stt.supported_content_types': AUDIO_STT_SUPPORTED_CONTENT_TYPES, + 'audio.stt.allowed_extensions': AUDIO_STT_ALLOWED_EXTENSIONS, + 'audio.stt.azure.api_key': AUDIO_STT_AZURE_API_KEY, + 'audio.stt.azure.region': AUDIO_STT_AZURE_REGION, + 'audio.stt.azure.locales': AUDIO_STT_AZURE_LOCALES, + 'audio.stt.azure.base_url': AUDIO_STT_AZURE_BASE_URL, + 'audio.stt.azure.max_speakers': AUDIO_STT_AZURE_MAX_SPEAKERS, + 'audio.stt.mistral.api_key': AUDIO_STT_MISTRAL_API_KEY, + 'audio.stt.mistral.api_base_url': AUDIO_STT_MISTRAL_API_BASE_URL, + 'audio.stt.mistral.use_chat_completions': AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS, + 'audio.tts.openai.api_base_url': AUDIO_TTS_OPENAI_API_BASE_URL, + 'audio.tts.openai.api_key': AUDIO_TTS_OPENAI_API_KEY, + 'audio.tts.openai.params': AUDIO_TTS_OPENAI_PARAMS, + 'audio.tts.api_key': AUDIO_TTS_API_KEY, + 'audio.tts.engine': AUDIO_TTS_ENGINE, + 'audio.tts.model': AUDIO_TTS_MODEL, + 'audio.tts.voice': AUDIO_TTS_VOICE, + 'audio.tts.split_on': AUDIO_TTS_SPLIT_ON, + 'audio.tts.azure.speech_region': AUDIO_TTS_AZURE_SPEECH_REGION, + 'audio.tts.azure.speech_base_url': AUDIO_TTS_AZURE_SPEECH_BASE_URL, + 'audio.tts.azure.speech_output_format': AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT, + 'audio.tts.mistral.api_key': AUDIO_TTS_MISTRAL_API_KEY, + 'audio.tts.mistral.api_base_url': AUDIO_TTS_MISTRAL_API_BASE_URL, + 'webui.url': WEBUI_URL, + 'ui.enable_signup': ENABLE_SIGNUP, + 'ui.enable_login_form': ENABLE_LOGIN_FORM, + 'ui.enable_password_change_form': ENABLE_PASSWORD_CHANGE_FORM, + 'ui.default_locale': DEFAULT_LOCALE, + 'ui.default_models': DEFAULT_MODELS, + 'ui.default_pinned_models': DEFAULT_PINNED_MODELS, + 'ui.prompt_suggestions': DEFAULT_PROMPT_SUGGESTIONS, + 'ui.model_order_list': MODEL_ORDER_LIST, + 'models.default_metadata': DEFAULT_MODEL_METADATA, + 'models.default_params': DEFAULT_MODEL_PARAMS, + 'ui.default_user_role': DEFAULT_USER_ROLE, + 'ui.default_group_id': DEFAULT_GROUP_ID, + 'ui.pending_user_overlay_title': PENDING_USER_OVERLAY_TITLE, + 'ui.pending_user_overlay_content': PENDING_USER_OVERLAY_CONTENT, + 'ui.watermark': RESPONSE_WATERMARK, + 'user.permissions': USER_PERMISSIONS, + 'folders.enable': ENABLE_FOLDERS, + 'folders.max_file_count': FOLDER_MAX_FILE_COUNT, + 'channels.enable': ENABLE_CHANNELS, + 'calendar.enable': ENABLE_CALENDAR, + 'automations.enable': ENABLE_AUTOMATIONS, + 'automations.max_count': AUTOMATION_MAX_COUNT, + 'automations.min_interval': AUTOMATION_MIN_INTERVAL, + 'automations.auth_token_expires_in': AUTOMATION_AUTH_TOKEN_EXPIRES_IN, + 'notes.enable': ENABLE_NOTES, + 'users.enable_status': ENABLE_USER_STATUS, + 'evaluation.arena.enable': ENABLE_EVALUATION_ARENA_MODELS, + 'evaluation.arena.models': EVALUATION_ARENA_MODELS, + 'webhook_url': WEBHOOK_URL, + 'ui.enable_community_sharing': ENABLE_COMMUNITY_SHARING, + 'ui.enable_message_rating': ENABLE_MESSAGE_RATING, + 'ui.enable_user_webhooks': ENABLE_USER_WEBHOOKS, + 'ui.banners': WEBUI_BANNERS, + 'auth.admin.show': SHOW_ADMIN_DETAILS, + 'auth.admin.email': ADMIN_EMAIL, + 'task.model.default': TASK_MODEL, + 'task.model.external': TASK_MODEL_EXTERNAL, + 'chat.context_compaction.enable': ENABLE_CONTEXT_COMPACTION, + 'chat.context_compaction.token_threshold': CONTEXT_COMPACTION_TOKEN_THRESHOLD, + 'chat.context_compaction.prompt_template': CONTEXT_COMPACTION_PROMPT_TEMPLATE, + 'task.title.prompt_template': TITLE_GENERATION_PROMPT_TEMPLATE, + 'task.tags.prompt_template': TAGS_GENERATION_PROMPT_TEMPLATE, + 'task.image.prompt_template': IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE, + 'task.follow_up.prompt_template': FOLLOW_UP_GENERATION_PROMPT_TEMPLATE, + 'task.follow_up.enable': ENABLE_FOLLOW_UP_GENERATION, + 'task.tags.enable': ENABLE_TAGS_GENERATION, + 'task.title.enable': ENABLE_TITLE_GENERATION, + 'task.query.search.enable': ENABLE_SEARCH_QUERY_GENERATION, + 'task.query.retrieval.enable': ENABLE_RETRIEVAL_QUERY_GENERATION, + 'task.query.prompt_template': QUERY_GENERATION_PROMPT_TEMPLATE, + 'task.autocomplete.enable': ENABLE_AUTOCOMPLETE_GENERATION, + 'task.autocomplete.input_max_length': AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH, + 'task.autocomplete.prompt_template': AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE, + 'task.voice.prompt_template': VOICE_MODE_PROMPT_TEMPLATE, + 'task.voice.prompt.enable': ENABLE_VOICE_MODE_PROMPT, + 'task.tools.prompt_template': TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, + 'auth.enable_api_keys': ENABLE_API_KEYS, + 'auth.api_key.endpoint_restrictions': ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, + 'auth.api_key.allowed_endpoints': API_KEYS_ALLOWED_ENDPOINTS, + 'auth.jwt_expiry': JWT_EXPIRES_IN, + 'oauth.enable_signup': ENABLE_OAUTH_SIGNUP, + 'oauth.auto_redirect': OAUTH_AUTO_REDIRECT, + 'oauth.refresh_token.include_scope': OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE, + 'oauth.merge_accounts_by_email': OAUTH_MERGE_ACCOUNTS_BY_EMAIL, + 'oauth.google.client_id': GOOGLE_CLIENT_ID, + 'oauth.google.client_secret': GOOGLE_CLIENT_SECRET, + 'oauth.google.scope': GOOGLE_OAUTH_SCOPE, + 'oauth.google.redirect_uri': GOOGLE_REDIRECT_URI, + 'oauth.microsoft.client_id': MICROSOFT_CLIENT_ID, + 'oauth.microsoft.client_secret': MICROSOFT_CLIENT_SECRET, + 'oauth.microsoft.tenant_id': MICROSOFT_CLIENT_TENANT_ID, + 'oauth.microsoft.login_base_url': MICROSOFT_CLIENT_LOGIN_BASE_URL, + 'oauth.microsoft.picture_url': MICROSOFT_CLIENT_PICTURE_URL, + 'oauth.microsoft.scope': MICROSOFT_OAUTH_SCOPE, + 'oauth.microsoft.redirect_uri': MICROSOFT_REDIRECT_URI, + 'oauth.github.client_id': GITHUB_CLIENT_ID, + 'oauth.github.client_secret': GITHUB_CLIENT_SECRET, + 'oauth.github.scope': GITHUB_CLIENT_SCOPE, + 'oauth.github.redirect_uri': GITHUB_CLIENT_REDIRECT_URI, + 'oauth.client_id': OAUTH_CLIENT_ID, + 'oauth.client_secret': OAUTH_CLIENT_SECRET, + 'oauth.provider_url': OPENID_PROVIDER_URL, + 'oauth.end_session_endpoint': OPENID_END_SESSION_ENDPOINT, + 'oauth.redirect_uri': OPENID_REDIRECT_URI, + 'oauth.scopes': OAUTH_SCOPES, + 'oauth.timeout': OAUTH_TIMEOUT, + 'oauth.token_endpoint_auth_method': OAUTH_TOKEN_ENDPOINT_AUTH_METHOD, + 'oauth.code_challenge_method': OAUTH_CODE_CHALLENGE_METHOD, + 'oauth.provider_name': OAUTH_PROVIDER_NAME, + 'oauth.sub_claim': OAUTH_SUB_CLAIM, + 'oauth.username_claim': OAUTH_USERNAME_CLAIM, + 'oauth.picture_claim': OAUTH_PICTURE_CLAIM, + 'oauth.email_claim': OAUTH_EMAIL_CLAIM, + 'oauth.group_claim': OAUTH_GROUPS_CLAIM, + 'oauth.feishu.client_id': FEISHU_CLIENT_ID, + 'oauth.feishu.client_secret': FEISHU_CLIENT_SECRET, + 'oauth.feishu.scope': FEISHU_OAUTH_SCOPE, + 'oauth.feishu.redirect_uri': FEISHU_REDIRECT_URI, + 'oauth.enable_role_mapping': ENABLE_OAUTH_ROLE_MANAGEMENT, + 'oauth.enable_group_mapping': ENABLE_OAUTH_GROUP_MANAGEMENT, + 'oauth.enable_group_creation': ENABLE_OAUTH_GROUP_CREATION, + 'oauth.group_default_share': OAUTH_GROUP_DEFAULT_SHARE, + 'oauth.blocked_groups': OAUTH_BLOCKED_GROUPS, + 'oauth.roles_claim': OAUTH_ROLES_CLAIM, + 'oauth.allowed_roles': OAUTH_ALLOWED_ROLES, + 'oauth.admin_roles': OAUTH_ADMIN_ROLES, + 'oauth.allowed_domains': OAUTH_ALLOWED_DOMAINS, + 'oauth.update_picture_on_login': OAUTH_UPDATE_PICTURE_ON_LOGIN, + 'oauth.update_name_on_login': OAUTH_UPDATE_NAME_ON_LOGIN, + 'oauth.update_email_on_login': OAUTH_UPDATE_EMAIL_ON_LOGIN, + 'oauth.audience': OAUTH_AUDIENCE, + 'ldap.enable': ENABLE_LDAP, + 'ldap.server.label': LDAP_SERVER_LABEL, + 'ldap.server.host': LDAP_SERVER_HOST, + 'ldap.server.port': LDAP_SERVER_PORT, + 'ldap.server.attribute_for_mail': LDAP_ATTRIBUTE_FOR_MAIL, + 'ldap.server.attribute_for_username': LDAP_ATTRIBUTE_FOR_USERNAME, + 'ldap.server.app_dn': LDAP_APP_DN, + 'ldap.server.app_password': LDAP_APP_PASSWORD, + 'ldap.server.users_dn': LDAP_SEARCH_BASE, + 'ldap.server.search_filter': LDAP_SEARCH_FILTERS, + 'ldap.server.use_tls': LDAP_USE_TLS, + 'ldap.server.ca_cert_file': LDAP_CA_CERT_FILE, + 'ldap.server.validate_cert': LDAP_VALIDATE_CERT, + 'ldap.server.ciphers': LDAP_CIPHERS, + 'ldap.group.enable_management': ENABLE_LDAP_GROUP_MANAGEMENT, + 'ldap.group.enable_creation': ENABLE_LDAP_GROUP_CREATION, + 'ldap.server.attribute_for_groups': LDAP_ATTRIBUTE_FOR_GROUPS, +} + + +ENABLE_PERSISTENT_CONFIG = os.getenv('ENABLE_PERSISTENT_CONFIG', 'True').lower() == 'true' +ENABLE_OAUTH_PERSISTENT_CONFIG = os.getenv('ENABLE_OAUTH_PERSISTENT_CONFIG', 'False').lower() == 'true' + +Config.configure( + defaults=DEFAULT_CONFIG, + enable_persistent=ENABLE_PERSISTENT_CONFIG, + enable_oauth_persistent=ENABLE_OAUTH_PERSISTENT_CONFIG, ) diff --git a/backend/open_webui/constants.py b/backend/open_webui/constants.py index 132f3ac19a..c4d6b8f3db 100644 --- a/backend/open_webui/constants.py +++ b/backend/open_webui/constants.py @@ -1,8 +1,29 @@ from __future__ import annotations +import errno from enum import Enum +_ERRNO_MESSAGES = { + errno.ENAMETOOLONG: 'File name is too long.', + errno.ENOSPC: 'The server is out of storage space.', + errno.EDQUOT: 'Server storage quota exceeded.', + errno.EACCES: 'Server storage is not writable.', + errno.EPERM: 'Server storage is not writable.', + errno.EROFS: 'Server storage is not writable.', +} + + +def _error_message(err='', fallback='') -> str: + if not err: + return 'Something went wrong :/' + if isinstance(err, OSError) and err.errno in _ERRNO_MESSAGES: + return f'[ERROR: {_ERRNO_MESSAGES[err.errno]}]' + if isinstance(err, Exception): + return f'[ERROR: {fallback}]' if fallback else 'Something went wrong :/' + return f'[ERROR: {err}]' + + class MESSAGES(str, Enum): DEFAULT = lambda msg='': f'{msg if msg else ""}' MODEL_ADDED = lambda model='': f"The model '{model}' has been added successfully." @@ -18,7 +39,7 @@ class ERROR_MESSAGES(str, Enum): def __str__(self) -> str: return super().__str__() - DEFAULT = lambda err='': f'{"Something went wrong :/" if err == "" else "[ERROR: " + str(err) + "]"}' + DEFAULT = _error_message ENV_VAR_NOT_FOUND = 'Required environment variable not found. Terminating now.' CREATE_USER_ERROR = 'Oops! Something went wrong while creating your account. Please try again later. If the issue persists, contact support for assistance.' DELETE_USER_ERROR = 'Oops! Something went wrong. We encountered an issue while trying to delete the user. Please give it another shot.' diff --git a/backend/open_webui/env.py b/backend/open_webui/env.py index 2f6b4ed632..e4b1e57b32 100644 --- a/backend/open_webui/env.py +++ b/backend/open_webui/env.py @@ -291,6 +291,7 @@ if 'postgres://' in DATABASE_URL: DATABASE_URL = DATABASE_URL.replace('postgres://', 'postgresql://') DATABASE_SCHEMA = os.getenv('DATABASE_SCHEMA', None) +DATABASE_ENABLE_IAM_TOKEN_AUTH = os.getenv('DATABASE_ENABLE_IAM_TOKEN_AUTH', 'False').lower() == 'true' _pool_size_raw = os.getenv('DATABASE_POOL_SIZE') try: @@ -498,6 +499,65 @@ else: WEBSOCKET_EVENT_CALLER_TIMEOUT = 300 +import ssl as _ssl + + +# Dedicated env var for a custom CA bundle file path. When set, this is +# used as the default CA bundle for all outbound HTTPS connections that +# have SSL verification enabled (i.e. when their per-connection SSL env +# var is ``"True"``). Per-connection overrides (setting the SSL env var +# to a path directly) take precedence over this global fallback. +# +# This follows the industry convention of ``SSL_CERT_FILE`` / ``REQUESTS_CA_BUNDLE`` +# but is scoped to Open WebUI to avoid interfering with system-level settings. +AIOHTTP_CLIENT_SSL_CERT_FILE = os.getenv('AIOHTTP_CLIENT_SSL_CERT_FILE', '').strip() + + +def _build_ssl_context_from_file(path: str) -> '_ssl.SSLContext | None': + """Create an SSLContext from a CA bundle file, or None if invalid.""" + if not path: + return None + if not os.path.isfile(path): + log.warning( + 'SSL CA bundle path does not exist: %r, ignoring', + path, + ) + return None + ctx = _ssl.create_default_context(cafile=path) + log.info('Using custom SSL CA bundle: %s', path) + return ctx + + +# Pre-built SSLContext from the dedicated env var (cached once at startup). +_GLOBAL_SSL_CONTEXT = _build_ssl_context_from_file(AIOHTTP_CLIENT_SSL_CERT_FILE) + + +def _parse_ssl_env(value: str) -> 'bool | _ssl.SSLContext': + """Parse an SSL env var into a bool or SSLContext. + + - ``"true"`` → uses ``AIOHTTP_CLIENT_SSL_CERT_FILE`` context if set, + otherwise ``True`` (default SSL verification via certifi) + - ``"false"`` → ``False`` (no verification) + - ``"/path/to/ca-bundle.crt"`` → ``SSLContext`` loading that CA file + (takes precedence over ``AIOHTTP_CLIENT_SSL_CERT_FILE``) + + This allows users with corporate or internal CAs to point Open WebUI + at a custom CA bundle without disabling verification entirely. + """ + lower = value.strip().lower() + if lower == 'true': + # Use the global dedicated CA bundle if configured, otherwise default + return _GLOBAL_SSL_CONTEXT if _GLOBAL_SSL_CONTEXT is not None else True + if lower == 'false': + return False + # Treat as a file path to a CA bundle (per-connection override) + ctx = _build_ssl_context_from_file(value.strip()) + if ctx is not None: + return ctx + # Path was invalid — fall back to default + return _GLOBAL_SSL_CONTEXT if _GLOBAL_SSL_CONTEXT is not None else True + + REQUESTS_VERIFY = os.getenv('REQUESTS_VERIFY', 'True').lower() == 'true' _aiohttp_timeout_raw = os.getenv('AIOHTTP_CLIENT_TIMEOUT', '') @@ -507,7 +567,10 @@ except (ValueError, TypeError): AIOHTTP_CLIENT_TIMEOUT = 300 -AIOHTTP_CLIENT_SESSION_SSL = os.getenv('AIOHTTP_CLIENT_SESSION_SSL', 'True').lower() == 'true' +# SSL verification for general outbound requests (OpenAI, OAuth, etc.). +# Accepts "True", "False", or a path to a CA bundle file. +# When "True", falls back to AIOHTTP_CLIENT_SSL_CERT_FILE if set. +AIOHTTP_CLIENT_SESSION_SSL = _parse_ssl_env(os.getenv('AIOHTTP_CLIENT_SESSION_SSL', 'True')) # When False (default), outbound HTTP requests do not follow 3xx redirects. AIOHTTP_CLIENT_ALLOW_REDIRECTS = os.getenv('AIOHTTP_CLIENT_ALLOW_REDIRECTS', 'False').lower() == 'true' @@ -533,7 +596,10 @@ except (ValueError, TypeError): AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER_DATA = 10 -AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL = os.getenv('AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL', 'True').lower() == 'true' +# SSL verification for tool server connections specifically. +# Accepts "True", "False", or a path to a CA bundle file. +# When "True", falls back to AIOHTTP_CLIENT_SSL_CERT_FILE if set. +AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL = _parse_ssl_env(os.getenv('AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL', 'True')) AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER = os.getenv('AIOHTTP_CLIENT_TIMEOUT_TOOL_SERVER', '') @@ -616,6 +682,8 @@ WEBUI_SECRET_KEY = os.getenv( os.getenv('WEBUI_JWT_SECRET_KEY', ''), ) +ENABLE_VALVE_ENCRYPTION = os.getenv('ENABLE_VALVE_ENCRYPTION', 'False').lower() == 'true' + WEBUI_SESSION_COOKIE_SAME_SITE = os.getenv('WEBUI_SESSION_COOKIE_SAME_SITE', 'lax') WEBUI_SESSION_COOKIE_SECURE = os.getenv('WEBUI_SESSION_COOKIE_SECURE', 'false').lower() == 'true' WEBUI_AUTH_COOKIE_SAME_SITE = os.getenv('WEBUI_AUTH_COOKIE_SAME_SITE', WEBUI_SESSION_COOKIE_SAME_SITE) @@ -662,6 +730,7 @@ WEBUI_AUTH_TRUSTED_ROLE_HEADER = os.getenv('WEBUI_AUTH_TRUSTED_ROLE_HEADER', Non CUSTOM_API_KEY_HEADER = os.getenv('CUSTOM_API_KEY_HEADER', 'x-api-key') ENABLE_PASSWORD_VALIDATION = os.getenv('ENABLE_PASSWORD_VALIDATION', 'False').lower() == 'true' +PASSWORD_HASH_ALGORITHM = os.getenv('PASSWORD_HASH_ALGORITHM', 'bcrypt').lower() PASSWORD_VALIDATION_REGEX_PATTERN = os.getenv( 'PASSWORD_VALIDATION_REGEX_PATTERN', r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\w\s]).{8,}$', @@ -686,6 +755,9 @@ BYPASS_RETRIEVAL_ACCESS_CONTROL = os.getenv('BYPASS_RETRIEVAL_ACCESS_CONTROL', ' # for non-admin users. When False (default), unknown collection names are # denied — closing the legacy unscoped namespace. ENABLE_RETRIEVAL_UNSCOPED_COLLECTIONS = os.getenv('ENABLE_RETRIEVAL_UNSCOPED_COLLECTIONS', 'False').lower() == 'true' +MINERU_MAX_MARKDOWN_BYTES = ( + int(os.getenv('MINERU_MAX_MARKDOWN_BYTES')) if os.getenv('MINERU_MAX_MARKDOWN_BYTES') else None +) # When enabled, skips pydub-based preprocessing (format conversion, compression, # and chunked splitting) before sending files to processing engines. Useful when @@ -862,6 +934,7 @@ else: ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION = ( os.getenv('ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION', 'False').lower() == 'true' ) +ENABLE_API_OUTLET_FILTERS = os.getenv('ENABLE_API_OUTLET_FILTERS', 'True').lower() == 'true' # When enabled, uses a hardcoded extension-to-MIME dictionary as a last-resort # fallback when both mimetypes.guess_type() and file.meta.content_type fail to @@ -985,6 +1058,12 @@ if OFFLINE_MODE: os.environ['HF_HUB_OFFLINE'] = '1' ENABLE_VERSION_UPDATE_CHECK = False +#################################### +# Pyodide file persistence +#################################### + +ENABLE_PYODIDE_FILE_PERSISTENCE = os.getenv('ENABLE_PYODIDE_FILE_PERSISTENCE', 'false').lower() == 'true' + #################################### # Audit logging #################################### diff --git a/backend/open_webui/events.py b/backend/open_webui/events.py new file mode 100644 index 0000000000..1e87d912bd --- /dev/null +++ b/backend/open_webui/events.py @@ -0,0 +1,1110 @@ +from __future__ import annotations + +import asyncio +import inspect +import logging +import time +import uuid +from types import SimpleNamespace +from typing import Any + +from open_webui.env import VERSION +from open_webui.models.config import Config +from pydantic import BaseModel, ConfigDict, Field, model_validator +from open_webui.retrieval.web.utils import validate_url +from open_webui.utils.webhook import post_webhook + +log = logging.getLogger(__name__) + +MAX_STRING_LENGTH = 1000 +EVENT_WEBHOOKS_CONFIG_KEY = 'events.webhooks' +LEGACY_WEBHOOK_CONFIG_KEY = 'webhook_url' +DEFAULT_WEBHOOK_ID = 'default' + + +class EventDefinition(BaseModel): + model_config = ConfigDict(frozen=True) + + name: str + description: str | None = None + message: str | None = None + + @model_validator(mode='after') + def defaults(self) -> 'EventDefinition': + title = self.name.replace('.', ' ').replace('_', ' ').title() + if self.description is None: + object.__setattr__(self, 'description', f'{title}.') + if self.message is None: + object.__setattr__(self, 'message', title) + return self + + +class EventDefinitions(BaseModel): + model_config = ConfigDict(frozen=True) + + SYSTEM_STARTUP_STARTED: EventDefinition = EventDefinition( + name='system.startup.started', description='Application startup began.', message='Startup started' + ) + SYSTEM_STARTUP_COMPLETED: EventDefinition = EventDefinition( + name='system.startup.completed', description='Application startup completed.', message='Startup completed' + ) + SYSTEM_SHUTDOWN_STARTED: EventDefinition = EventDefinition( + name='system.shutdown.started', description='Application shutdown began.', message='Shutdown started' + ) + SYSTEM_SHUTDOWN_COMPLETED: EventDefinition = EventDefinition( + name='system.shutdown.completed', description='Application shutdown completed.', message='Shutdown completed' + ) + CONFIG_IMPORTED: EventDefinition = EventDefinition( + name='config.imported', description='Configuration was imported.', message='Config imported' + ) + CONFIG_UPDATED: EventDefinition = EventDefinition( + name='config.updated', description='Configuration was updated.', message='Config updated' + ) + CONFIG_WEBHOOK_UPDATED: EventDefinition = EventDefinition( + name='config.webhook.updated', + description='Event webhook configuration was updated.', + message='Webhook configuration updated', + ) + CONFIG_CONNECTIONS_UPDATED: EventDefinition = EventDefinition( + name='config.connections.updated', + description='Connection configuration was updated.', + message='Config Connections updated', + ) + CONFIG_TOOL_SERVERS_UPDATED: EventDefinition = EventDefinition( + name='config.tool_servers.updated', + description='Tool server configuration was updated.', + message='Config Tool Servers updated', + ) + CONFIG_TERMINAL_SERVERS_UPDATED: EventDefinition = EventDefinition( + name='config.terminal_servers.updated', + description='Terminal server configuration was updated.', + message='Config Terminal Servers updated', + ) + CONFIG_CODE_EXECUTION_UPDATED: EventDefinition = EventDefinition( + name='config.code_execution.updated', + description='Code execution configuration was updated.', + message='Config Code Execution updated', + ) + CONFIG_MODELS_UPDATED: EventDefinition = EventDefinition( + name='config.models.updated', description='Model configuration was updated.', message='Config Models updated' + ) + CONFIG_BANNERS_UPDATED: EventDefinition = EventDefinition( + name='config.banners.updated', description='Banner configuration was updated.', message='Config Banners updated' + ) + CONFIG_SUGGESTIONS_UPDATED: EventDefinition = EventDefinition( + name='config.suggestions.updated', + description='Suggestion configuration was updated.', + message='Config Suggestions updated', + ) + AUTH_SIGNUP: EventDefinition = EventDefinition( + name='auth.signup', description='A user account was created through signup.', message='User signed up' + ) + AUTH_LOGIN: EventDefinition = EventDefinition( + name='auth.login', description='A user successfully logged in.', message='User logged in' + ) + AUTH_LOGOUT: EventDefinition = EventDefinition( + name='auth.logout', description='A user logged out.', message='User logged out' + ) + AUTH_PASSWORD_CHANGED: EventDefinition = EventDefinition( + name='auth.password_changed', description='A user password was changed.', message='Password changed' + ) + AUTH_API_KEY_CREATED: EventDefinition = EventDefinition( + name='auth.api_key.created', description='A user API key was created.', message='API key created' + ) + AUTH_API_KEY_DELETED: EventDefinition = EventDefinition( + name='auth.api_key.deleted', description='A user API key was deleted.', message='API key deleted' + ) + AUTH_OAUTH_SESSION_DELETED: EventDefinition = EventDefinition( + name='auth.oauth_session.deleted', description='An OAuth session was deleted.', message='OAuth session deleted' + ) + USER_CREATED: EventDefinition = EventDefinition( + name='user.created', description='A user account was created.', message='User created' + ) + USER_UPDATED: EventDefinition = EventDefinition( + name='user.updated', description='A user account was updated.', message='User updated' + ) + USER_DELETED: EventDefinition = EventDefinition( + name='user.deleted', description='A user account was deleted.', message='User deleted' + ) + USER_ROLE_UPDATED: EventDefinition = EventDefinition( + name='user.role_updated', description='A user role was updated.', message='User role updated' + ) + USER_STATUS_UPDATED: EventDefinition = EventDefinition( + name='user.status_updated', description='A user status was updated.', message='User status updated' + ) + USER_SETTINGS_UPDATED: EventDefinition = EventDefinition( + name='user.settings_updated', description='A user settings object was updated.', message='User settings updated' + ) + USER_PROFILE_UPDATED: EventDefinition = EventDefinition( + name='user.profile_updated', description='A user profile was updated.', message='User profile updated' + ) + USER_PERMISSIONS_UPDATED: EventDefinition = EventDefinition( + name='user.permissions_updated', + description='A user permissions object was updated.', + message='User permissions updated', + ) + GROUP_CREATED: EventDefinition = EventDefinition( + name='group.created', description='A group was created.', message='Group created' + ) + GROUP_UPDATED: EventDefinition = EventDefinition( + name='group.updated', description='A group was updated.', message='Group updated' + ) + GROUP_DELETED: EventDefinition = EventDefinition( + name='group.deleted', description='A group was deleted.', message='Group deleted' + ) + GROUP_MEMBER_ADDED: EventDefinition = EventDefinition( + name='group.member_added', description='A user was added to a group.', message='Group member added' + ) + GROUP_MEMBER_REMOVED: EventDefinition = EventDefinition( + name='group.member_removed', description='A user was removed from a group.', message='Group member removed' + ) + CHAT_CREATED: EventDefinition = EventDefinition( + name='chat.created', description='A chat was created.', message='Chat created' + ) + CHAT_IMPORTED: EventDefinition = EventDefinition( + name='chat.imported', description='A chat was imported.', message='Chat imported' + ) + CHAT_UPDATED: EventDefinition = EventDefinition( + name='chat.updated', description='A chat was updated.', message='Chat updated' + ) + CHAT_DELETED: EventDefinition = EventDefinition( + name='chat.deleted', description='A chat was deleted.', message='Chat deleted' + ) + CHAT_DELETED_ALL: EventDefinition = EventDefinition( + name='chat.deleted_all', description='All chats for a scope were deleted.', message='Chat deleted all' + ) + CHAT_COMPACTED: EventDefinition = EventDefinition( + name='chat.compacted', description='A chat was compacted.', message='Chat compacted' + ) + CHAT_PINNED: EventDefinition = EventDefinition( + name='chat.pinned', description='A chat was pinned.', message='Chat pinned' + ) + CHAT_UNPINNED: EventDefinition = EventDefinition( + name='chat.unpinned', description='A chat was unpinned.', message='Chat unpinned' + ) + CHAT_CLONED: EventDefinition = EventDefinition( + name='chat.cloned', description='A chat was cloned.', message='Chat cloned' + ) + CHAT_ARCHIVED: EventDefinition = EventDefinition( + name='chat.archived', description='A chat was archived.', message='Chat archived' + ) + CHAT_UNARCHIVED: EventDefinition = EventDefinition( + name='chat.unarchived', description='A chat was unarchived.', message='Chat unarchived' + ) + CHAT_SHARED: EventDefinition = EventDefinition( + name='chat.shared', description='A chat was shared.', message='Chat shared' + ) + CHAT_UNSHARED: EventDefinition = EventDefinition( + name='chat.unshared', description='A chat was unshared.', message='Chat unshared' + ) + CHAT_FOLDER_UPDATED: EventDefinition = EventDefinition( + name='chat.folder_updated', description='A chat folder assignment was updated.', message='Chat folder updated' + ) + CHAT_TAG_ADDED: EventDefinition = EventDefinition( + name='chat.tag_added', description='A tag was added to a chat.', message='Chat tag added' + ) + CHAT_TAG_REMOVED: EventDefinition = EventDefinition( + name='chat.tag_removed', description='A tag was removed from a chat.', message='Chat tag removed' + ) + MESSAGE_CREATED: EventDefinition = EventDefinition( + name='message.created', description='A message was created.', message='Message created' + ) + MESSAGE_UPDATED: EventDefinition = EventDefinition( + name='message.updated', description='A message was updated.', message='Message updated' + ) + MESSAGE_DELETED: EventDefinition = EventDefinition( + name='message.deleted', description='A message was deleted.', message='Message deleted' + ) + MESSAGE_EVENT_RECEIVED: EventDefinition = EventDefinition( + name='message.event_received', + description='A message-level event was received.', + message='Message event received', + ) + MESSAGE_REACTION_ADDED: EventDefinition = EventDefinition( + name='message.reaction_added', + description='A reaction was added to a message.', + message='Message reaction added', + ) + MESSAGE_REACTION_REMOVED: EventDefinition = EventDefinition( + name='message.reaction_removed', + description='A reaction was removed from a message.', + message='Message reaction removed', + ) + MESSAGE_PINNED: EventDefinition = EventDefinition( + name='message.pinned', description='A message was pinned.', message='Message pinned' + ) + MESSAGE_UNPINNED: EventDefinition = EventDefinition( + name='message.unpinned', description='A message was unpinned.', message='Message unpinned' + ) + CHANNEL_CREATED: EventDefinition = EventDefinition( + name='channel.created', description='A channel was created.', message='Channel created' + ) + CHANNEL_UPDATED: EventDefinition = EventDefinition( + name='channel.updated', description='A channel was updated.', message='Channel updated' + ) + CHANNEL_DELETED: EventDefinition = EventDefinition( + name='channel.deleted', description='A channel was deleted.', message='Channel deleted' + ) + CHANNEL_MEMBER_ADDED: EventDefinition = EventDefinition( + name='channel.member_added', description='A member was added to a channel.', message='Channel member added' + ) + CHANNEL_MEMBER_REMOVED: EventDefinition = EventDefinition( + name='channel.member_removed', + description='A member was removed from a channel.', + message='Channel member removed', + ) + CHANNEL_MEMBER_ACTIVE_UPDATED: EventDefinition = EventDefinition( + name='channel.member_active_updated', + description='A channel member active state was updated.', + message='Channel member active updated', + ) + CHANNEL_WEBHOOK_CREATED: EventDefinition = EventDefinition( + name='channel.webhook.created', + description='A channel incoming webhook was created.', + message='Channel Webhook created', + ) + CHANNEL_WEBHOOK_UPDATED: EventDefinition = EventDefinition( + name='channel.webhook.updated', + description='A channel incoming webhook was updated.', + message='Channel Webhook updated', + ) + CHANNEL_WEBHOOK_DELETED: EventDefinition = EventDefinition( + name='channel.webhook.deleted', + description='A channel incoming webhook was deleted.', + message='Channel Webhook deleted', + ) + FILE_UPLOADED: EventDefinition = EventDefinition( + name='file.uploaded', description='A file was uploaded.', message='File uploaded' + ) + FILE_CONTENT_UPDATED: EventDefinition = EventDefinition( + name='file.content_updated', description='File content was updated.', message='File content updated' + ) + FILE_RENAMED: EventDefinition = EventDefinition( + name='file.renamed', description='A file was renamed.', message='File renamed' + ) + FILE_DELETED: EventDefinition = EventDefinition( + name='file.deleted', description='A file was deleted.', message='File deleted' + ) + FILE_DELETED_ALL: EventDefinition = EventDefinition( + name='file.deleted_all', description='All files for a scope were deleted.', message='File deleted all' + ) + FOLDER_CREATED: EventDefinition = EventDefinition( + name='folder.created', description='A folder was created.', message='Folder created' + ) + FOLDER_UPDATED: EventDefinition = EventDefinition( + name='folder.updated', description='A folder was updated.', message='Folder updated' + ) + FOLDER_PARENT_UPDATED: EventDefinition = EventDefinition( + name='folder.parent_updated', description='A folder parent was updated.', message='Folder parent updated' + ) + FOLDER_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='folder.access_updated', description='Folder access was updated.', message='Folder access updated' + ) + FOLDER_DELETED: EventDefinition = EventDefinition( + name='folder.deleted', description='A folder was deleted.', message='Folder deleted' + ) + NOTE_CREATED: EventDefinition = EventDefinition( + name='note.created', description='A note was created.', message='Note created' + ) + NOTE_UPDATED: EventDefinition = EventDefinition( + name='note.updated', description='A note was updated.', message='Note updated' + ) + NOTE_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='note.access_updated', description='Note access was updated.', message='Note access updated' + ) + NOTE_PINNED: EventDefinition = EventDefinition( + name='note.pinned', description='A note was pinned.', message='Note pinned' + ) + NOTE_UNPINNED: EventDefinition = EventDefinition( + name='note.unpinned', description='A note was unpinned.', message='Note unpinned' + ) + NOTE_DELETED: EventDefinition = EventDefinition( + name='note.deleted', description='A note was deleted.', message='Note deleted' + ) + MEMORY_CREATED: EventDefinition = EventDefinition( + name='memory.created', description='A memory was created.', message='Memory created' + ) + MEMORY_UPDATED: EventDefinition = EventDefinition( + name='memory.updated', description='A memory was updated.', message='Memory updated' + ) + MEMORY_DELETED: EventDefinition = EventDefinition( + name='memory.deleted', description='A memory was deleted.', message='Memory deleted' + ) + MEMORY_RESET: EventDefinition = EventDefinition( + name='memory.reset', description='A memory was reset.', message='Memory reset' + ) + KNOWLEDGE_CREATED: EventDefinition = EventDefinition( + name='knowledge.created', description='A knowledge was created.', message='Knowledge created' + ) + KNOWLEDGE_UPDATED: EventDefinition = EventDefinition( + name='knowledge.updated', description='A knowledge was updated.', message='Knowledge updated' + ) + KNOWLEDGE_DELETED: EventDefinition = EventDefinition( + name='knowledge.deleted', description='A knowledge was deleted.', message='Knowledge deleted' + ) + KNOWLEDGE_RESET: EventDefinition = EventDefinition( + name='knowledge.reset', description='A knowledge was reset.', message='Knowledge reset' + ) + KNOWLEDGE_REINDEXED: EventDefinition = EventDefinition( + name='knowledge.reindexed', description='A knowledge was reindexed.', message='Knowledge reindexed' + ) + KNOWLEDGE_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='knowledge.access_updated', description='Knowledge access was updated.', message='Knowledge access updated' + ) + KNOWLEDGE_FILE_ADDED: EventDefinition = EventDefinition( + name='knowledge.file.added', description='A file was added to a knowledge base.', message='Knowledge File added' + ) + KNOWLEDGE_FILE_UPDATED: EventDefinition = EventDefinition( + name='knowledge.file.updated', description='A knowledge file was updated.', message='Knowledge File updated' + ) + KNOWLEDGE_FILE_REMOVED: EventDefinition = EventDefinition( + name='knowledge.file.removed', + description='A file was removed from a knowledge base.', + message='Knowledge File removed', + ) + KNOWLEDGE_FILE_MOVED: EventDefinition = EventDefinition( + name='knowledge.file.moved', description='A knowledge file was moved.', message='Knowledge File moved' + ) + KNOWLEDGE_DIRECTORY_CREATED: EventDefinition = EventDefinition( + name='knowledge.directory.created', + description='A knowledge directory was created.', + message='Knowledge Directory created', + ) + KNOWLEDGE_DIRECTORY_UPDATED: EventDefinition = EventDefinition( + name='knowledge.directory.updated', + description='A knowledge directory was updated.', + message='Knowledge Directory updated', + ) + KNOWLEDGE_DIRECTORY_DELETED: EventDefinition = EventDefinition( + name='knowledge.directory.deleted', + description='A knowledge directory was deleted.', + message='Knowledge Directory deleted', + ) + KNOWLEDGE_EXTERNAL_CONNECTION_CREATED: EventDefinition = EventDefinition( + name='knowledge.external_connection.created', + description='A knowledge external connection was created.', + message='Knowledge External Connection created', + ) + KNOWLEDGE_EXTERNAL_CONNECTION_UPDATED: EventDefinition = EventDefinition( + name='knowledge.external_connection.updated', + description='A knowledge external connection was updated.', + message='Knowledge External Connection updated', + ) + KNOWLEDGE_EXTERNAL_CONNECTION_DELETED: EventDefinition = EventDefinition( + name='knowledge.external_connection.deleted', + description='A knowledge external connection was deleted.', + message='Knowledge External Connection deleted', + ) + RETRIEVAL_CONTENT_PROCESSED: EventDefinition = EventDefinition( + name='retrieval.content.processed', + description='Retrieval content was processed.', + message='Retrieval Content processed', + ) + RETRIEVAL_COLLECTION_DELETED: EventDefinition = EventDefinition( + name='retrieval.collection.deleted', + description='A retrieval collection was deleted.', + message='Retrieval Collection deleted', + ) + RETRIEVAL_VECTOR_DB_RESET: EventDefinition = EventDefinition( + name='retrieval.vector_db.reset', + description='The retrieval vector database was reset.', + message='Retrieval Vector Db reset', + ) + RETRIEVAL_UPLOADS_RESET: EventDefinition = EventDefinition( + name='retrieval.uploads.reset', description='Retrieval uploads were reset.', message='Retrieval Uploads reset' + ) + MODEL_CREATED: EventDefinition = EventDefinition( + name='model.created', description='A model was created.', message='Model created' + ) + MODEL_IMPORTED: EventDefinition = EventDefinition( + name='model.imported', description='A model was imported.', message='Model imported' + ) + MODEL_SYNCED: EventDefinition = EventDefinition( + name='model.synced', description='A model was synced.', message='Model synced' + ) + MODEL_UPDATED: EventDefinition = EventDefinition( + name='model.updated', description='A model was updated.', message='Model updated' + ) + MODEL_DELETED: EventDefinition = EventDefinition( + name='model.deleted', description='A model was deleted.', message='Model deleted' + ) + MODEL_ENABLED: EventDefinition = EventDefinition( + name='model.enabled', description='A model was enabled.', message='Model enabled' + ) + MODEL_DISABLED: EventDefinition = EventDefinition( + name='model.disabled', description='A model was disabled.', message='Model disabled' + ) + MODEL_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='model.access_updated', description='Model access was updated.', message='Model access updated' + ) + MODEL_PROVIDER_CONFIG_UPDATED: EventDefinition = EventDefinition( + name='model.provider_config.updated', + description='Model provider configuration was updated.', + message='Model Provider Config updated', + ) + MODEL_PROVIDER_MODEL_CREATED: EventDefinition = EventDefinition( + name='model.provider_model.created', + description='A provider model was created.', + message='Provider model created', + ) + MODEL_PROVIDER_MODEL_DELETED: EventDefinition = EventDefinition( + name='model.provider_model.deleted', + description='A provider model was deleted.', + message='Provider model deleted', + ) + FUNCTION_CREATED: EventDefinition = EventDefinition( + name='function.created', description='A function was created.', message='Function created' + ) + FUNCTION_UPDATED: EventDefinition = EventDefinition( + name='function.updated', description='A function was updated.', message='Function updated' + ) + FUNCTION_DELETED: EventDefinition = EventDefinition( + name='function.deleted', description='A function was deleted.', message='Function deleted' + ) + FUNCTION_ENABLED: EventDefinition = EventDefinition( + name='function.enabled', description='A function was enabled.', message='Function enabled' + ) + FUNCTION_DISABLED: EventDefinition = EventDefinition( + name='function.disabled', description='A function was disabled.', message='Function disabled' + ) + FUNCTION_VALVES_UPDATED: EventDefinition = EventDefinition( + name='function.valves_updated', description='Function valves were updated.', message='Function valves updated' + ) + TOOL_CREATED: EventDefinition = EventDefinition( + name='tool.created', description='A tool was created.', message='Tool created' + ) + TOOL_UPDATED: EventDefinition = EventDefinition( + name='tool.updated', description='A tool was updated.', message='Tool updated' + ) + TOOL_DELETED: EventDefinition = EventDefinition( + name='tool.deleted', description='A tool was deleted.', message='Tool deleted' + ) + TOOL_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='tool.access_updated', description='Tool access was updated.', message='Tool access updated' + ) + TOOL_VALVES_UPDATED: EventDefinition = EventDefinition( + name='tool.valves_updated', description='Tool valves were updated.', message='Tool valves updated' + ) + SKILL_CREATED: EventDefinition = EventDefinition( + name='skill.created', description='A skill was created.', message='Skill created' + ) + SKILL_UPDATED: EventDefinition = EventDefinition( + name='skill.updated', description='A skill was updated.', message='Skill updated' + ) + SKILL_DELETED: EventDefinition = EventDefinition( + name='skill.deleted', description='A skill was deleted.', message='Skill deleted' + ) + SKILL_ENABLED: EventDefinition = EventDefinition( + name='skill.enabled', description='A skill was enabled.', message='Skill enabled' + ) + SKILL_DISABLED: EventDefinition = EventDefinition( + name='skill.disabled', description='A skill was disabled.', message='Skill disabled' + ) + PROMPT_CREATED: EventDefinition = EventDefinition( + name='prompt.created', description='A prompt was created.', message='Prompt created' + ) + PROMPT_UPDATED: EventDefinition = EventDefinition( + name='prompt.updated', description='A prompt was updated.', message='Prompt updated' + ) + PROMPT_DELETED: EventDefinition = EventDefinition( + name='prompt.deleted', description='A prompt was deleted.', message='Prompt deleted' + ) + PROMPT_ENABLED: EventDefinition = EventDefinition( + name='prompt.enabled', description='A prompt was enabled.', message='Prompt enabled' + ) + PROMPT_DISABLED: EventDefinition = EventDefinition( + name='prompt.disabled', description='A prompt was disabled.', message='Prompt disabled' + ) + PROMPT_VERSION_UPDATED: EventDefinition = EventDefinition( + name='prompt.version_updated', description='A prompt version was updated.', message='Prompt version updated' + ) + PROMPT_ACCESS_UPDATED: EventDefinition = EventDefinition( + name='prompt.access_updated', description='Prompt access was updated.', message='Prompt access updated' + ) + PIPELINE_UPLOADED: EventDefinition = EventDefinition( + name='pipeline.uploaded', description='A pipeline was uploaded.', message='Pipeline uploaded' + ) + PIPELINE_ADDED: EventDefinition = EventDefinition( + name='pipeline.added', description='A pipeline was added.', message='Pipeline added' + ) + PIPELINE_DELETED: EventDefinition = EventDefinition( + name='pipeline.deleted', description='A pipeline was deleted.', message='Pipeline deleted' + ) + PIPELINE_VALVES_UPDATED: EventDefinition = EventDefinition( + name='pipeline.valves_updated', description='Pipeline valves were updated.', message='Pipeline valves updated' + ) + CALENDAR_CREATED: EventDefinition = EventDefinition( + name='calendar.created', description='A calendar was created.', message='Calendar created' + ) + CALENDAR_UPDATED: EventDefinition = EventDefinition( + name='calendar.updated', description='A calendar was updated.', message='Calendar updated' + ) + CALENDAR_DELETED: EventDefinition = EventDefinition( + name='calendar.deleted', description='A calendar was deleted.', message='Calendar deleted' + ) + CALENDAR_DEFAULT_UPDATED: EventDefinition = EventDefinition( + name='calendar.default_updated', + description='The default calendar was updated.', + message='Calendar default updated', + ) + CALENDAR_EVENT_CREATED: EventDefinition = EventDefinition( + name='calendar.event.created', description='A calendar event was created.', message='Calendar Event created' + ) + CALENDAR_EVENT_UPDATED: EventDefinition = EventDefinition( + name='calendar.event.updated', description='A calendar event was updated.', message='Calendar Event updated' + ) + CALENDAR_EVENT_DELETED: EventDefinition = EventDefinition( + name='calendar.event.deleted', description='A calendar event was deleted.', message='Calendar Event deleted' + ) + CALENDAR_EVENT_RSVP_UPDATED: EventDefinition = EventDefinition( + name='calendar.event.rsvp_updated', + description='A calendar event RSVP was updated.', + message='Calendar Event rsvp updated', + ) + AUTOMATION_CREATED: EventDefinition = EventDefinition( + name='automation.created', description='An automation was created.', message='Automation created' + ) + AUTOMATION_UPDATED: EventDefinition = EventDefinition( + name='automation.updated', description='An automation was updated.', message='Automation updated' + ) + AUTOMATION_ENABLED: EventDefinition = EventDefinition( + name='automation.enabled', description='An automation was enabled.', message='Automation enabled' + ) + AUTOMATION_DISABLED: EventDefinition = EventDefinition( + name='automation.disabled', description='An automation was disabled.', message='Automation disabled' + ) + AUTOMATION_DELETED: EventDefinition = EventDefinition( + name='automation.deleted', description='An automation was deleted.', message='Automation deleted' + ) + AUTOMATION_RUN_STARTED: EventDefinition = EventDefinition( + name='automation.run_started', description='An automation run started.', message='Automation run started' + ) + AUTOMATION_RUN_COMPLETED: EventDefinition = EventDefinition( + name='automation.run_completed', description='An automation run completed.', message='Automation run completed' + ) + AUTOMATION_RUN_FAILED: EventDefinition = EventDefinition( + name='automation.run_failed', description='An automation run failed.', message='Automation run failed' + ) + FEEDBACK_CREATED: EventDefinition = EventDefinition( + name='feedback.created', description='A feedback was created.', message='Feedback created' + ) + FEEDBACK_UPDATED: EventDefinition = EventDefinition( + name='feedback.updated', description='A feedback was updated.', message='Feedback updated' + ) + FEEDBACK_DELETED: EventDefinition = EventDefinition( + name='feedback.deleted', description='A feedback was deleted.', message='Feedback deleted' + ) + FEEDBACK_DELETED_ALL: EventDefinition = EventDefinition( + name='feedback.deleted_all', description='All feedback for a scope was deleted.', message='Feedback deleted all' + ) + IMAGE_GENERATED: EventDefinition = EventDefinition( + name='image.generated', description='An image was generated.', message='Image generated' + ) + IMAGE_EDITED: EventDefinition = EventDefinition( + name='image.edited', description='An image was edited.', message='Image edited' + ) + AUDIO_SPEECH_REQUESTED: EventDefinition = EventDefinition( + name='audio.speech_requested', description='Speech generation was requested.', message='Speech requested' + ) + AUDIO_TRANSCRIPTION_REQUESTED: EventDefinition = EventDefinition( + name='audio.transcription_requested', + description='Audio transcription was requested.', + message='Transcription requested', + ) + TERMINAL_SESSION_OPENED: EventDefinition = EventDefinition( + name='terminal.session.opened', description='A terminal session was opened.', message='Terminal Session opened' + ) + TERMINAL_SESSION_CLOSED: EventDefinition = EventDefinition( + name='terminal.session.closed', description='A terminal session was closed.', message='Terminal Session closed' + ) + + +EVENTS = EventDefinitions() +EVENT_DEFINITIONS = tuple(getattr(EVENTS, field_name) for field_name in EventDefinitions.model_fields) +EVENT_DEFINITIONS_BY_NAME = {definition.name: definition for definition in EVENT_DEFINITIONS} +EVENT_CATALOG = tuple(definition.name for definition in EVENT_DEFINITIONS) +EVENT_CATALOG_SET = set(EVENT_CATALOG) + + +def get_event_catalog() -> list[dict[str, str]]: + return [ + { + 'event': definition.name, + 'description': definition.description, + 'message': definition.message, + } + for definition in EVENT_DEFINITIONS + ] + + +SENSITIVE_KEYS = { + 'password', + 'hashed_password', + 'token', + 'access_token', + 'refresh_token', + 'id_token', + 'api_key', + 'secret', + 'key', + 'authorization', + 'cookie', + 'webhook_token', +} + +SAFE_ACTOR_FIELDS = ('id', 'name', 'email', 'role', 'created_at', 'updated_at') + + +def normalize_event_webhook(webhook: dict[str, Any], *, create: bool = False) -> dict[str, Any]: + now = int(time.time()) + webhook_id = str(webhook.get('id') or uuid.uuid4()) + url = str(webhook.get('url') or '').strip() + + events = [str(event).strip() for event in (webhook.get('events') or ['*']) if str(event).strip()] + events = events or ['*'] + for event_filter in events: + if event_filter == '*': + continue + if event_filter.endswith('.*'): + prefix = event_filter[:-2] + if prefix and any(event.startswith(f'{prefix}.') for event in EVENT_CATALOG): + continue + raise ValueError(f'Invalid event pattern: {event_filter}') + if event_filter not in EVENT_CATALOG_SET: + raise ValueError(f'Invalid event: {event_filter}') + + targets = normalize_event_targets(webhook.get('targets')) + + return { + 'id': webhook_id, + 'name': str(webhook.get('name') or ('Default webhook' if webhook_id == DEFAULT_WEBHOOK_ID else 'Webhook')), + 'url': url, + 'enabled': bool(webhook.get('enabled', True)), + 'events': events, + 'targets': targets, + 'created_at': int(webhook.get('created_at') or now), + 'updated_at': now if create or webhook.get('updated_at') is None else int(webhook.get('updated_at') or now), + } + + +def normalize_event_targets(targets: Any) -> list[dict[str, str]] | None: + if targets is None: + return None + if not isinstance(targets, list): + raise ValueError('Invalid targets') + + normalized = [] + seen = set() + for target in targets: + if not isinstance(target, dict): + raise ValueError('Invalid target') + + target_type = str(target.get('type') or '').strip() + target_id = str(target.get('id') or '').strip() + if target_type not in {'user', 'group'} or not target_id: + raise ValueError('Invalid target') + + key = (target_type, target_id) + if key in seen: + continue + + normalized.append({'type': target_type, 'id': target_id}) + seen.add(key) + + return normalized + + +def event_filter_matches(webhook: dict[str, Any], event_name: str) -> bool: + if not webhook.get('enabled', True): + return False + + for event_filter in webhook.get('events') or ['*']: + if event_filter == '*': + return True + if event_filter.endswith('.*') and event_name.startswith(f'{event_filter[:-2]}.'): + return True + if event_name == event_filter: + return True + return False + + +def event_user_ids(event: 'Event') -> set[str]: + user_ids = set() + actor = event.actor or {} + subject = event.subject or {} + data = event.data or {} + + if actor.get('id'): + user_ids.add(str(actor['id'])) + + if subject.get('type') == 'user' and subject.get('id'): + user_ids.add(str(subject['id'])) + + if data.get('user_id'): + user_ids.add(str(data['user_id'])) + + for user_id in data.get('user_ids') or []: + if user_id: + user_ids.add(str(user_id)) + + return user_ids + + +async def event_target_matches( + targets: list[dict[str, str]] | None, + user_ids: set[str], + user_group_ids: dict[str, set[str]] | None = None, +) -> bool: + if targets is None: + return True + if not targets: + return not user_ids + if not user_ids: + return False + + target_user_ids = {target['id'] for target in targets if target.get('type') == 'user'} + if target_user_ids.intersection(user_ids): + return True + + target_group_ids = {target['id'] for target in targets if target.get('type') == 'group'} + if not target_group_ids: + return False + + if user_group_ids is None: + from open_webui.models.groups import Groups + + groups_by_user = await Groups.get_groups_by_member_ids(list(user_ids)) + user_group_ids = {user_id: {group.id for group in groups} for user_id, groups in groups_by_user.items()} + + return any(group_ids.intersection(target_group_ids) for group_ids in user_group_ids.values()) + + +async def event_webhook_matches(webhook: dict[str, Any], event: 'Event') -> bool: + if not event_filter_matches(webhook, event.event): + return False + + return await event_target_matches(webhook.get('targets'), event_user_ids(event)) + + +async def get_event_webhooks() -> list[dict[str, Any]]: + webhooks = await Config.get(EVENT_WEBHOOKS_CONFIG_KEY, []) or [] + if not isinstance(webhooks, list): + return [] + + normalized = [] + for webhook in webhooks: + if not isinstance(webhook, dict): + continue + try: + normalized.append(normalize_event_webhook(webhook)) + except ValueError: + log.exception('Invalid event webhook config skipped') + return normalized + + +async def migrate_legacy_webhook_config() -> list[dict[str, Any]]: + webhooks = await get_event_webhooks() + if any(webhook.get('id') == DEFAULT_WEBHOOK_ID for webhook in webhooks): + return webhooks + + now = int(time.time()) + legacy_url = await Config.get(LEGACY_WEBHOOK_CONFIG_KEY) or '' + if not legacy_url: + return webhooks + + webhooks = [ + { + 'id': DEFAULT_WEBHOOK_ID, + 'name': 'Default webhook', + 'url': legacy_url, + 'enabled': True, + 'events': ['*'], + 'targets': None, + 'created_at': now, + 'updated_at': now, + }, + *webhooks, + ] + await Config.upsert({EVENT_WEBHOOKS_CONFIG_KEY: webhooks}) + return webhooks + + +async def upsert_event_webhook(webhook: dict[str, Any]) -> dict[str, Any]: + webhooks = await get_event_webhooks() + url = str(webhook.get('url') or '').strip() + if url: + validate_url(url) + + normalized = normalize_event_webhook(webhook, create=True) + replaced = False + next_webhooks = [] + + for existing in webhooks: + if existing.get('id') == normalized['id']: + next_webhooks.append( + { + **existing, + **normalized, + 'created_at': existing.get('created_at') or normalized['created_at'], + } + ) + replaced = True + else: + next_webhooks.append(existing) + + if not replaced: + next_webhooks.append(normalized) + + await Config.upsert({EVENT_WEBHOOKS_CONFIG_KEY: next_webhooks}) + return next(webhook for webhook in next_webhooks if webhook.get('id') == normalized['id']) + + +async def delete_event_webhook(webhook_id: str) -> bool: + webhooks = await get_event_webhooks() + next_webhooks = [webhook for webhook in webhooks if webhook.get('id') != webhook_id] + if len(next_webhooks) == len(webhooks): + return False + + values = {EVENT_WEBHOOKS_CONFIG_KEY: next_webhooks} + if webhook_id == DEFAULT_WEBHOOK_ID: + values[LEGACY_WEBHOOK_CONFIG_KEY] = '' + + await Config.upsert(values) + return True + + +class Event(BaseModel): + model_config = ConfigDict(populate_by_name=True) + + schema_: str = Field(alias='schema') + id: str + event: str + resource: str + operation: str + created_at: int + instance_id: str | None + version: str + source: str + actor: dict[str, Any] | None = None + subject: dict[str, Any] | None = None + data: dict[str, Any] = Field(default_factory=dict) + message: str | None = None + + def model_dump(self, *args, **kwargs) -> dict[str, Any]: + kwargs.setdefault('by_alias', True) + return super().model_dump(*args, **kwargs) + + +def _sensitive(key: Any) -> bool: + normalized = str(key).lower().replace('-', '_') + return ( + normalized in SENSITIVE_KEYS + or normalized.endswith('_token') + or normalized.endswith('_secret') + or normalized.endswith('_api_key') + or normalized.endswith('_key') + ) + + +def _sanitize(value: Any) -> Any: + if hasattr(value, 'model_dump'): + value = value.model_dump() + + if isinstance(value, dict): + return {key: _sanitize(item) for key, item in value.items() if not _sensitive(key)} + + if isinstance(value, (list, tuple, set)): + return [_sanitize(item) for item in value] + + if isinstance(value, str) and len(value) > MAX_STRING_LENGTH: + return f'{value[:MAX_STRING_LENGTH]}...' + + return value + + +def _actor(actor: Any | None) -> dict[str, Any] | None: + actor = _sanitize(actor) + if not actor: + return None + + get = actor.get if isinstance(actor, dict) else lambda key: getattr(actor, key, None) + data = {field: get(field) for field in SAFE_ACTOR_FIELDS if get(field) is not None} + if not data: + return None + + data['type'] = get('type') or 'user' + return data + + +def event_name(event: EventDefinition | str) -> str: + name = event.name if isinstance(event, EventDefinition) else str(event) + if name not in EVENT_CATALOG_SET: + raise ValueError(f'Unknown event: {name}') + return name + + +def build_event( + request_or_app: Any, + event: EventDefinition | str, + *, + actor: Any | None = None, + subject_id: Any | None = None, + subject_type: str | None = None, + source: str = 'api', + data: dict | None = None, + message: str | None = None, +) -> Event: + event_name_value = event_name(event) + app = getattr(request_or_app, 'app', request_or_app) + parts = event_name_value.split('.') + resource = '.'.join(parts[:-1]) + instance_id = getattr(getattr(app, 'state', None), 'instance_id', None) + subject = ( + {'type': subject_type or resource, 'id': subject_id} + if subject_id is not None or subject_type is not None + else None + ) + + return Event( + schema=VERSION, + id=str(uuid.uuid4()), + event=event_name_value, + resource=resource, + operation=parts[-1], + created_at=int(time.time()), + instance_id=instance_id, + version=VERSION, + source=source, + actor=_actor(actor), + subject=_sanitize(subject) if subject else None, + data=_sanitize(data or {}), + message=message, + ) + + +async def dispatch_webhook_event(app: Any, event: Event) -> None: + name = getattr(getattr(app, 'state', None), 'WEBUI_NAME', 'Open WebUI') + subject = event.subject or {} + subject_id = subject.get('id') + definition = EVENT_DEFINITIONS_BY_NAME.get(event.event) + message = event.message or (definition.message if definition else event.event) + if subject_id: + message = f'{message} ({subject_id})' + + for webhook in await get_event_webhooks(): + if not webhook.get('url') or not await event_webhook_matches(webhook, event): + continue + + try: + await post_webhook( + name, + webhook['url'], + message, + event.model_dump(), + description=definition.description if definition else None, + ) + except Exception: + log.exception('Event webhook failed for %s', webhook.get('id')) + + +def schedule_webhook_dispatch(app: Any, event: Event) -> None: + try: + asyncio.create_task(dispatch_webhook_event(app, event)) + except RuntimeError: + log.exception('Event webhook delivery could not be scheduled for %s', event.event) + + +class WebhookEventSink: + async def handle_event(self, app: Any, event: Event, request: Any | None = None) -> None: + schedule_webhook_dispatch(app, event) + + +async def dispatch_event_functions(app: Any, event: Event, request: Any | None = None) -> None: + from open_webui.models.functions import Functions + from open_webui.utils.plugin import get_function_module_from_cache + + context = request or SimpleNamespace(app=app) + event_payload = event.model_dump() + + try: + event_functions = await Functions.get_functions_by_type('event', active_only=True) + except Exception: + log.exception('Event functions could not be loaded for %s', event.event) + return + + for function in event_functions: + try: + function_module, _, _ = await get_function_module_from_cache(context, function.id, function=function) + handler = getattr(function_module, 'event', None) + if not handler: + continue + + if hasattr(function_module, 'valves') and hasattr(function_module, 'Valves'): + valves = await Functions.get_function_valves_by_id(function.id) + function_module.valves = function_module.Valves(**(valves if valves else {})) + + sig = inspect.signature(handler) + accepts_kwargs = any(param.kind == inspect.Parameter.VAR_KEYWORD for param in sig.parameters.values()) + extra_params = { + 'event': event_payload, + '__id__': function.id, + '__event__': event, + '__event_id__': event.id, + '__event_name__': event.event, + '__app__': app, + '__request__': request, + } + params = {key: value for key, value in extra_params.items() if accepts_kwargs or key in sig.parameters} + + if inspect.iscoroutinefunction(handler): + await handler(**params) + else: + handler(**params) + except Exception: + log.exception('Event function failed for %s', function.id) + + +def schedule_event_function_dispatch(app: Any, event: Event, request: Any | None = None) -> None: + try: + asyncio.create_task(dispatch_event_functions(app, event, request)) + except RuntimeError: + log.exception('Event functions could not be scheduled for %s', event.event) + + +class EventFunctionSink: + async def handle_event(self, app: Any, event: Event, request: Any | None = None) -> None: + schedule_event_function_dispatch(app, event, request) + + +EVENT_SINKS = [EventFunctionSink(), WebhookEventSink()] + + +async def publish_event( + request_or_app: Any, + event: EventDefinition | str, + *, + actor: Any | None = None, + subject_id: Any | None = None, + subject_type: str | None = None, + source: str = 'api', + data: dict | None = None, + message: str | None = None, +) -> None: + app = getattr(request_or_app, 'app', request_or_app) + request = request_or_app if hasattr(request_or_app, 'app') else None + event_payload = build_event( + request_or_app, + event, + actor=actor, + subject_id=subject_id, + subject_type=subject_type, + source=source, + data=data, + message=message, + ) + + for sink in EVENT_SINKS: + try: + await sink.handle_event(app, event_payload, request=request) + except Exception: + log.exception('Event sink failed for %s', event_payload.event) diff --git a/backend/open_webui/internal/config.py b/backend/open_webui/internal/config.py deleted file mode 100644 index 46f5b1b67d..0000000000 --- a/backend/open_webui/internal/config.py +++ /dev/null @@ -1,265 +0,0 @@ -"""Database-backed configuration with environment variable defaults.""" - -from __future__ import annotations - -import asyncio -import json -import logging -from datetime import datetime -from functools import reduce -from typing import Any, Optional, Union - -import redis -from open_webui.internal.db import Base, get_async_db, get_db -from open_webui.utils.redis import get_redis_connection -from sqlalchemy import JSON, Column, DateTime, Integer, func, select - -log = logging.getLogger(__name__) - - -# ── Model ──────────────────────────────────────────────────────────────────── - - -class ConfigTable(Base): - __tablename__ = 'config' - - id = Column(Integer, primary_key=True) - data = Column(JSON, nullable=False) - version = Column(Integer, nullable=False, default=0) - created_at = Column(DateTime, nullable=False, server_default=func.now()) - updated_at = Column(DateTime, nullable=True, onupdate=func.now()) - - -# ── Blob ───────────────────────────────────────────────────────────────────── - - -class ConfigState: - """In-memory mirror of the single-row config JSON blob.""" - - __slots__ = ('_data',) - - def __init__(self) -> None: - self._data: dict[str, Any] = {} - - @property - def snapshot(self) -> dict: - return self._data - - def read(self, path: str) -> Any: - return reduce( - lambda n, k: n.get(k) if isinstance(n, dict) else None, - path.split('.'), - self._data, - ) - - def write(self, path: str, value: Any) -> None: - keys = path.split('.') - reduce(lambda d, k: d.setdefault(k, {}), keys[:-1], self._data)[keys[-1]] = value - - def replace(self, data: dict) -> None: - self._data = data - - def load(self) -> dict: - with get_db() as db: - row = db.query(ConfigTable).order_by(ConfigTable.id.desc()).first() - self._data = row.data if row else {'version': 0, 'ui': {}} - return self._data - - def persist(self, data: dict | None = None) -> None: - if data is not None: - self._data = data - with get_db() as db: - row = db.query(ConfigTable).first() - if row is None: - db.add(ConfigTable(data=self._data, version=0)) - else: - row.data, row.updated_at = self._data, datetime.now() - db.add(row) - db.commit() - - async def persist_async(self, data: dict | None = None) -> None: - if data is not None: - self._data = data - async with get_async_db() as db: - result = await db.execute(select(ConfigTable).limit(1)) - row = result.scalars().first() - if row is None: - db.add(ConfigTable(data=self._data, version=0)) - else: - row.data, row.updated_at = self._data, datetime.now() - db.add(row) - await db.commit() - - def clear(self) -> None: - with get_db() as db: - db.query(ConfigTable).delete() - db.commit() - - async def clear_async(self) -> None: - from sqlalchemy import delete as sa_delete - - async with get_async_db() as db: - await db.execute(sa_delete(ConfigTable)) - await db.commit() - - -STATE = ConfigState() - - -# ── ConfigVar ────────────────────────────────────────────────────────────────── - - -_persist_enabled: bool = True -_oauth_persist_enabled: bool = False -_all_configs: list[ConfigVar] = [] - - -def initialize(*, enable_persistent: bool = True, enable_oauth_persistent: bool = False) -> dict: - global _persist_enabled, _oauth_persist_enabled - _persist_enabled = enable_persistent - _oauth_persist_enabled = enable_oauth_persistent - return STATE.load() - - -class ConfigVar: - __slots__ = ('env_name', 'config_path', 'env_value', 'config_value', 'value') - - def __init__(self, env_name: str, config_path: str, env_value: Any) -> None: - self.env_name = env_name - self.config_path = config_path - self.env_value = env_value - self.config_value = STATE.read(config_path) - - if self.config_value is not None and _persist_enabled: - if config_path.startswith('oauth.') and not _oauth_persist_enabled: - log.info("Skipping DB value for '%s' (OAuth persistence disabled)", env_name) - self.value = env_value - else: - log.info("'%s' loaded from database", env_name) - self.value = self.config_value - else: - self.value = env_value - - _all_configs.append(self) - - def __str__(self) -> str: - return str(self.value) - - def __repr__(self) -> str: - return f'' - - @property - def __dict__(self): # type: ignore[override] - raise TypeError(f"ConfigVar('{self.env_name}') cannot be cast to dict; use .value") - - def __getattribute__(self, item: str): - if item == '__dict__': - raise TypeError('ConfigVar cannot be cast to dict; use .value') - return super().__getattribute__(item) - - def refresh(self) -> None: - current = STATE.read(self.config_path) - if current is not None: - self.value = current - log.info('Refreshed %s → %s', self.env_name, self.value) - - def commit(self) -> None: - log.info("Persisting '%s'", self.env_name) - STATE.write(self.config_path, self.value) - self.config_value = self.value - STATE.persist() - - async def commit_async(self) -> None: - log.info("Persisting '%s'", self.env_name) - STATE.write(self.config_path, self.value) - self.config_value = self.value - await STATE.persist_async() - - -# ── AppConfig ────────────────────────────────────────────────────────── - - -class AppConfig: - """Attribute-style container for ConfigVars with optional Redis sync.""" - - def __init__( - self, - *, - redis_url: Optional[str] = None, - redis_sentinels: Optional[list] = None, - redis_cluster: bool = False, - redis_key_prefix: str = 'open-webui', - ) -> None: - super().__setattr__('_entries', {}) - super().__setattr__('_key_prefix', redis_key_prefix) - - # If sentinels weren't explicitly provided, read from env. - if redis_sentinels is None: - from open_webui.env import REDIS_SENTINEL_HOSTS, REDIS_SENTINEL_PORT - from open_webui.utils.redis import get_sentinels_from_env - - redis_sentinels = get_sentinels_from_env(REDIS_SENTINEL_HOSTS, REDIS_SENTINEL_PORT) - - rc: Union[redis.Redis, redis.cluster.RedisCluster, None] = None - if redis_url: - rc = get_redis_connection(redis_url, redis_sentinels or [], redis_cluster, decode_responses=True) - super().__setattr__('_rc', rc) - - def __setattr__(self, name: str, value: Any) -> None: - entries: dict = super().__getattribute__('_entries') - - if isinstance(value, ConfigVar): - entries[name] = value - return - - entries[name].value = value - - try: - asyncio.get_running_loop().create_task(self._write_async(name)) - except RuntimeError: - entries[name].commit() - - rc = super().__getattribute__('_rc') - if rc and _persist_enabled: - prefix = super().__getattribute__('_key_prefix') - try: - rc.set(f'{prefix}:config:{name}', json.dumps(entries[name].value)) - except Exception as exc: - log.error("Redis write failed for '%s': %s", name, exc) - - async def _write_async(self, name: str) -> None: - try: - await self._entries[name].commit_async() - except Exception as exc: - log.error("Async persist failed for '%s': %s", name, exc) - - def __getattr__(self, name: str) -> Any: - entries = super().__getattribute__('_entries') - if name not in entries: - raise AttributeError(f"No config key '{name}'") - - rc = super().__getattribute__('_rc') - if rc and _persist_enabled: - prefix = super().__getattribute__('_key_prefix') - try: - raw = rc.get(f'{prefix}:config:{name}') - if raw is not None: - decoded = json.loads(raw) - if entries[name].value != decoded: - entries[name].value = decoded - log.info("Updated '%s' from Redis", name) - except Exception as exc: - log.error("Redis read failed for '%s': %s", name, exc) - - return entries[name].value - - def _sync_to_redis(self) -> None: - rc = super().__getattribute__('_rc') - if not rc or not _persist_enabled: - return - prefix = super().__getattribute__('_key_prefix') - for name, s in super().__getattribute__('_entries').items(): - try: - rc.set(f'{prefix}:config:{name}', json.dumps(s.value)) - except Exception as exc: - log.error("Redis sync failed for '%s': %s", name, exc) diff --git a/backend/open_webui/internal/db.py b/backend/open_webui/internal/db.py index d3402b0310..7c890e0ca2 100644 --- a/backend/open_webui/internal/db.py +++ b/backend/open_webui/internal/db.py @@ -5,10 +5,12 @@ import logging import os import sys from contextlib import asynccontextmanager, contextmanager +from datetime import datetime, timedelta, timezone from typing import Any, Optional from urllib.parse import parse_qs, urlencode, urlparse, urlunparse from open_webui.env import ( + DATABASE_ENABLE_IAM_TOKEN_AUTH, DATABASE_ENABLE_SESSION_SHARING, DATABASE_ENABLE_SQLITE_WAL, DATABASE_POOL_MAX_OVERFLOW, @@ -27,6 +29,7 @@ from open_webui.env import ( OPEN_WEBUI_DIR, ) from sqlalchemy import Dialect, MetaData, create_engine, event, types +from sqlalchemy.engine.url import make_url from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session, scoped_session, sessionmaker @@ -146,6 +149,63 @@ _url_without_ssl, _ssl_dict = extract_ssl_params_from_url(DATABASE_URL) SQLALCHEMY_DATABASE_URL = reattach_ssl_params_to_url(_url_without_ssl, _ssl_dict) if _ssl_dict else DATABASE_URL +class RDSIAMTokenAuth: + _refresh_after = timedelta(minutes=14) + + def __init__(self, database_url: str) -> None: + url = make_url(database_url) + if not url.drivername.startswith(('postgresql', 'postgres')): + raise ValueError('DATABASE_ENABLE_IAM_TOKEN_AUTH is only supported for PostgreSQL databases') + if not url.host or not url.username: + raise ValueError('DATABASE_ENABLE_IAM_TOKEN_AUTH requires a database host and user') + + self.host = url.host + self.port = url.port or 5432 + self.username = url.username + self._client = None + self._token: str | None = None + self._expires_at = datetime.min.replace(tzinfo=timezone.utc) + + @property + def client(self): + if self._client is None: + import boto3 + + self._client = boto3.client('rds') + return self._client + + def get_password(self) -> str: + now = datetime.now(timezone.utc) + if self._token and now < self._expires_at: + return self._token + + self._token = self.client.generate_db_auth_token( + DBHostname=self.host, + Port=self.port, + DBUsername=self.username, + ) + self._expires_at = now + self._refresh_after + log.info('AWS RDS IAM database token refreshed; next refresh after %s', self._expires_at.isoformat()) + return self._token + + +_rds_iam_token_auth = RDSIAMTokenAuth(SQLALCHEMY_DATABASE_URL) if DATABASE_ENABLE_IAM_TOKEN_AUTH else None + + +def _set_iam_token_password(dialect, conn_rec, cargs, cparams): + if _rds_iam_token_auth is not None: + cparams['password'] = _rds_iam_token_auth.get_password() + + +def enable_iam_token_auth(connectable) -> None: + if _rds_iam_token_auth is None: + return + + engine = getattr(connectable, 'sync_engine', connectable) + if not event.contains(engine, 'do_connect', _set_iam_token_password): + event.listen(engine, 'do_connect', _set_iam_token_password) + + def _make_async_url(url: str) -> str: """Convert a sync database URL to its async driver equivalent. @@ -268,6 +328,8 @@ else: else: engine = create_engine(SQLALCHEMY_DATABASE_URL, pool_pre_ping=True) +enable_iam_token_auth(engine) + # Sync session — used ONLY for startup config loading (config.py runs at import time) SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, expire_on_commit=False) @@ -344,6 +406,8 @@ else: pool_pre_ping=True, ) +enable_iam_token_auth(async_engine) + AsyncSessionLocal = async_sessionmaker( bind=async_engine, diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index e05497c616..bd9580e9ce 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -1,42 +1,30 @@ from __future__ import annotations import asyncio -import inspect import json import logging import mimetypes import os -import random -import re -import shutil import sys import time from contextlib import asynccontextmanager -from typing import Optional -from urllib.parse import parse_qs, urlencode, urlparse from uuid import uuid4 import aiohttp import anyio.to_thread -from aiocache import cached from fastapi import ( - BackgroundTasks, Depends, FastAPI, - File, - Form, HTTPException, Request, - UploadFile, applications, status, ) from fastapi.middleware.cors import CORSMiddleware from fastapi.openapi.docs import get_swagger_ui_html -from fastapi.responses import FileResponse, JSONResponse, RedirectResponse +from fastapi.responses import FileResponse, JSONResponse from fastapi.staticfiles import StaticFiles from pydantic import BaseModel -from redis import Redis from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession from starlette.datastructures import Headers @@ -53,372 +41,34 @@ from starsessions import ( from starsessions.stores.redis import RedisStore from open_webui.config import ( - ADMIN_EMAIL, - API_KEYS_ALLOWED_ENDPOINTS, - AUDIO_STT_ALLOWED_EXTENSIONS, - AUDIO_STT_AZURE_API_KEY, - AUDIO_STT_AZURE_BASE_URL, - AUDIO_STT_AZURE_LOCALES, - AUDIO_STT_AZURE_MAX_SPEAKERS, - AUDIO_STT_AZURE_REGION, - # Audio - AUDIO_STT_ENGINE, - AUDIO_STT_MISTRAL_API_BASE_URL, - AUDIO_STT_MISTRAL_API_KEY, - AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS, - AUDIO_STT_MODEL, - AUDIO_STT_OPENAI_API_BASE_URL, - AUDIO_STT_OPENAI_API_KEY, - AUDIO_STT_SUPPORTED_CONTENT_TYPES, - AUDIO_TTS_API_KEY, - AUDIO_TTS_AZURE_SPEECH_BASE_URL, - AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT, - AUDIO_TTS_AZURE_SPEECH_REGION, - AUDIO_TTS_ENGINE, - AUDIO_TTS_MISTRAL_API_BASE_URL, - AUDIO_TTS_MISTRAL_API_KEY, - AUDIO_TTS_MODEL, - AUDIO_TTS_OPENAI_API_BASE_URL, - AUDIO_TTS_OPENAI_API_KEY, - AUDIO_TTS_OPENAI_PARAMS, - AUDIO_TTS_SPLIT_ON, - AUDIO_TTS_VOICE, - AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH, - AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE, - # Image - AUTOMATIC1111_API_AUTH, - AUTOMATIC1111_BASE_URL, - AUTOMATIC1111_PARAMS, - AUTOMATION_MAX_COUNT, - AUTOMATION_MIN_INTERVAL, - BING_SEARCH_V7_ENDPOINT, - BING_SEARCH_V7_SUBSCRIPTION_KEY, - BOCHA_SEARCH_API_KEY, - BRAVE_SEARCH_API_KEY, - BRAVE_SEARCH_CONTEXT_TOKENS, BYPASS_ADMIN_ACCESS_CONTROL, - BYPASS_EMBEDDING_AND_RETRIEVAL, - BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, - BYPASS_WEB_SEARCH_WEB_LOADER, CACHE_DIR, - CHUNK_MIN_SIZE_TARGET, - CHUNK_OVERLAP, - CHUNK_SIZE, - CODE_EXECUTION_ENGINE, - CODE_EXECUTION_JUPYTER_AUTH, - CODE_EXECUTION_JUPYTER_AUTH_PASSWORD, - CODE_EXECUTION_JUPYTER_AUTH_TOKEN, - CODE_EXECUTION_JUPYTER_TIMEOUT, - CODE_EXECUTION_JUPYTER_URL, - CODE_INTERPRETER_ENGINE, - CODE_INTERPRETER_JUPYTER_AUTH, - CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD, - CODE_INTERPRETER_JUPYTER_AUTH_TOKEN, - CODE_INTERPRETER_JUPYTER_TIMEOUT, - CODE_INTERPRETER_JUPYTER_URL, - CODE_INTERPRETER_PROMPT_TEMPLATE, - COMFYUI_API_KEY, - COMFYUI_BASE_URL, - COMFYUI_WORKFLOW, - COMFYUI_WORKFLOW_NODES, - CONTENT_EXTRACTION_ENGINE, CORS_ALLOW_ORIGIN, - DATALAB_MARKER_ADDITIONAL_CONFIG, - DATALAB_MARKER_API_BASE_URL, - DATALAB_MARKER_API_KEY, - DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, - DATALAB_MARKER_FORCE_OCR, - DATALAB_MARKER_FORMAT_LINES, - DATALAB_MARKER_OUTPUT_FORMAT, - DATALAB_MARKER_PAGINATE, - DATALAB_MARKER_SKIP_CACHE, - DATALAB_MARKER_STRIP_EXISTING_OCR, - DATALAB_MARKER_USE_LLM, - DDGS_BACKEND, - DEEPGRAM_API_KEY, - DEFAULT_ARENA_MODEL, - DEFAULT_GROUP_ID, DEFAULT_LOCALE, - DEFAULT_MODEL_METADATA, - DEFAULT_MODEL_PARAMS, - DEFAULT_MODELS, - DEFAULT_PINNED_MODELS, - DEFAULT_PROMPT_SUGGESTIONS, - DEFAULT_RAG_TEMPLATE, - DEFAULT_USER_ROLE, - DOCLING_API_KEY, - DOCLING_PARAMS, - DOCLING_SERVER_URL, - DOCUMENT_INTELLIGENCE_ENDPOINT, - DOCUMENT_INTELLIGENCE_KEY, - DOCUMENT_INTELLIGENCE_MODEL, ENABLE_ADMIN_ANALYTICS, # Admin ENABLE_ADMIN_CHAT_ACCESS, ENABLE_ADMIN_EXPORT, - ENABLE_API_KEYS, - ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, - ENABLE_ASYNC_EMBEDDING, - ENABLE_AUTOCOMPLETE_GENERATION, - ENABLE_AUTOMATIONS, - # Model list - ENABLE_BASE_MODELS_CACHE, - ENABLE_CALENDAR, - ENABLE_CHANNELS, - # Code Execution - ENABLE_CODE_EXECUTION, - ENABLE_CODE_INTERPRETER, - ENABLE_COMMUNITY_SHARING, - # Direct Connections - ENABLE_DIRECT_CONNECTIONS, - ENABLE_EVALUATION_ARENA_MODELS, - ENABLE_FOLDERS, - ENABLE_FOLLOW_UP_GENERATION, - ENABLE_GOOGLE_DRIVE_INTEGRATION, - ENABLE_IMAGE_EDIT, - ENABLE_IMAGE_GENERATION, - ENABLE_IMAGE_PROMPT_GENERATION, - # WebUI (LDAP) - ENABLE_LDAP, - ENABLE_LDAP_GROUP_CREATION, - # LDAP Group Management - ENABLE_LDAP_GROUP_MANAGEMENT, - ENABLE_LOGIN_FORM, - ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, - ENABLE_MEMORIES, - ENABLE_MESSAGE_RATING, - ENABLE_NOTES, - # WebUI (OAuth) - ENABLE_OAUTH_ROLE_MANAGEMENT, - # Ollama - ENABLE_OLLAMA_API, ENABLE_ONEDRIVE_BUSINESS, - ENABLE_ONEDRIVE_INTEGRATION, ENABLE_ONEDRIVE_PERSONAL, # OpenAI - ENABLE_OPENAI_API, - ENABLE_PASSWORD_CHANGE_FORM, - ENABLE_RAG_HYBRID_SEARCH, - ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, - ENABLE_RAG_LOCAL_WEB_FETCH, - ENABLE_RETRIEVAL_QUERY_GENERATION, - ENABLE_SEARCH_QUERY_GENERATION, - ENABLE_SIGNUP, - ENABLE_TAGS_GENERATION, - ENABLE_TITLE_GENERATION, - ENABLE_USER_STATUS, - ENABLE_USER_WEBHOOKS, - ENABLE_VOICE_MODE_PROMPT, - ENABLE_WEB_LOADER_SSL_VERIFICATION, - # Retrieval (Web Search) - ENABLE_WEB_SEARCH, - # Misc ENV, - EVALUATION_ARENA_MODELS, - EXA_API_KEY, - EXTERNAL_DOCUMENT_LOADER_API_KEY, - EXTERNAL_DOCUMENT_LOADER_URL, - EXTERNAL_WEB_LOADER_API_KEY, - EXTERNAL_WEB_LOADER_URL, - EXTERNAL_WEB_SEARCH_API_KEY, - EXTERNAL_WEB_SEARCH_URL, - FILE_IMAGE_COMPRESSION_HEIGHT, - FILE_IMAGE_COMPRESSION_WIDTH, - FIRECRAWL_API_BASE_URL, - FIRECRAWL_API_KEY, - FIRECRAWL_TIMEOUT, - FOLDER_MAX_FILE_COUNT, - FOLLOW_UP_GENERATION_PROMPT_TEMPLATE, FRONTEND_BUILD_DIR, GOOGLE_DRIVE_API_KEY, GOOGLE_DRIVE_CLIENT_ID, - GOOGLE_PSE_API_KEY, - GOOGLE_PSE_ENGINE_ID, IFRAME_CSP, - IMAGE_EDIT_ENGINE, - IMAGE_EDIT_MODEL, - IMAGE_EDIT_SIZE, - IMAGE_GENERATION_ENGINE, - IMAGE_GENERATION_MODEL, - IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE, - IMAGE_SIZE, - IMAGE_STEPS, - IMAGES_EDIT_COMFYUI_API_KEY, - IMAGES_EDIT_COMFYUI_BASE_URL, - IMAGES_EDIT_COMFYUI_WORKFLOW, - IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, - IMAGES_EDIT_GEMINI_API_BASE_URL, - IMAGES_EDIT_GEMINI_API_KEY, - IMAGES_EDIT_OPENAI_API_BASE_URL, - IMAGES_EDIT_OPENAI_API_KEY, - IMAGES_EDIT_OPENAI_API_VERSION, - IMAGES_GEMINI_API_BASE_URL, - IMAGES_GEMINI_API_KEY, - IMAGES_GEMINI_ENDPOINT_METHOD, - IMAGES_OPENAI_API_BASE_URL, - IMAGES_OPENAI_API_KEY, - IMAGES_OPENAI_API_PARAMS, - IMAGES_OPENAI_API_VERSION, - JINA_API_BASE_URL, - JINA_API_KEY, - JWT_EXPIRES_IN, - KAGI_SEARCH_API_KEY, - LDAP_APP_DN, - LDAP_APP_PASSWORD, - LDAP_ATTRIBUTE_FOR_GROUPS, - LDAP_ATTRIBUTE_FOR_MAIL, - LDAP_ATTRIBUTE_FOR_USERNAME, - LDAP_CA_CERT_FILE, - LDAP_CIPHERS, - LDAP_SEARCH_BASE, - LDAP_SEARCH_FILTERS, - LDAP_SERVER_HOST, - LDAP_SERVER_LABEL, - LDAP_SERVER_PORT, - LDAP_USE_TLS, - LDAP_VALIDATE_CERT, - MINERU_API_KEY, - MINERU_API_MODE, - MINERU_API_TIMEOUT, - MINERU_API_URL, - MINERU_FILE_EXTENSIONS, - MINERU_PARAMS, - MISTRAL_OCR_API_BASE_URL, - MISTRAL_OCR_API_KEY, - MODEL_ORDER_LIST, - MOJEEK_SEARCH_API_KEY, - OAUTH_ADMIN_ROLES, - OAUTH_ALLOWED_ROLES, - OAUTH_AUTO_REDIRECT, - OAUTH_EMAIL_CLAIM, - OAUTH_PICTURE_CLAIM, OAUTH_PROVIDERS, - OAUTH_ROLES_CLAIM, - OAUTH_SUB_CLAIM, - OAUTH_USERNAME_CLAIM, - OLLAMA_API_CONFIGS, - OLLAMA_BASE_URLS, - OLLAMA_CLOUD_WEB_SEARCH_API_KEY, ONEDRIVE_CLIENT_ID_BUSINESS, ONEDRIVE_CLIENT_ID_PERSONAL, ONEDRIVE_SHAREPOINT_TENANT_ID, ONEDRIVE_SHAREPOINT_URL, - OPENAI_API_BASE_URLS, - OPENAI_API_CONFIGS, - OPENAI_API_KEYS, - PADDLEOCR_VL_BASE_URL, - PADDLEOCR_VL_TOKEN, - PDF_EXTRACT_IMAGES, - PDF_LOADER_MODE, - PENDING_USER_OVERLAY_CONTENT, - PENDING_USER_OVERLAY_TITLE, - PERPLEXITY_API_KEY, - PERPLEXITY_MODEL, - PERPLEXITY_SEARCH_API_URL, - PERPLEXITY_SEARCH_CONTEXT_USAGE, - PLAYWRIGHT_TIMEOUT, - PLAYWRIGHT_WS_URL, - QUERY_GENERATION_PROMPT_TEMPLATE, - RAG_ALLOWED_FILE_EXTENSIONS, - RAG_AZURE_OPENAI_API_KEY, - RAG_AZURE_OPENAI_API_VERSION, - RAG_AZURE_OPENAI_BASE_URL, - RAG_EMBEDDING_BATCH_SIZE, - RAG_EMBEDDING_CONCURRENT_REQUESTS, - RAG_EMBEDDING_ENGINE, - RAG_EMBEDDING_MODEL, - RAG_EMBEDDING_MODEL_AUTO_UPDATE, - RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE, - RAG_EXTERNAL_RERANKER_API_KEY, - RAG_EXTERNAL_RERANKER_TIMEOUT, - RAG_EXTERNAL_RERANKER_URL, - RAG_FILE_MAX_COUNT, - RAG_FILE_MAX_SIZE, - RAG_FULL_CONTEXT, - RAG_HYBRID_BM25_WEIGHT, - RAG_OLLAMA_API_KEY, - RAG_OLLAMA_BASE_URL, - RAG_OPENAI_API_BASE_URL, - RAG_OPENAI_API_KEY, - RAG_RELEVANCE_THRESHOLD, - RAG_RERANKING_BATCH_SIZE, - RAG_RERANKING_ENGINE, - RAG_RERANKING_MODEL, - RAG_RERANKING_MODEL_AUTO_UPDATE, - RAG_RERANKING_MODEL_TRUST_REMOTE_CODE, - # Retrieval - RAG_TEMPLATE, - RAG_TEXT_SPLITTER, - RAG_TOP_K, - RAG_TOP_K_RERANKER, - RESPONSE_WATERMARK, - SEARCHAPI_API_KEY, - SEARCHAPI_ENGINE, - SEARXNG_LANGUAGE, - SEARXNG_QUERY_URL, - SERPAPI_API_KEY, - SERPAPI_ENGINE, - SERPER_API_KEY, - SERPLY_API_KEY, - SERPSTACK_API_KEY, - SERPSTACK_HTTPS, - SHOW_ADMIN_DETAILS, - SOUGOU_API_SID, - SOUGOU_API_SK, STATIC_DIR, - TAGS_GENERATION_PROMPT_TEMPLATE, - # Tasks - TASK_MODEL, - TASK_MODEL_EXTERNAL, - TAVILY_API_KEY, - TAVILY_EXTRACT_DEPTH, - # Terminal Server - TERMINAL_SERVER_CONNECTIONS, - # Thread pool size for FastAPI/AnyIO THREAD_POOL_SIZE, - TIKA_SERVER_URL, - TIKTOKEN_ENCODING_NAME, - TITLE_GENERATION_PROMPT_TEMPLATE, - # Tool Server Configs - TOOL_SERVER_CONNECTIONS, - TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, - UPLOAD_DIR, - USER_PERMISSIONS, - VOICE_MODE_PROMPT_TEMPLATE, - WEB_FETCH_MAX_CONTENT_LENGTH, - WEB_LOADER_CONCURRENT_REQUESTS, - WEB_LOADER_ENGINE, - WEB_LOADER_TIMEOUT, - WEB_SEARCH_CONCURRENT_REQUESTS, - WEB_SEARCH_DOMAIN_FILTER_LIST, - WEB_SEARCH_ENGINE, - WEB_SEARCH_RESULT_COUNT, - WEB_SEARCH_TRUST_ENV, - WEBHOOK_URL, - # WebUI WEBUI_AUTH, - WEBUI_BANNERS, WEBUI_NAME, - WEBUI_URL, - WHISPER_LANGUAGE, - WHISPER_MODEL, - WHISPER_MODEL_AUTO_UPDATE, - WHISPER_MODEL_DIR, - WHISPER_VAD_FILTER, - YACY_PASSWORD, - YACY_QUERY_URL, - YACY_USERNAME, - YANDEX_WEB_SEARCH_API_KEY, - YANDEX_WEB_SEARCH_CONFIG, - YANDEX_WEB_SEARCH_URL, - YOUCOM_API_KEY, - LINKUP_API_KEY, - LINKUP_SEARCH_PARAMS, - YOUTUBE_LOADER_LANGUAGE, - YOUTUBE_LOADER_PROXY_URL, - AppConfig, async_reset_config, - reset_config, + import_legacy_config_json, + seed_registered_defaults, ) from open_webui.constants import ERROR_MESSAGES, TASKS from open_webui.env import ( @@ -433,6 +83,7 @@ from open_webui.env import ( ENABLE_COMPRESSION_MIDDLEWARE, ENABLE_CUSTOM_MODEL_FALLBACK, ENABLE_EASTER_EGGS, + EXTERNAL_PWA_MANIFEST_URL, # OAuth Back-Channel Logout ENABLE_OAUTH_BACKCHANNEL_LOGOUT, ENABLE_OTEL, @@ -441,16 +92,15 @@ from open_webui.env import ( ENABLE_SCIM, ENABLE_SIGNUP_PASSWORD_CONFIRMATION, ENABLE_STAR_SESSIONS_MIDDLEWARE, + ENABLE_PYODIDE_FILE_PERSISTENCE, ENABLE_VERSION_UPDATE_CHECK, ENABLE_WEBSOCKET_SUPPORT, - EXTERNAL_PWA_MANIFEST_URL, GLOBAL_LOG_LEVEL, INSTANCE_ID, LICENSE_KEY, LOG_FORMAT, MAX_BODY_LOG_SIZE, # Redis - REDIS_CLUSTER, REDIS_KEY_PREFIX, REDIS_URL, RESET_CONFIG_ON_START, @@ -461,22 +111,30 @@ from open_webui.env import ( WEBUI_ADMIN_EMAIL, WEBUI_ADMIN_NAME, WEBUI_ADMIN_PASSWORD, - WEBUI_AUTH_SIGNOUT_REDIRECT_URL, WEBUI_AUTH_TRUSTED_EMAIL_HEADER, - WEBUI_AUTH_TRUSTED_NAME_HEADER, WEBUI_BUILD_HASH, WEBUI_SECRET_KEY, WEBUI_SESSION_COOKIE_SAME_SITE, WEBUI_SESSION_COOKIE_SECURE, ) -from open_webui.internal.db import ScopedSession, engine, get_async_session +from open_webui.events import ( + EVENTS, + delete_event_webhook, + get_event_catalog as get_event_catalog_items, + get_event_webhooks, + migrate_legacy_webhook_config, + publish_event, + upsert_event_webhook, +) +from open_webui.internal.db import engine, get_async_session from open_webui.models.access_grants import AccessGrants from open_webui.models.channels import Channels from open_webui.models.chats import ChatForm, Chats +from open_webui.models.config import Config from open_webui.models.functions import Functions from open_webui.models.messages import Messages from open_webui.models.models import Models -from open_webui.models.users import UserModel, Users +from open_webui.models.users import Users from open_webui.routers import ( analytics, audio, @@ -537,6 +195,7 @@ from open_webui.tasks import ( stop_task, ) # Import from tasks.py from open_webui.utils import logger +from open_webui.utils.access_control import has_permission from open_webui.utils.actions import chat_action as chat_action_handler from open_webui.utils.asgi_middleware import ( AuthTokenMiddleware, @@ -562,6 +221,7 @@ from open_webui.utils.chat import ( from open_webui.utils.embeddings import generate_embeddings from open_webui.utils.logger import start_logger from open_webui.utils.middleware import ( + background_tasks_handler, build_chat_response_context, process_chat_payload, process_chat_response, @@ -576,14 +236,16 @@ from open_webui.utils.oauth import ( OAuthClientInformationFull, OAuthClientManager, OAuthManager, + apply_connection_oauth_options, decrypt_data, encrypt_data, get_oauth_client_info_with_dynamic_client_registration, get_oauth_client_info_with_static_credentials, + recover_static_oauth_client_metadata, resolve_oauth_client_info, ) from open_webui.utils.plugin import install_tool_and_function_dependencies -from open_webui.utils.redis import get_redis_client, get_redis_connection +from open_webui.utils.redis import get_redis_client from open_webui.utils.security_headers import SecurityHeadersMiddleware from open_webui.utils.session_pool import get_session from open_webui.utils.tools import set_terminal_servers, set_tool_servers @@ -611,6 +273,13 @@ class SPAStaticFiles(StaticFiles): raise ex +class CORSStaticFiles(StaticFiles): + async def get_response(self, path: str, scope): + response = await super().get_response(path, scope) + response.headers['Access-Control-Allow-Origin'] = '*' + return response + + if LOG_FORMAT != 'json': banner = rf""" ██████╗ ██████╗ ███████╗███╗ ██╗ ██╗ ██╗███████╗██████╗ ██╗ ██╗██╗ @@ -644,6 +313,12 @@ async def lifespan(app: FastAPI): if RESET_CONFIG_ON_START: await async_reset_config() + await import_legacy_config_json() + await seed_registered_defaults() + await initialize_runtime_config(app) + await migrate_legacy_webhook_config() + await publish_event(app, EVENTS.SYSTEM_STARTUP_STARTED, source='system') + if LICENSE_KEY: get_license_data(app, LICENSE_KEY) @@ -651,7 +326,7 @@ async def lifespan(app: FastAPI): if WEBUI_ADMIN_EMAIL and WEBUI_ADMIN_PASSWORD: if await create_admin_user(WEBUI_ADMIN_EMAIL, WEBUI_ADMIN_PASSWORD, WEBUI_ADMIN_NAME): # Disable signup since we now have an admin - app.state.config.ENABLE_SIGNUP = False + await Config.upsert({'ui.enable_signup': False}) if SAFE_MODE: await Functions.deactivate_all_functions() @@ -677,7 +352,7 @@ async def lifespan(app: FastAPI): asyncio.create_task(scheduler_worker_loop(app)) - if app.state.config.ENABLE_BASE_MODELS_CACHE: + if await Config.get('models.base_models_cache'): try: await get_all_models( Request( @@ -702,7 +377,7 @@ async def lifespan(app: FastAPI): log.warning(f'Failed to pre-fetch models at startup: {e}') # Pre-fetch tool server specs so the first request doesn't pay the latency cost - if len(app.state.config.TOOL_SERVER_CONNECTIONS) > 0: + if len(await Config.get('tool_server.connections', []) or []) > 0: mock_request = Request( { 'type': 'http', @@ -734,9 +409,12 @@ async def lifespan(app: FastAPI): # Mark application as ready to accept traffic from a startup perspective. app.state.startup_complete = True + await publish_event(app, EVENTS.SYSTEM_STARTUP_COMPLETED, source='system') yield + await publish_event(app, EVENTS.SYSTEM_SHUTDOWN_STARTED, source='system') + # Shutdown: clean up shared resources from open_webui.utils.session_pool import close_session @@ -745,6 +423,8 @@ async def lifespan(app: FastAPI): if hasattr(app.state, 'redis_task_command_listener'): app.state.redis_task_command_listener.cancel() + await publish_event(app, EVENTS.SYSTEM_SHUTDOWN_COMPLETED, source='system') + app = FastAPI( title='Open WebUI', @@ -766,15 +446,12 @@ oauth_client_manager = OAuthClientManager(app) app.state.oauth_client_manager = oauth_client_manager app.state.instance_id = None -app.state.config = AppConfig( - redis_url=REDIS_URL, - redis_cluster=REDIS_CLUSTER, - redis_key_prefix=REDIS_KEY_PREFIX, -) app.state.redis = None app.state.WEBUI_NAME = WEBUI_NAME app.state.LICENSE_METADATA = None +app.state.USER_COUNT = None +app.state.EXTERNAL_PWA_MANIFEST_URL = EXTERNAL_PWA_MANIFEST_URL ######################################## @@ -796,10 +473,6 @@ if ENABLE_OTEL: ######################################## -app.state.config.ENABLE_OLLAMA_API = ENABLE_OLLAMA_API -app.state.config.OLLAMA_BASE_URLS = OLLAMA_BASE_URLS -app.state.config.OLLAMA_API_CONFIGS = OLLAMA_API_CONFIGS - app.state.OLLAMA_MODELS = {} ######################################## @@ -808,10 +481,6 @@ app.state.OLLAMA_MODELS = {} # ######################################## -app.state.config.ENABLE_OPENAI_API = ENABLE_OPENAI_API -app.state.config.OPENAI_API_BASE_URLS = OPENAI_API_BASE_URLS -app.state.config.OPENAI_API_KEYS = OPENAI_API_KEYS -app.state.config.OPENAI_API_CONFIGS = OPENAI_API_CONFIGS app.state.OPENAI_MODELS = {} @@ -821,7 +490,6 @@ app.state.OPENAI_MODELS = {} # ######################################## -app.state.config.TOOL_SERVER_CONNECTIONS = TOOL_SERVER_CONNECTIONS app.state.TOOL_SERVERS = [] ######################################## @@ -830,7 +498,6 @@ app.state.TOOL_SERVERS = [] # ######################################## -app.state.config.TERMINAL_SERVER_CONNECTIONS = TERMINAL_SERVER_CONNECTIONS app.state.TERMINAL_SERVERS = [] ######################################## @@ -839,7 +506,6 @@ app.state.TERMINAL_SERVERS = [] # ######################################## -app.state.config.ENABLE_DIRECT_CONNECTIONS = ENABLE_DIRECT_CONNECTIONS ######################################## # @@ -856,7 +522,6 @@ app.state.SCIM_TOKEN = SCIM_TOKEN # ######################################## -app.state.config.ENABLE_BASE_MODELS_CACHE = ENABLE_BASE_MODELS_CACHE app.state.BASE_MODELS = [] ######################################## @@ -865,352 +530,130 @@ app.state.BASE_MODELS = [] # ######################################## -app.state.config.WEBUI_URL = WEBUI_URL -app.state.config.ENABLE_SIGNUP = ENABLE_SIGNUP -app.state.config.ENABLE_LOGIN_FORM = ENABLE_LOGIN_FORM -app.state.config.OAUTH_AUTO_REDIRECT = OAUTH_AUTO_REDIRECT -app.state.config.ENABLE_PASSWORD_CHANGE_FORM = ENABLE_PASSWORD_CHANGE_FORM -app.state.config.ENABLE_API_KEYS = ENABLE_API_KEYS -app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS = ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS -app.state.config.API_KEYS_ALLOWED_ENDPOINTS = API_KEYS_ALLOWED_ENDPOINTS +async def initialize_runtime_config(app: FastAPI): + # Migrate legacy access_control → access_grants on boot. + from open_webui.utils.access_control import migrate_access_control -app.state.config.JWT_EXPIRES_IN = JWT_EXPIRES_IN + connections = await Config.get('tool_server.connections', []) or [] + if any('access_control' in c.get('config', {}) for c in connections): + for connection in connections: + migrate_access_control(connection.get('config', {})) + await Config.upsert({'tool_server.connections': connections}) -app.state.config.SHOW_ADMIN_DETAILS = SHOW_ADMIN_DETAILS -app.state.config.ADMIN_EMAIL = ADMIN_EMAIL + for tool_server_connection in connections: + if tool_server_connection.get('type', 'openapi') == 'mcp': + server_id = (tool_server_connection.get('info') or {}).get('id') + auth_type = tool_server_connection.get('auth_type', 'none') + if server_id and auth_type in ('oauth_2.1', 'oauth_2.1_static'): + try: + oauth_client_info = resolve_oauth_client_info(tool_server_connection) + oauth_client_info = await recover_static_oauth_client_metadata( + tool_server_connection, oauth_client_info + ) + oauth_client_info = apply_connection_oauth_options(tool_server_connection, oauth_client_info) + app.state.oauth_client_manager.add_client( + f'mcp:{server_id}', + OAuthClientInformationFull(**oauth_client_info), + ) + except Exception as e: + log.error(f'Error adding OAuth client for MCP tool server {server_id}: {e}') -app.state.config.DEFAULT_MODELS = DEFAULT_MODELS -app.state.config.DEFAULT_PINNED_MODELS = DEFAULT_PINNED_MODELS -app.state.config.MODEL_ORDER_LIST = MODEL_ORDER_LIST -app.state.config.DEFAULT_MODEL_METADATA = DEFAULT_MODEL_METADATA -app.state.config.DEFAULT_MODEL_PARAMS = DEFAULT_MODEL_PARAMS + arena_models = await Config.get('evaluation.arena.models', []) or [] + if any('access_control' in m.get('meta', {}) for m in arena_models): + for model in arena_models: + migrate_access_control(model.get('meta', {})) + await Config.upsert({'evaluation.arena.models': arena_models}) + app.state.EMBEDDING_FUNCTION = None + app.state.RERANKING_FUNCTION = None + app.state.ef = None + app.state.rf = None + app.state.YOUTUBE_LOADER_TRANSLATION = None -app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS -app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE -app.state.config.DEFAULT_GROUP_ID = DEFAULT_GROUP_ID - -app.state.config.PENDING_USER_OVERLAY_CONTENT = PENDING_USER_OVERLAY_CONTENT -app.state.config.PENDING_USER_OVERLAY_TITLE = PENDING_USER_OVERLAY_TITLE - -app.state.config.RESPONSE_WATERMARK = RESPONSE_WATERMARK - -app.state.config.USER_PERMISSIONS = USER_PERMISSIONS -app.state.config.WEBHOOK_URL = WEBHOOK_URL -app.state.config.BANNERS = WEBUI_BANNERS - - -app.state.config.ENABLE_FOLDERS = ENABLE_FOLDERS -app.state.config.FOLDER_MAX_FILE_COUNT = FOLDER_MAX_FILE_COUNT -app.state.config.ENABLE_AUTOMATIONS = ENABLE_AUTOMATIONS -app.state.config.AUTOMATION_MAX_COUNT = AUTOMATION_MAX_COUNT -app.state.config.AUTOMATION_MIN_INTERVAL = AUTOMATION_MIN_INTERVAL -app.state.config.ENABLE_CHANNELS = ENABLE_CHANNELS -app.state.config.ENABLE_CALENDAR = ENABLE_CALENDAR -app.state.config.ENABLE_NOTES = ENABLE_NOTES -app.state.config.ENABLE_COMMUNITY_SHARING = ENABLE_COMMUNITY_SHARING -app.state.config.ENABLE_MESSAGE_RATING = ENABLE_MESSAGE_RATING -app.state.config.ENABLE_USER_WEBHOOKS = ENABLE_USER_WEBHOOKS -app.state.config.ENABLE_USER_STATUS = ENABLE_USER_STATUS - -app.state.config.ENABLE_EVALUATION_ARENA_MODELS = ENABLE_EVALUATION_ARENA_MODELS -app.state.config.EVALUATION_ARENA_MODELS = EVALUATION_ARENA_MODELS - -# Migrate legacy access_control → access_grants on boot -from open_webui.utils.access_control import has_permission, migrate_access_control - -connections = app.state.config.TOOL_SERVER_CONNECTIONS -if any('access_control' in c.get('config', {}) for c in connections): - for connection in connections: - migrate_access_control(connection.get('config', {})) - app.state.config.TOOL_SERVER_CONNECTIONS = connections - -arena_models = app.state.config.EVALUATION_ARENA_MODELS -if any('access_control' in m.get('meta', {}) for m in arena_models): - for model in arena_models: - migrate_access_control(model.get('meta', {})) - app.state.config.EVALUATION_ARENA_MODELS = arena_models - -app.state.config.OAUTH_SUB_CLAIM = OAUTH_SUB_CLAIM -app.state.config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM -app.state.config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM -app.state.config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM - -app.state.config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT -app.state.config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM -app.state.config.OAUTH_ALLOWED_ROLES = OAUTH_ALLOWED_ROLES -app.state.config.OAUTH_ADMIN_ROLES = OAUTH_ADMIN_ROLES - -app.state.config.ENABLE_LDAP = ENABLE_LDAP -app.state.config.LDAP_SERVER_LABEL = LDAP_SERVER_LABEL -app.state.config.LDAP_SERVER_HOST = LDAP_SERVER_HOST -app.state.config.LDAP_SERVER_PORT = LDAP_SERVER_PORT -app.state.config.LDAP_ATTRIBUTE_FOR_MAIL = LDAP_ATTRIBUTE_FOR_MAIL -app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME = LDAP_ATTRIBUTE_FOR_USERNAME -app.state.config.LDAP_APP_DN = LDAP_APP_DN -app.state.config.LDAP_APP_PASSWORD = LDAP_APP_PASSWORD -app.state.config.LDAP_SEARCH_BASE = LDAP_SEARCH_BASE -app.state.config.LDAP_SEARCH_FILTERS = LDAP_SEARCH_FILTERS -app.state.config.LDAP_USE_TLS = LDAP_USE_TLS -app.state.config.LDAP_CA_CERT_FILE = LDAP_CA_CERT_FILE -app.state.config.LDAP_VALIDATE_CERT = LDAP_VALIDATE_CERT -app.state.config.LDAP_CIPHERS = LDAP_CIPHERS - -# For LDAP Group Management -app.state.config.ENABLE_LDAP_GROUP_MANAGEMENT = ENABLE_LDAP_GROUP_MANAGEMENT -app.state.config.ENABLE_LDAP_GROUP_CREATION = ENABLE_LDAP_GROUP_CREATION -app.state.config.LDAP_ATTRIBUTE_FOR_GROUPS = LDAP_ATTRIBUTE_FOR_GROUPS - - -app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER -app.state.AUTH_TRUSTED_NAME_HEADER = WEBUI_AUTH_TRUSTED_NAME_HEADER -app.state.WEBUI_AUTH_SIGNOUT_REDIRECT_URL = WEBUI_AUTH_SIGNOUT_REDIRECT_URL -app.state.EXTERNAL_PWA_MANIFEST_URL = EXTERNAL_PWA_MANIFEST_URL - -app.state.USER_COUNT = None - -app.state.TOOLS = {} -app.state.TOOL_CONTENTS = {} - -app.state.FUNCTIONS = {} -app.state.FUNCTION_CONTENTS = {} - -######################################## -# -# RETRIEVAL -# -######################################## - - -app.state.config.TOP_K = RAG_TOP_K -app.state.config.TOP_K_RERANKER = RAG_TOP_K_RERANKER -app.state.config.RELEVANCE_THRESHOLD = RAG_RELEVANCE_THRESHOLD -app.state.config.HYBRID_BM25_WEIGHT = RAG_HYBRID_BM25_WEIGHT - - -app.state.config.ALLOWED_FILE_EXTENSIONS = RAG_ALLOWED_FILE_EXTENSIONS -app.state.config.FILE_MAX_SIZE = RAG_FILE_MAX_SIZE -app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT -app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = FILE_IMAGE_COMPRESSION_WIDTH -app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = FILE_IMAGE_COMPRESSION_HEIGHT - - -app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT -app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = BYPASS_EMBEDDING_AND_RETRIEVAL -app.state.config.ENABLE_RAG_HYBRID_SEARCH = ENABLE_RAG_HYBRID_SEARCH -app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS -app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION = ENABLE_WEB_LOADER_SSL_VERIFICATION - -app.state.config.CONTENT_EXTRACTION_ENGINE = CONTENT_EXTRACTION_ENGINE -app.state.config.DATALAB_MARKER_API_KEY = DATALAB_MARKER_API_KEY -app.state.config.DATALAB_MARKER_API_BASE_URL = DATALAB_MARKER_API_BASE_URL -app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG = DATALAB_MARKER_ADDITIONAL_CONFIG -app.state.config.DATALAB_MARKER_SKIP_CACHE = DATALAB_MARKER_SKIP_CACHE -app.state.config.DATALAB_MARKER_FORCE_OCR = DATALAB_MARKER_FORCE_OCR -app.state.config.DATALAB_MARKER_PAGINATE = DATALAB_MARKER_PAGINATE -app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR = DATALAB_MARKER_STRIP_EXISTING_OCR -app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION -app.state.config.DATALAB_MARKER_FORMAT_LINES = DATALAB_MARKER_FORMAT_LINES -app.state.config.DATALAB_MARKER_USE_LLM = DATALAB_MARKER_USE_LLM -app.state.config.DATALAB_MARKER_OUTPUT_FORMAT = DATALAB_MARKER_OUTPUT_FORMAT -app.state.config.EXTERNAL_DOCUMENT_LOADER_URL = EXTERNAL_DOCUMENT_LOADER_URL -app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY = EXTERNAL_DOCUMENT_LOADER_API_KEY -app.state.config.TIKA_SERVER_URL = TIKA_SERVER_URL -app.state.config.DOCLING_SERVER_URL = DOCLING_SERVER_URL -app.state.config.DOCLING_API_KEY = DOCLING_API_KEY -app.state.config.DOCLING_PARAMS = DOCLING_PARAMS -app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT = DOCUMENT_INTELLIGENCE_ENDPOINT -app.state.config.DOCUMENT_INTELLIGENCE_KEY = DOCUMENT_INTELLIGENCE_KEY -app.state.config.DOCUMENT_INTELLIGENCE_MODEL = DOCUMENT_INTELLIGENCE_MODEL -app.state.config.MISTRAL_OCR_API_BASE_URL = MISTRAL_OCR_API_BASE_URL -app.state.config.MISTRAL_OCR_API_KEY = MISTRAL_OCR_API_KEY -app.state.config.PADDLEOCR_VL_BASE_URL = PADDLEOCR_VL_BASE_URL -app.state.config.PADDLEOCR_VL_TOKEN = PADDLEOCR_VL_TOKEN -app.state.config.MINERU_API_MODE = MINERU_API_MODE -app.state.config.MINERU_API_URL = MINERU_API_URL -app.state.config.MINERU_API_KEY = MINERU_API_KEY -app.state.config.MINERU_API_TIMEOUT = MINERU_API_TIMEOUT -app.state.config.MINERU_PARAMS = MINERU_PARAMS -app.state.config.MINERU_FILE_EXTENSIONS = MINERU_FILE_EXTENSIONS - -app.state.config.TEXT_SPLITTER = RAG_TEXT_SPLITTER -app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER - -app.state.config.TIKTOKEN_ENCODING_NAME = TIKTOKEN_ENCODING_NAME - -app.state.config.CHUNK_SIZE = CHUNK_SIZE -app.state.config.CHUNK_MIN_SIZE_TARGET = CHUNK_MIN_SIZE_TARGET -app.state.config.CHUNK_OVERLAP = CHUNK_OVERLAP - - -app.state.config.RAG_EMBEDDING_ENGINE = RAG_EMBEDDING_ENGINE -app.state.config.RAG_EMBEDDING_MODEL = RAG_EMBEDDING_MODEL -app.state.config.RAG_EMBEDDING_BATCH_SIZE = RAG_EMBEDDING_BATCH_SIZE -app.state.config.ENABLE_ASYNC_EMBEDDING = ENABLE_ASYNC_EMBEDDING -app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS = RAG_EMBEDDING_CONCURRENT_REQUESTS - -app.state.config.RAG_RERANKING_ENGINE = RAG_RERANKING_ENGINE -app.state.config.RAG_RERANKING_MODEL = RAG_RERANKING_MODEL -app.state.config.RAG_EXTERNAL_RERANKER_URL = RAG_EXTERNAL_RERANKER_URL -app.state.config.RAG_EXTERNAL_RERANKER_API_KEY = RAG_EXTERNAL_RERANKER_API_KEY -app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT = RAG_EXTERNAL_RERANKER_TIMEOUT -app.state.config.RAG_RERANKING_BATCH_SIZE = RAG_RERANKING_BATCH_SIZE - -app.state.config.RAG_TEMPLATE = RAG_TEMPLATE - -app.state.config.RAG_OPENAI_API_BASE_URL = RAG_OPENAI_API_BASE_URL -app.state.config.RAG_OPENAI_API_KEY = RAG_OPENAI_API_KEY - -app.state.config.RAG_AZURE_OPENAI_BASE_URL = RAG_AZURE_OPENAI_BASE_URL -app.state.config.RAG_AZURE_OPENAI_API_KEY = RAG_AZURE_OPENAI_API_KEY -app.state.config.RAG_AZURE_OPENAI_API_VERSION = RAG_AZURE_OPENAI_API_VERSION - -app.state.config.RAG_OLLAMA_BASE_URL = RAG_OLLAMA_BASE_URL -app.state.config.RAG_OLLAMA_API_KEY = RAG_OLLAMA_API_KEY - -app.state.config.PDF_EXTRACT_IMAGES = PDF_EXTRACT_IMAGES -app.state.config.PDF_LOADER_MODE = PDF_LOADER_MODE - -app.state.config.YOUTUBE_LOADER_LANGUAGE = YOUTUBE_LOADER_LANGUAGE -app.state.config.YOUTUBE_LOADER_PROXY_URL = YOUTUBE_LOADER_PROXY_URL - - -app.state.config.ENABLE_WEB_SEARCH = ENABLE_WEB_SEARCH -app.state.config.WEB_SEARCH_ENGINE = WEB_SEARCH_ENGINE -app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST = WEB_SEARCH_DOMAIN_FILTER_LIST -app.state.config.WEB_SEARCH_RESULT_COUNT = WEB_SEARCH_RESULT_COUNT -app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS = WEB_SEARCH_CONCURRENT_REQUESTS -app.state.config.WEB_FETCH_MAX_CONTENT_LENGTH = WEB_FETCH_MAX_CONTENT_LENGTH - -app.state.config.WEB_LOADER_ENGINE = WEB_LOADER_ENGINE -app.state.config.WEB_LOADER_CONCURRENT_REQUESTS = WEB_LOADER_CONCURRENT_REQUESTS -app.state.config.WEB_LOADER_TIMEOUT = WEB_LOADER_TIMEOUT - -app.state.config.WEB_SEARCH_TRUST_ENV = WEB_SEARCH_TRUST_ENV -app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL -app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER = BYPASS_WEB_SEARCH_WEB_LOADER - -app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION -app.state.config.ENABLE_ONEDRIVE_INTEGRATION = ENABLE_ONEDRIVE_INTEGRATION - -app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY = OLLAMA_CLOUD_WEB_SEARCH_API_KEY -app.state.config.SEARXNG_QUERY_URL = SEARXNG_QUERY_URL -app.state.config.SEARXNG_LANGUAGE = SEARXNG_LANGUAGE -app.state.config.YACY_QUERY_URL = YACY_QUERY_URL -app.state.config.YACY_USERNAME = YACY_USERNAME -app.state.config.YACY_PASSWORD = YACY_PASSWORD -app.state.config.GOOGLE_PSE_API_KEY = GOOGLE_PSE_API_KEY -app.state.config.GOOGLE_PSE_ENGINE_ID = GOOGLE_PSE_ENGINE_ID -app.state.config.BRAVE_SEARCH_API_KEY = BRAVE_SEARCH_API_KEY -app.state.config.BRAVE_SEARCH_CONTEXT_TOKENS = BRAVE_SEARCH_CONTEXT_TOKENS -app.state.config.KAGI_SEARCH_API_KEY = KAGI_SEARCH_API_KEY -app.state.config.MOJEEK_SEARCH_API_KEY = MOJEEK_SEARCH_API_KEY -app.state.config.BOCHA_SEARCH_API_KEY = BOCHA_SEARCH_API_KEY -app.state.config.SERPSTACK_API_KEY = SERPSTACK_API_KEY -app.state.config.SERPSTACK_HTTPS = SERPSTACK_HTTPS -app.state.config.SERPER_API_KEY = SERPER_API_KEY -app.state.config.SERPLY_API_KEY = SERPLY_API_KEY -app.state.config.DDGS_BACKEND = DDGS_BACKEND -app.state.config.TAVILY_API_KEY = TAVILY_API_KEY -app.state.config.SEARCHAPI_API_KEY = SEARCHAPI_API_KEY -app.state.config.SEARCHAPI_ENGINE = SEARCHAPI_ENGINE -app.state.config.SERPAPI_API_KEY = SERPAPI_API_KEY -app.state.config.SERPAPI_ENGINE = SERPAPI_ENGINE -app.state.config.JINA_API_KEY = JINA_API_KEY -app.state.config.JINA_API_BASE_URL = JINA_API_BASE_URL -app.state.config.BING_SEARCH_V7_ENDPOINT = BING_SEARCH_V7_ENDPOINT -app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = BING_SEARCH_V7_SUBSCRIPTION_KEY -app.state.config.EXA_API_KEY = EXA_API_KEY -app.state.config.PERPLEXITY_API_KEY = PERPLEXITY_API_KEY -app.state.config.PERPLEXITY_MODEL = PERPLEXITY_MODEL -app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = PERPLEXITY_SEARCH_CONTEXT_USAGE -app.state.config.PERPLEXITY_SEARCH_API_URL = PERPLEXITY_SEARCH_API_URL -app.state.config.SOUGOU_API_SID = SOUGOU_API_SID -app.state.config.SOUGOU_API_SK = SOUGOU_API_SK -app.state.config.EXTERNAL_WEB_SEARCH_URL = EXTERNAL_WEB_SEARCH_URL -app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = EXTERNAL_WEB_SEARCH_API_KEY -app.state.config.EXTERNAL_WEB_LOADER_URL = EXTERNAL_WEB_LOADER_URL -app.state.config.EXTERNAL_WEB_LOADER_API_KEY = EXTERNAL_WEB_LOADER_API_KEY -app.state.config.YANDEX_WEB_SEARCH_URL = YANDEX_WEB_SEARCH_URL -app.state.config.YANDEX_WEB_SEARCH_API_KEY = YANDEX_WEB_SEARCH_API_KEY -app.state.config.YANDEX_WEB_SEARCH_CONFIG = YANDEX_WEB_SEARCH_CONFIG -app.state.config.YOUCOM_API_KEY = YOUCOM_API_KEY -app.state.config.LINKUP_API_KEY = LINKUP_API_KEY -app.state.config.LINKUP_SEARCH_PARAMS = LINKUP_SEARCH_PARAMS - - -app.state.config.PLAYWRIGHT_WS_URL = PLAYWRIGHT_WS_URL -app.state.config.PLAYWRIGHT_TIMEOUT = PLAYWRIGHT_TIMEOUT -app.state.config.FIRECRAWL_API_BASE_URL = FIRECRAWL_API_BASE_URL -app.state.config.FIRECRAWL_API_KEY = FIRECRAWL_API_KEY -app.state.config.FIRECRAWL_TIMEOUT = FIRECRAWL_TIMEOUT -app.state.config.TAVILY_EXTRACT_DEPTH = TAVILY_EXTRACT_DEPTH - -app.state.EMBEDDING_FUNCTION = None -app.state.RERANKING_FUNCTION = None -app.state.ef = None -app.state.rf = None - -app.state.YOUTUBE_LOADER_TRANSLATION = None - - -try: - app.state.ef = get_ef(app.state.config.RAG_EMBEDDING_ENGINE, app.state.config.RAG_EMBEDDING_MODEL) - if app.state.config.ENABLE_RAG_HYBRID_SEARCH and not app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL: - app.state.rf = get_rf( - app.state.config.RAG_RERANKING_ENGINE, - app.state.config.RAG_RERANKING_MODEL, - app.state.config.RAG_EXTERNAL_RERANKER_URL, - app.state.config.RAG_EXTERNAL_RERANKER_API_KEY, - app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT, + try: + rag_config = await Config.get_many( + 'rag.embedding_engine', + 'rag.embedding_model', + 'rag.enable_hybrid_search', + 'rag.bypass_embedding_and_retrieval', + 'rag.reranking_engine', + 'rag.reranking_model', + 'rag.external_reranker_url', + 'rag.external_reranker_api_key', + 'rag.external_reranker_timeout', ) - else: + app.state.ef = get_ef(rag_config.get('rag.embedding_engine'), rag_config.get('rag.embedding_model')) + if rag_config.get('rag.enable_hybrid_search') and not rag_config.get('rag.bypass_embedding_and_retrieval'): + app.state.rf = get_rf( + rag_config.get('rag.reranking_engine'), + rag_config.get('rag.reranking_model'), + rag_config.get('rag.external_reranker_url'), + rag_config.get('rag.external_reranker_api_key'), + rag_config.get('rag.external_reranker_timeout'), + ) + else: + app.state.rf = None + except Exception as e: + log.error(f'Error updating models: {e}') app.state.rf = None -except Exception as e: - log.error(f'Error updating models: {e}') - pass + rag_config = await Config.get_many( + 'rag.embedding_engine', + 'rag.embedding_model', + 'rag.openai.api_base_url', + 'rag.ollama.base_url', + 'rag.azure_openai.base_url', + 'rag.openai.api_key', + 'rag.ollama.api_key', + 'rag.azure_openai.api_key', + 'rag.embedding_batch_size', + 'rag.azure_openai.api_version', + 'rag.enable_async_embedding', + 'rag.embedding_concurrent_requests', + 'rag.reranking_engine', + 'rag.reranking_model', + 'rag.reranking_batch_size', + ) + embedding_engine = rag_config.get('rag.embedding_engine') + app.state.EMBEDDING_FUNCTION = get_embedding_function( + embedding_engine, + rag_config.get('rag.embedding_model'), + embedding_function=app.state.ef, + url=( + rag_config.get('rag.openai.api_base_url') + if embedding_engine == 'openai' + else ( + rag_config.get('rag.ollama.base_url') + if embedding_engine == 'ollama' + else rag_config.get('rag.azure_openai.base_url') + ) + ), + key=( + rag_config.get('rag.openai.api_key') + if embedding_engine == 'openai' + else ( + rag_config.get('rag.ollama.api_key') + if embedding_engine == 'ollama' + else rag_config.get('rag.azure_openai.api_key') + ) + ), + embedding_batch_size=rag_config.get('rag.embedding_batch_size'), + azure_api_version=( + rag_config.get('rag.azure_openai.api_version') if embedding_engine == 'azure_openai' else None + ), + enable_async=rag_config.get('rag.enable_async_embedding'), + concurrent_requests=rag_config.get('rag.embedding_concurrent_requests'), + ) -app.state.EMBEDDING_FUNCTION = get_embedding_function( - app.state.config.RAG_EMBEDDING_ENGINE, - app.state.config.RAG_EMBEDDING_MODEL, - embedding_function=app.state.ef, - url=( - app.state.config.RAG_OPENAI_API_BASE_URL - if app.state.config.RAG_EMBEDDING_ENGINE == 'openai' - else ( - app.state.config.RAG_OLLAMA_BASE_URL - if app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else app.state.config.RAG_AZURE_OPENAI_BASE_URL - ) - ), - key=( - app.state.config.RAG_OPENAI_API_KEY - if app.state.config.RAG_EMBEDDING_ENGINE == 'openai' - else ( - app.state.config.RAG_OLLAMA_API_KEY - if app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else app.state.config.RAG_AZURE_OPENAI_API_KEY - ) - ), - embedding_batch_size=app.state.config.RAG_EMBEDDING_BATCH_SIZE, - azure_api_version=( - app.state.config.RAG_AZURE_OPENAI_API_VERSION - if app.state.config.RAG_EMBEDDING_ENGINE == 'azure_openai' - else None - ), - enable_async=app.state.config.ENABLE_ASYNC_EMBEDDING, - concurrent_requests=app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS, -) + app.state.RERANKING_FUNCTION = get_reranking_function( + rag_config.get('rag.reranking_engine'), + rag_config.get('rag.reranking_model'), + reranking_function=app.state.rf, + reranking_batch_size=rag_config.get('rag.reranking_batch_size'), + ) -app.state.RERANKING_FUNCTION = get_reranking_function( - app.state.config.RAG_RERANKING_ENGINE, - app.state.config.RAG_RERANKING_MODEL, - reranking_function=app.state.rf, - reranking_batch_size=app.state.config.RAG_RERANKING_BATCH_SIZE, -) ######################################## # @@ -1218,23 +661,6 @@ app.state.RERANKING_FUNCTION = get_reranking_function( # ######################################## -app.state.config.ENABLE_CODE_EXECUTION = ENABLE_CODE_EXECUTION -app.state.config.CODE_EXECUTION_ENGINE = CODE_EXECUTION_ENGINE -app.state.config.CODE_EXECUTION_JUPYTER_URL = CODE_EXECUTION_JUPYTER_URL -app.state.config.CODE_EXECUTION_JUPYTER_AUTH = CODE_EXECUTION_JUPYTER_AUTH -app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN = CODE_EXECUTION_JUPYTER_AUTH_TOKEN -app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = CODE_EXECUTION_JUPYTER_AUTH_PASSWORD -app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT = CODE_EXECUTION_JUPYTER_TIMEOUT - -app.state.config.ENABLE_CODE_INTERPRETER = ENABLE_CODE_INTERPRETER -app.state.config.CODE_INTERPRETER_ENGINE = CODE_INTERPRETER_ENGINE -app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = CODE_INTERPRETER_PROMPT_TEMPLATE - -app.state.config.CODE_INTERPRETER_JUPYTER_URL = CODE_INTERPRETER_JUPYTER_URL -app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = CODE_INTERPRETER_JUPYTER_AUTH -app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = CODE_INTERPRETER_JUPYTER_AUTH_TOKEN -app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD -app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIMEOUT ######################################## # @@ -1242,48 +668,6 @@ app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = CODE_INTERPRETER_JUPYTER_TIM # ######################################## -app.state.config.IMAGE_GENERATION_ENGINE = IMAGE_GENERATION_ENGINE -app.state.config.ENABLE_IMAGE_GENERATION = ENABLE_IMAGE_GENERATION -app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = ENABLE_IMAGE_PROMPT_GENERATION -app.state.config.ENABLE_MEMORIES = ENABLE_MEMORIES - -app.state.config.IMAGE_GENERATION_MODEL = IMAGE_GENERATION_MODEL -app.state.config.IMAGE_SIZE = IMAGE_SIZE -app.state.config.IMAGE_STEPS = IMAGE_STEPS - -app.state.config.IMAGES_OPENAI_API_BASE_URL = IMAGES_OPENAI_API_BASE_URL -app.state.config.IMAGES_OPENAI_API_VERSION = IMAGES_OPENAI_API_VERSION -app.state.config.IMAGES_OPENAI_API_KEY = IMAGES_OPENAI_API_KEY -app.state.config.IMAGES_OPENAI_API_PARAMS = IMAGES_OPENAI_API_PARAMS - -app.state.config.IMAGES_GEMINI_API_BASE_URL = IMAGES_GEMINI_API_BASE_URL -app.state.config.IMAGES_GEMINI_API_KEY = IMAGES_GEMINI_API_KEY -app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD = IMAGES_GEMINI_ENDPOINT_METHOD - -app.state.config.AUTOMATIC1111_BASE_URL = AUTOMATIC1111_BASE_URL -app.state.config.AUTOMATIC1111_API_AUTH = AUTOMATIC1111_API_AUTH -app.state.config.AUTOMATIC1111_PARAMS = AUTOMATIC1111_PARAMS - -app.state.config.COMFYUI_BASE_URL = COMFYUI_BASE_URL -app.state.config.COMFYUI_API_KEY = COMFYUI_API_KEY -app.state.config.COMFYUI_WORKFLOW = COMFYUI_WORKFLOW -app.state.config.COMFYUI_WORKFLOW_NODES = COMFYUI_WORKFLOW_NODES - - -app.state.config.ENABLE_IMAGE_EDIT = ENABLE_IMAGE_EDIT -app.state.config.IMAGE_EDIT_ENGINE = IMAGE_EDIT_ENGINE -app.state.config.IMAGE_EDIT_MODEL = IMAGE_EDIT_MODEL -app.state.config.IMAGE_EDIT_SIZE = IMAGE_EDIT_SIZE -app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL = IMAGES_EDIT_OPENAI_API_BASE_URL -app.state.config.IMAGES_EDIT_OPENAI_API_KEY = IMAGES_EDIT_OPENAI_API_KEY -app.state.config.IMAGES_EDIT_OPENAI_API_VERSION = IMAGES_EDIT_OPENAI_API_VERSION -app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL = IMAGES_EDIT_GEMINI_API_BASE_URL -app.state.config.IMAGES_EDIT_GEMINI_API_KEY = IMAGES_EDIT_GEMINI_API_KEY -app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL = IMAGES_EDIT_COMFYUI_BASE_URL -app.state.config.IMAGES_EDIT_COMFYUI_API_KEY = IMAGES_EDIT_COMFYUI_API_KEY -app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW = IMAGES_EDIT_COMFYUI_WORKFLOW -app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = IMAGES_EDIT_COMFYUI_WORKFLOW_NODES - ######################################## # @@ -1291,47 +675,6 @@ app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = IMAGES_EDIT_COMFYUI_WORKFL # ######################################## -app.state.config.STT_ENGINE = AUDIO_STT_ENGINE -app.state.config.STT_MODEL = AUDIO_STT_MODEL -app.state.config.STT_SUPPORTED_CONTENT_TYPES = AUDIO_STT_SUPPORTED_CONTENT_TYPES -app.state.config.STT_ALLOWED_EXTENSIONS = AUDIO_STT_ALLOWED_EXTENSIONS - -app.state.config.STT_OPENAI_API_BASE_URL = AUDIO_STT_OPENAI_API_BASE_URL -app.state.config.STT_OPENAI_API_KEY = AUDIO_STT_OPENAI_API_KEY - -app.state.config.WHISPER_MODEL = WHISPER_MODEL -app.state.config.DEEPGRAM_API_KEY = DEEPGRAM_API_KEY - -app.state.config.AUDIO_STT_AZURE_API_KEY = AUDIO_STT_AZURE_API_KEY -app.state.config.AUDIO_STT_AZURE_REGION = AUDIO_STT_AZURE_REGION -app.state.config.AUDIO_STT_AZURE_LOCALES = AUDIO_STT_AZURE_LOCALES -app.state.config.AUDIO_STT_AZURE_BASE_URL = AUDIO_STT_AZURE_BASE_URL -app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS = AUDIO_STT_AZURE_MAX_SPEAKERS - -app.state.config.AUDIO_STT_MISTRAL_API_KEY = AUDIO_STT_MISTRAL_API_KEY -app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL = AUDIO_STT_MISTRAL_API_BASE_URL -app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS - -app.state.config.TTS_ENGINE = AUDIO_TTS_ENGINE - -app.state.config.TTS_MODEL = AUDIO_TTS_MODEL -app.state.config.TTS_VOICE = AUDIO_TTS_VOICE - -app.state.config.TTS_OPENAI_API_BASE_URL = AUDIO_TTS_OPENAI_API_BASE_URL -app.state.config.TTS_OPENAI_API_KEY = AUDIO_TTS_OPENAI_API_KEY -app.state.config.TTS_OPENAI_PARAMS = AUDIO_TTS_OPENAI_PARAMS - -app.state.config.TTS_API_KEY = AUDIO_TTS_API_KEY -app.state.config.TTS_SPLIT_ON = AUDIO_TTS_SPLIT_ON - - -app.state.config.TTS_AZURE_SPEECH_REGION = AUDIO_TTS_AZURE_SPEECH_REGION -app.state.config.TTS_AZURE_SPEECH_BASE_URL = AUDIO_TTS_AZURE_SPEECH_BASE_URL -app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT - -app.state.config.TTS_MISTRAL_API_KEY = AUDIO_TTS_MISTRAL_API_KEY -app.state.config.TTS_MISTRAL_API_BASE_URL = AUDIO_TTS_MISTRAL_API_BASE_URL - app.state.faster_whisper_model = None app.state.speech_synthesiser = None @@ -1345,31 +688,6 @@ app.state.speech_speaker_embeddings_dataset = None ######################################## -app.state.config.TASK_MODEL = TASK_MODEL -app.state.config.TASK_MODEL_EXTERNAL = TASK_MODEL_EXTERNAL - - -app.state.config.ENABLE_SEARCH_QUERY_GENERATION = ENABLE_SEARCH_QUERY_GENERATION -app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = ENABLE_RETRIEVAL_QUERY_GENERATION -app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = ENABLE_AUTOCOMPLETE_GENERATION -app.state.config.ENABLE_TAGS_GENERATION = ENABLE_TAGS_GENERATION -app.state.config.ENABLE_TITLE_GENERATION = ENABLE_TITLE_GENERATION -app.state.config.ENABLE_FOLLOW_UP_GENERATION = ENABLE_FOLLOW_UP_GENERATION - - -app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = TITLE_GENERATION_PROMPT_TEMPLATE -app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = TAGS_GENERATION_PROMPT_TEMPLATE -app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE -app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = FOLLOW_UP_GENERATION_PROMPT_TEMPLATE - -app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE -app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE = QUERY_GENERATION_PROMPT_TEMPLATE -app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE = AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE -app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH -app.state.config.VOICE_MODE_PROMPT_TEMPLATE = VOICE_MODE_PROMPT_TEMPLATE -app.state.config.ENABLE_VOICE_MODE_PROMPT = ENABLE_VOICE_MODE_PROMPT - - ######################################## # # WEBUI @@ -1506,7 +824,11 @@ async def get_models(request: Request, refresh: bool = False, user=Depends(get_v models.append(model) - model_order_list = request.app.state.config.MODEL_ORDER_LIST + # Chat requests resolve models by ID from request.app.state.MODELS, where + # duplicate IDs collapse to the last model. Return the same effective list. + models = list({model['id']: model for model in models}.values()) + + model_order_list = await Config.get('ui.model_order_list') if model_order_list: model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)} # Sort models by order list priority, with fallback for those not in the list @@ -1535,6 +857,12 @@ class ModelUnloadForm(BaseModel): model: str +def strip_provider_model_prefix(model_id: str, prefix_id: str | None) -> str: + if prefix_id and model_id.startswith(f'{prefix_id}.'): + return model_id[len(f'{prefix_id}.') :] + return model_id + + @app.post('/api/models/unload') async def unload_model(request: Request, form_data: ModelUnloadForm, user=Depends(get_admin_user)): """ @@ -1544,23 +872,34 @@ async def unload_model(request: Request, form_data: ModelUnloadForm, user=Depend """ model_id = form_data.model - # --- Ollama provider --- ollama_models = getattr(request.app.state, 'OLLAMA_MODELS', None) or {} + openai_models = getattr(request.app.state, 'OPENAI_MODELS', None) or {} + + seen = set() + while model_id not in ollama_models and model_id not in openai_models and model_id not in seen: + seen.add(model_id) + model_info = await Models.get_model_by_id(model_id) + if not model_info or not model_info.base_model_id: + break + model_id = model_info.base_model_id + + # --- Ollama provider --- if model_id in ollama_models: + ollama_config = await Config.get_many('ollama.base_urls', 'ollama.api_configs') + ollama_base_urls = ollama_config.get('ollama.base_urls') or [] + ollama_api_configs = ollama_config.get('ollama.api_configs') or {} url_indices = ollama_models[model_id].get('urls', []) errors = [] for idx in url_indices: - url = request.app.state.config.OLLAMA_BASE_URLS[idx] - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + url = ollama_base_urls[idx] + api_config = ollama_api_configs.get( str(idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), + ollama_api_configs.get(url, {}), ) key = api_config.get('key', None) prefix_id = api_config.get('prefix_id', None) - actual_model = model_id - if prefix_id and actual_model.startswith(f'{prefix_id}.'): - actual_model = actual_model[len(f'{prefix_id}.') :] + actual_model = strip_provider_model_prefix(model_id, prefix_id) payload = json.dumps({'model': actual_model, 'keep_alive': 0, 'prompt': ''}) @@ -1590,19 +929,21 @@ async def unload_model(request: Request, form_data: ModelUnloadForm, user=Depend return {'status': True} # --- OpenAI-compatible providers --- - openai_models = getattr(request.app.state, 'OPENAI_MODELS', None) or {} if model_id in openai_models: + openai_config = await Config.get_many('openai.api_configs', 'openai.api_base_urls', 'openai.api_keys') + openai_api_configs = openai_config.get('openai.api_configs') or {} + openai_base_urls = openai_config.get('openai.api_base_urls') or [] + openai_api_keys = openai_config.get('openai.api_keys') or [] model_info = openai_models[model_id] idx = model_info.get('urlIdx') - api_config = request.app.state.config.OPENAI_API_CONFIGS.get(str(idx), {}) + api_config = openai_api_configs.get(str(idx), {}) provider = api_config.get('provider', '') - base_url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = ( - request.app.state.config.OPENAI_API_KEYS[idx] if idx < len(request.app.state.config.OPENAI_API_KEYS) else '' - ) + base_url = openai_base_urls[idx] + key = openai_api_keys[idx] if idx < len(openai_api_keys) else '' if provider == 'llama.cpp': root_url = base_url.rstrip('/').removesuffix('/v1') + actual_model = strip_provider_model_prefix(model_id, api_config.get('prefix_id')) try: timeout = aiohttp.ClientTimeout(total=30) async with aiohttp.ClientSession(timeout=timeout, trust_env=True) as session: @@ -1612,7 +953,7 @@ async def unload_model(request: Request, form_data: ModelUnloadForm, user=Depend } async with session.post( f'{root_url}/models/unload', - json={'model': model_id}, + json={'model': actual_model}, headers=headers, ) as r: if not r.ok: @@ -1700,18 +1041,24 @@ async def chat_completion( request.state.model = model # Model params: global defaults as base, per-model overrides win - default_model_params = getattr(request.app.state.config, 'DEFAULT_MODEL_PARAMS', None) or {} + default_model_params = await Config.get('models.default_params', {}) or {} model_info_params = { **default_model_params, **(model_info.params.model_dump() if model_info and model_info.params else {}), } + request_params = {key: value for key, value in (form_data.get('params') or {}).items() if value is not None} + if model_info_params or request_params: + form_data['params'] = { + **model_info_params, + **request_params, + } # Check base model existence for custom models if model_info and model_info.base_model_id: base_model_id = model_info.base_model_id if base_model_id not in request.app.state.MODELS: if ENABLE_CUSTOM_MODEL_FALLBACK: - default_models = (request.app.state.config.DEFAULT_MODELS or '').split(',') + default_models = ((await Config.get('ui.default_models')) or '').split(',') fallback_model_id = default_models[0].strip() if default_models[0] else None @@ -1727,6 +1074,7 @@ async def chat_completion( # Chat Params stream_delta_chunk_size = form_data.get('params', {}).get('stream_delta_chunk_size') reasoning_tags = form_data.get('params', {}).get('reasoning_tags') + compact_token_threshold = form_data.get('params', {}).get('compact_token_threshold') # Model Params if model_info_params.get('stream_response') is not None: @@ -1738,6 +1086,9 @@ async def chat_completion( if model_info_params.get('reasoning_tags') is not None: reasoning_tags = model_info_params.get('reasoning_tags') + if model_info_params.get('compact_token_threshold') is not None: + compact_token_threshold = model_info_params.get('compact_token_threshold') + # parent_id signals intent: # null → new chat (root message, no parent) # value → follow-up (user message's parentId = prev assistant) @@ -1746,13 +1097,19 @@ async def chat_completion( parent_id = form_data.pop('parent_id', None) form_data.pop('new_chat', None) # Legacy field - # Multi-model: {model_id: assistant_message_id} - # Single-model fallback: built from 'model' + 'id' + # Multi-model message_ids: list of {model_id, message_id} entries. + # Supports both the new array format and legacy dict format for backward compat. message_ids = form_data.pop('message_ids', None) - if not message_ids: - message_ids = {model_id: form_data.pop('id', None)} - else: + if isinstance(message_ids, list): + # New format: [{"model_id": ..., "message_id": ...}, ...] form_data.pop('id', None) + elif isinstance(message_ids, dict): + # Legacy dict format: {model_id: message_id} — convert to list + message_ids = [{'model_id': k, 'message_id': v} for k, v in message_ids.items()] + form_data.pop('id', None) + else: + # Single-model fallback + message_ids = [{'model_id': model_id, 'message_id': form_data.pop('id', None)}] user_message = form_data.pop('user_message', None) or form_data.pop('parent_message', None) @@ -1765,13 +1122,14 @@ async def chat_completion( and not await has_permission( user.id, 'features.direct_tool_servers', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), ) ): tool_servers = None metadata = { 'user_id': user.id, + 'user_agent': request.headers.get('user-agent', '') or '', 'chat_id': form_data.pop('chat_id', None) or '', 'user_message': user_message, 'user_message_id': user_message.get('id') if user_message else None, @@ -1789,13 +1147,11 @@ async def chat_completion( 'params': { 'stream_delta_chunk_size': stream_delta_chunk_size, 'reasoning_tags': reasoning_tags, + 'compact_token_threshold': compact_token_threshold, 'function_calling': ( - 'native' - if ( - form_data.get('params', {}).get('function_calling') == 'native' - or model_info_params.get('function_calling') == 'native' - ) - else 'default' + form_data.get('params', {}).get('function_calling') + or model_info_params.get('function_calling') + or 'native' ), }, } @@ -1803,6 +1159,10 @@ async def chat_completion( if is_new_chat: metadata['chat_id'] = str(uuid4()) + initial_title_generation = None + if is_new_chat and tasks and TASKS.TITLE_GENERATION in tasks: + initial_title_generation = tasks.pop(TASKS.TITLE_GENERATION) + if metadata.get('chat_id') and user: chat_id = metadata['chat_id'] @@ -1834,8 +1194,10 @@ async def chat_completion( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT(), ) - target_message_id = list(message_ids.values())[0] if message_ids else None - if target_message_id: + for entry in message_ids: + target_message_id = entry.get('message_id') + if not target_message_id: + continue target_message = await Messages.get_message_by_id(target_message_id) if target_message and target_message.channel_id != channel.id: raise HTTPException( @@ -1852,13 +1214,15 @@ async def chat_completion( user_message_id = user_message.get('id') if user_message else None history_messages = {} - all_assistant_ids = [assistant_id for assistant_id in message_ids.values() if assistant_id] + all_assistant_ids = [entry['message_id'] for entry in message_ids if entry.get('message_id')] if user_message_id and user_message: user_message['childrenIds'] = all_assistant_ids history_messages[user_message_id] = user_message - for target_model_id, assistant_message_id in message_ids.items(): + for entry in message_ids: + target_model_id = entry['model_id'] + assistant_message_id = entry['message_id'] if assistant_message_id: history_messages[assistant_message_id] = { 'id': assistant_message_id, @@ -1878,7 +1242,7 @@ async def chat_completion( chat={ 'id': chat_id, 'title': 'New Chat', - 'models': list(message_ids.keys()), + 'models': [entry['model_id'] for entry in message_ids], 'history': { 'currentId': all_assistant_ids[0] if all_assistant_ids else user_message_id, 'messages': history_messages, @@ -1895,6 +1259,39 @@ async def chat_completion( folder_id=metadata.get('folder_id'), ), ) + await publish_event( + request, + EVENTS.CHAT_CREATED, + actor=user, + subject_id=chat_id, + data={'title': 'New Chat'}, + ) + if user_message_id: + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor=user, + subject_id=user_message_id, + data={ + 'chat_id': chat_id, + 'role': 'user', + 'content_preview': user_message.get('content', '')[:300], + }, + ) + for entry in message_ids: + assistant_message_id = entry.get('message_id') + if assistant_message_id: + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor=user, + subject_id=assistant_message_id, + data={ + 'chat_id': chat_id, + 'role': 'assistant', + 'model': entry.get('model_id'), + }, + ) # Insert chat files from user message if any user_message_files = user_message.get('files', []) @@ -1913,6 +1310,29 @@ async def chat_completion( except Exception as e: log.debug(f'Error inserting chat files: {e}') pass + + if initial_title_generation is not None and all_assistant_ids: + title_metadata = { + **metadata, + 'message_id': all_assistant_ids[0], + } + event_emitter = await get_event_emitter(title_metadata, update_db=False) + title_ctx = { + 'request': request, + 'form_data': form_data, + 'user': user, + 'metadata': title_metadata, + 'tasks': {TASKS.TITLE_GENERATION: initial_title_generation}, + 'event_emitter': event_emitter, + } + + async def run_initial_title_generation(): + try: + await background_tasks_handler(title_ctx) + except Exception as e: + log.debug(f'Error generating initial chat title: {e}') + + asyncio.create_task(run_initial_title_generation()) else: # Existing chat — verify ownership if not await Chats.is_chat_owner(chat_id, user.id) and user.role != 'admin': @@ -1939,6 +1359,17 @@ async def chat_completion( user_message['id'], user_message, ) + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor=user, + subject_id=user_message['id'], + data={ + 'chat_id': chat_id, + 'role': user_message.get('role', 'user'), + 'content_preview': user_message.get('content', '')[:300], + }, + ) # Link grandparent → user message (childrenIds) grandparent_id = user_message.get('parentId') @@ -1972,7 +1403,7 @@ async def chat_completion( # Save ALL assistant placeholders user_message_id = metadata.get('user_message_id') - all_assistant_ids = [assistant_id for assistant_id in message_ids.values() if assistant_id] + all_assistant_ids = [entry['message_id'] for entry in message_ids if entry.get('message_id')] # Link user message → all assistant messages (childrenIds) if user_message_id and all_assistant_ids: @@ -1989,7 +1420,9 @@ async def chat_completion( ) # Save each assistant placeholder - for target_model_id, assistant_message_id in message_ids.items(): + for entry in message_ids: + target_model_id = entry['model_id'] + assistant_message_id = entry['message_id'] if assistant_message_id: await Chats.upsert_message_to_chat_by_id_and_message_id( chat_id, @@ -2005,6 +1438,17 @@ async def chat_completion( 'timestamp': int(time.time()), }, ) + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor=user, + subject_id=assistant_message_id, + data={ + 'chat_id': chat_id, + 'role': 'assistant', + 'model': target_model_id, + }, + ) request.state.metadata = metadata form_data['metadata'] = metadata @@ -2109,7 +1553,8 @@ async def chat_completion( # task's current cancel scope", which propagates as a # BaseException through the finally block, discards the response # return value, and surfaces as a 500 "No response returned." - # MCPClient.disconnect() already catches BaseException internally. + # MCPClient.disconnect() suppresses known transport teardown errors + # while still propagating real task cancellation. try: if mcp_clients := metadata.get('mcp_clients'): for client in reversed(list(mcp_clients.values())): @@ -2141,7 +1586,9 @@ async def chat_completion( task_ids = [] chat_id = metadata['chat_id'] - for idx, (target_model_id, assistant_message_id) in enumerate(message_ids.items()): + for idx, entry in enumerate(message_ids): + target_model_id = entry['model_id'] + assistant_message_id = entry['message_id'] if not assistant_message_id: continue @@ -2161,7 +1608,7 @@ async def chat_completion( # Resolve the model object for this specific model resolved_model = request.app.state.MODELS.get(target_model_id, model) - # Only the first model runs title/tags generation; + # Only the first model runs chat-level background tasks; # subsequent models only run follow-ups. task_id, _ = await create_task( request.app.state.redis, @@ -2188,7 +1635,7 @@ async def chat_completion( # Emit chat:active=true if task_ids: event_emitter = await get_event_emitter( - {**metadata, 'message_id': list(message_ids.values())[0]}, + {**metadata, 'message_id': message_ids[0]['message_id']}, update_db=False, ) if event_emitter: @@ -2201,7 +1648,7 @@ async def chat_completion( } else: # Legacy/direct: single model, synchronous - metadata['message_id'] = list(message_ids.values())[0] + metadata['message_id'] = message_ids[0]['message_id'] return await process_chat(request, form_data, user, metadata, model, tasks) @@ -2394,7 +1841,54 @@ async def get_app_config(request: Request): if user is None: onboarding = not await Users.has_users() - user_count = await Users.get_num_users() if app.state.LICENSE_METADATA else None + license_metadata = getattr(app.state, 'LICENSE_METADATA', None) + user_count = await Users.get_num_users() if license_metadata else None + config = await Config.get_many( + 'oauth.auto_redirect', + 'ldap.enable', + 'ui.enable_signup', + 'ui.enable_login_form', + 'auth.enable_api_keys', + 'ui.enable_password_change_form', + 'direct.enable', + 'folders.enable', + 'folders.max_file_count', + 'channels.enable', + 'calendar.enable', + 'automations.enable', + 'notes.enable', + 'web.search.enable', + 'web.search.confirmation.enable', + 'web.search.confirmation.content', + 'code_execution.enable', + 'code_interpreter.enable', + 'image_generation.enable', + 'task.autocomplete.enable', + 'ui.enable_community_sharing', + 'ui.enable_message_rating', + 'ui.enable_user_webhooks', + 'users.enable_status', + 'google_drive.enable', + 'onedrive.enable', + 'memories.enable', + 'ui.default_models', + 'ui.default_pinned_models', + 'ui.prompt_suggestions', + 'code_execution.engine', + 'code_interpreter.engine', + 'audio.tts.engine', + 'audio.tts.voice', + 'audio.tts.split_on', + 'audio.stt.engine', + 'rag.file.max_size', + 'rag.file.max_count', + 'file.image_compression_width', + 'file.image_compression_height', + 'user.permissions', + 'ui.pending_user_overlay_title', + 'ui.pending_user_overlay_content', + 'ui.watermark', + ) return { **({'onboarding': True} if onboarding else {}), @@ -2404,53 +1898,56 @@ async def get_app_config(request: Request): 'default_locale': str(DEFAULT_LOCALE), 'oauth': { 'providers': {name: config.get('name', name) for name, config in OAUTH_PROVIDERS.items()}, - 'auto_redirect': app.state.config.OAUTH_AUTO_REDIRECT, + 'auto_redirect': config.get('oauth.auto_redirect'), }, 'features': { # --- Public: required by login/signup page pre-auth --- 'auth': WEBUI_AUTH, - 'auth_trusted_header': bool(app.state.AUTH_TRUSTED_EMAIL_HEADER), + 'auth_trusted_header': bool(WEBUI_AUTH_TRUSTED_EMAIL_HEADER), 'enable_signup_password_confirmation': ENABLE_SIGNUP_PASSWORD_CONFIRMATION, - 'enable_ldap': app.state.config.ENABLE_LDAP, - 'enable_signup': app.state.config.ENABLE_SIGNUP, - 'enable_login_form': app.state.config.ENABLE_LOGIN_FORM, + 'enable_ldap': config.get('ldap.enable'), + 'enable_signup': config.get('ui.enable_signup'), + 'enable_login_form': config.get('ui.enable_login_form'), 'enable_websocket': ENABLE_WEBSOCKET_SUPPORT, # --- Authenticated: only consumed by logged-in frontend --- **( { - 'enable_api_keys': app.state.config.ENABLE_API_KEYS, - 'enable_password_change_form': app.state.config.ENABLE_PASSWORD_CHANGE_FORM, + 'enable_api_keys': config.get('auth.enable_api_keys'), + 'enable_password_change_form': config.get('ui.enable_password_change_form'), 'enable_version_update_check': ENABLE_VERSION_UPDATE_CHECK, + 'enable_pyodide_file_persistence': ENABLE_PYODIDE_FILE_PERSISTENCE, 'enable_public_active_users_count': ENABLE_PUBLIC_ACTIVE_USERS_COUNT, 'enable_easter_eggs': ENABLE_EASTER_EGGS, - 'enable_direct_connections': app.state.config.ENABLE_DIRECT_CONNECTIONS, - 'enable_folders': app.state.config.ENABLE_FOLDERS, - 'folder_max_file_count': app.state.config.FOLDER_MAX_FILE_COUNT, - 'enable_channels': app.state.config.ENABLE_CHANNELS, - 'enable_calendar': app.state.config.ENABLE_CALENDAR, - 'enable_automations': app.state.config.ENABLE_AUTOMATIONS, - 'enable_notes': app.state.config.ENABLE_NOTES, - 'enable_web_search': app.state.config.ENABLE_WEB_SEARCH, - 'enable_code_execution': app.state.config.ENABLE_CODE_EXECUTION, - 'enable_code_interpreter': app.state.config.ENABLE_CODE_INTERPRETER, - 'enable_image_generation': app.state.config.ENABLE_IMAGE_GENERATION, - 'enable_autocomplete_generation': app.state.config.ENABLE_AUTOCOMPLETE_GENERATION, - 'enable_community_sharing': app.state.config.ENABLE_COMMUNITY_SHARING, - 'enable_message_rating': app.state.config.ENABLE_MESSAGE_RATING, - 'enable_user_webhooks': app.state.config.ENABLE_USER_WEBHOOKS, - 'enable_user_status': app.state.config.ENABLE_USER_STATUS, + 'enable_direct_connections': config.get('direct.enable'), + 'enable_folders': config.get('folders.enable'), + 'folder_max_file_count': config.get('folders.max_file_count'), + 'enable_channels': config.get('channels.enable'), + 'enable_calendar': config.get('calendar.enable'), + 'enable_automations': config.get('automations.enable'), + 'enable_notes': config.get('notes.enable'), + 'enable_web_search': config.get('web.search.enable'), + 'enable_web_search_confirmation': config.get('web.search.confirmation.enable'), + 'web_search_confirmation_content': config.get('web.search.confirmation.content'), + 'enable_code_execution': config.get('code_execution.enable'), + 'enable_code_interpreter': config.get('code_interpreter.enable'), + 'enable_image_generation': config.get('image_generation.enable'), + 'enable_autocomplete_generation': config.get('task.autocomplete.enable'), + 'enable_community_sharing': config.get('ui.enable_community_sharing'), + 'enable_message_rating': config.get('ui.enable_message_rating'), + 'enable_user_webhooks': config.get('ui.enable_user_webhooks'), + 'enable_user_status': config.get('users.enable_status'), 'enable_admin_export': ENABLE_ADMIN_EXPORT, 'enable_admin_chat_access': ENABLE_ADMIN_CHAT_ACCESS, 'enable_admin_analytics': ENABLE_ADMIN_ANALYTICS, - 'enable_google_drive_integration': app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION, - 'enable_onedrive_integration': app.state.config.ENABLE_ONEDRIVE_INTEGRATION, - 'enable_memories': app.state.config.ENABLE_MEMORIES, + 'enable_google_drive_integration': config.get('google_drive.enable'), + 'enable_onedrive_integration': config.get('onedrive.enable'), + 'enable_memories': config.get('memories.enable'), **( { 'enable_onedrive_personal': ENABLE_ONEDRIVE_PERSONAL, 'enable_onedrive_business': ENABLE_ONEDRIVE_BUSINESS, } - if app.state.config.ENABLE_ONEDRIVE_INTEGRATION + if config.get('onedrive.enable') else {} ), } @@ -2460,55 +1957,55 @@ async def get_app_config(request: Request): }, **( { - 'default_models': app.state.config.DEFAULT_MODELS, - 'default_pinned_models': app.state.config.DEFAULT_PINNED_MODELS, - 'default_prompt_suggestions': app.state.config.DEFAULT_PROMPT_SUGGESTIONS, + 'default_models': config.get('ui.default_models'), + 'default_pinned_models': config.get('ui.default_pinned_models'), + 'default_prompt_suggestions': config.get('ui.prompt_suggestions'), **({'user_count': user_count} if user_count is not None else {}), 'code': { - 'engine': app.state.config.CODE_EXECUTION_ENGINE, - 'interpreter_engine': app.state.config.CODE_INTERPRETER_ENGINE, + 'engine': config.get('code_execution.engine'), + 'interpreter_engine': config.get('code_interpreter.engine'), }, 'audio': { 'tts': { - 'engine': app.state.config.TTS_ENGINE, - 'voice': app.state.config.TTS_VOICE, - 'split_on': app.state.config.TTS_SPLIT_ON, + 'engine': config.get('audio.tts.engine'), + 'voice': config.get('audio.tts.voice'), + 'split_on': config.get('audio.tts.split_on'), }, 'stt': { - 'engine': app.state.config.STT_ENGINE, + 'engine': config.get('audio.stt.engine'), }, }, 'file': { - 'max_size': app.state.config.FILE_MAX_SIZE, - 'max_count': app.state.config.FILE_MAX_COUNT, + 'max_size': config.get('rag.file.max_size'), + 'max_count': config.get('rag.file.max_count'), 'image_compression': { - 'width': app.state.config.FILE_IMAGE_COMPRESSION_WIDTH, - 'height': app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT, + 'width': config.get('file.image_compression_width'), + 'height': config.get('file.image_compression_height'), }, }, - 'permissions': {**app.state.config.USER_PERMISSIONS}, + 'permissions': {**(config.get('user.permissions') or {})}, 'google_drive': { - 'client_id': GOOGLE_DRIVE_CLIENT_ID.value, - 'api_key': GOOGLE_DRIVE_API_KEY.value, + 'client_id': GOOGLE_DRIVE_CLIENT_ID, + 'api_key': GOOGLE_DRIVE_API_KEY, }, 'onedrive': { 'client_id_personal': ONEDRIVE_CLIENT_ID_PERSONAL, 'client_id_business': ONEDRIVE_CLIENT_ID_BUSINESS, - 'sharepoint_url': ONEDRIVE_SHAREPOINT_URL.value, - 'sharepoint_tenant_id': ONEDRIVE_SHAREPOINT_TENANT_ID.value, + 'sharepoint_url': ONEDRIVE_SHAREPOINT_URL, + 'sharepoint_tenant_id': ONEDRIVE_SHAREPOINT_TENANT_ID, }, 'ui': { - 'pending_user_overlay_title': app.state.config.PENDING_USER_OVERLAY_TITLE, - 'pending_user_overlay_content': app.state.config.PENDING_USER_OVERLAY_CONTENT, - 'response_watermark': app.state.config.RESPONSE_WATERMARK, + 'pending_user_overlay_title': config.get('ui.pending_user_overlay_title'), + 'pending_user_overlay_content': config.get('ui.pending_user_overlay_content'), + 'response_watermark': config.get('ui.watermark'), 'iframe_csp': IFRAME_CSP, }, - 'license_metadata': app.state.LICENSE_METADATA, + 'license_metadata': license_metadata, **( { - 'active_entries': app.state.USER_COUNT, + 'active_entries': user_count, } - if user.role == 'admin' + if user.role == 'admin' and user_count is not None else {} ), } @@ -2517,8 +2014,8 @@ async def get_app_config(request: Request): **( { 'ui': { - 'pending_user_overlay_title': app.state.config.PENDING_USER_OVERLAY_TITLE, - 'pending_user_overlay_content': app.state.config.PENDING_USER_OVERLAY_CONTENT, + 'pending_user_overlay_title': config.get('ui.pending_user_overlay_title'), + 'pending_user_overlay_content': config.get('ui.pending_user_overlay_content'), } } if user and user.role == 'pending' @@ -2527,11 +2024,11 @@ async def get_app_config(request: Request): **( { 'metadata': { - 'login_footer': app.state.LICENSE_METADATA.get('login_footer', ''), - 'auth_logo_position': app.state.LICENSE_METADATA.get('auth_logo_position', ''), + 'login_footer': license_metadata.get('login_footer', ''), + 'auth_logo_position': license_metadata.get('auth_logo_position', ''), } } - if app.state.LICENSE_METADATA + if license_metadata else {} ), } @@ -2539,22 +2036,115 @@ async def get_app_config(request: Request): } -class UrlForm(BaseModel): +class EventWebhookForm(BaseModel): + name: str | None = None url: str + enabled: bool = True + events: list[str] | None = None + targets: list[dict[str, str]] | None = None -@app.get('/api/webhook') -async def get_webhook_url(user=Depends(get_admin_user)): +class EventWebhookUpdateForm(BaseModel): + name: str | None = None + url: str | None = None + enabled: bool | None = None + events: list[str] | None = None + targets: list[dict[str, str]] | None = None + + +@app.get('/api/events') +async def get_event_catalog(user=Depends(get_admin_user)): return { - 'url': app.state.config.WEBHOOK_URL, + 'schema': VERSION, + 'events': get_event_catalog_items(), } -@app.post('/api/webhook') -async def update_webhook_url(form_data: UrlForm, user=Depends(get_admin_user)): - app.state.config.WEBHOOK_URL = form_data.url - app.state.WEBHOOK_URL = app.state.config.WEBHOOK_URL - return {'url': app.state.config.WEBHOOK_URL} +@app.get('/api/events/webhooks') +async def get_event_webhooks_api(user=Depends(get_admin_user)): + return await get_event_webhooks() + + +@app.post('/api/events/webhooks') +async def create_event_webhook(form_data: EventWebhookForm, user=Depends(get_admin_user)): + try: + webhook = await upsert_event_webhook( + { + 'name': form_data.name, + 'url': form_data.url, + 'enabled': form_data.enabled, + 'events': form_data.events, + 'targets': form_data.targets, + } + ) + except ValueError as e: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) + + await publish_event( + app, + EVENTS.CONFIG_WEBHOOK_UPDATED, + actor=user, + subject_id=webhook['id'], + subject_type='config', + data={ + 'action': 'created', + 'enabled': webhook.get('enabled'), + 'events': webhook.get('events'), + 'targets': webhook.get('targets'), + }, + ) + return webhook + + +@app.put('/api/events/webhooks/{webhook_id}') +async def update_event_webhook(webhook_id: str, form_data: EventWebhookUpdateForm, user=Depends(get_admin_user)): + webhooks = await get_event_webhooks() + existing = next((webhook for webhook in webhooks if webhook.get('id') == webhook_id), None) + if not existing: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Webhook not found') + + try: + webhook = await upsert_event_webhook( + { + **existing, + **form_data.model_dump(exclude_unset=True), + 'id': webhook_id, + } + ) + except ValueError as e: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e)) + + await publish_event( + app, + EVENTS.CONFIG_WEBHOOK_UPDATED, + actor=user, + subject_id=webhook_id, + subject_type='config', + data={ + 'action': 'updated', + 'enabled': webhook.get('enabled'), + 'events': webhook.get('events'), + 'targets': webhook.get('targets'), + }, + ) + return webhook + + +@app.delete('/api/events/webhooks/{webhook_id}') +async def delete_event_webhook_api(webhook_id: str, user=Depends(get_admin_user)): + deleted = await delete_event_webhook(webhook_id) + if not deleted: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='Webhook not found') + + await publish_event( + app, + EVENTS.CONFIG_WEBHOOK_UPDATED, + actor=user, + subject_id=webhook_id, + subject_type='config', + data={'action': 'deleted'}, + ) + return {'status': True} @app.get('/api/version') @@ -2620,24 +2210,6 @@ async def get_current_usage(user=Depends(get_verified_user)): # --- OAuth Login & Callback --- -# Initialize OAuth client manager with any MCP tool servers using OAuth 2.1 -if len(app.state.config.TOOL_SERVER_CONNECTIONS) > 0: - for tool_server_connection in app.state.config.TOOL_SERVER_CONNECTIONS: - if tool_server_connection.get('type', 'openapi') == 'mcp': - server_id = tool_server_connection.get('info', {}).get('id') - auth_type = tool_server_connection.get('auth_type', 'none') - - if server_id and auth_type in ('oauth_2.1', 'oauth_2.1_static'): - try: - oauth_client_info = resolve_oauth_client_info(tool_server_connection) - app.state.oauth_client_manager.add_client( - f'mcp:{server_id}', - OAuthClientInformationFull(**oauth_client_info), - ) - except Exception as e: - log.error(f'Error adding OAuth client for MCP tool server {server_id}: {e}') - pass - try: if ENABLE_STAR_SESSIONS_MIDDLEWARE: redis_session_store = RedisStore( @@ -2672,9 +2244,10 @@ async def register_client(request, client_id: str) -> bool: connection = None connection_idx = None - for idx, conn in enumerate(request.app.state.config.TOOL_SERVER_CONNECTIONS or []): + tool_server_connections = await Config.get('tool_server.connections', []) or [] + for idx, conn in enumerate(tool_server_connections): if conn.get('type', 'openapi') == server_type: - info = conn.get('info', {}) + info = conn.get('info') or {} if info.get('id') == server_id: connection = conn connection_idx = idx @@ -2686,12 +2259,15 @@ async def register_client(request, client_id: str) -> bool: server_url = connection.get('url') auth_type = connection.get('auth_type', 'none') + oauth_scope = (connection.get('info') or {}).get('oauth_scope') or (connection.get('config') or {}).get( + 'oauth_scope' + ) oauth_server_key = (connection.get('config') or {}).get('oauth_server_key') try: if auth_type == 'oauth_2.1_static': # Static credentials: rebuild from admin-provided credentials + fresh metadata - info = connection.get('info', {}) + info = connection.get('info') or {} oauth_client_id = info.get('oauth_client_id') or '' oauth_client_secret = info.get('oauth_client_secret') or '' if not oauth_client_id or not oauth_client_secret: @@ -2709,6 +2285,7 @@ async def register_client(request, client_id: str) -> bool: server_url, oauth_client_id=oauth_client_id, oauth_client_secret=oauth_client_secret, + oauth_scope=oauth_scope, ) else: oauth_client_info = await get_oauth_client_info_with_dynamic_client_registration( @@ -2716,28 +2293,30 @@ async def register_client(request, client_id: str) -> bool: client_id, server_url, oauth_server_key, + oauth_scope=oauth_scope, ) except Exception as e: log.error(f'OAuth client re-registration failed for {client_id}: {e}') return False try: - connections = request.app.state.config.TOOL_SERVER_CONNECTIONS + connections = await Config.get('tool_server.connections', []) or [] connections[connection_idx] = { **connection, 'info': { - **connection.get('info', {}), + **(connection.get('info') or {}), 'oauth_client_info': encrypt_data(oauth_client_info.model_dump(mode='json')), }, } - # Re-assign the full list to trigger AppConfig.__setattr__ → ConfigVar.save() - # (in-place list mutation via list[idx] = ... does not trigger __setattr__) - request.app.state.config.TOOL_SERVER_CONNECTIONS = connections + await Config.upsert({'tool_server.connections': connections}) except Exception as e: log.error(f'Failed to persist updated OAuth client info for tool server {client_id}: {e}') return False oauth_client_manager.remove_client(client_id) + oauth_client_info = OAuthClientInformationFull( + **apply_connection_oauth_options(connection, oauth_client_info.model_dump(mode='json')) + ) oauth_client_manager.add_client(client_id, oauth_client_info) log.info(f'Re-registered OAuth client {client_id} for tool server') return True @@ -2751,8 +2330,8 @@ async def oauth_client_authorize( user=Depends(get_verified_user), ): # ensure_valid_client_registration - client = oauth_client_manager.get_client(client_id) - client_info = oauth_client_manager.get_client_info(client_id) + client = await oauth_client_manager.get_client(client_id) + client_info = await oauth_client_manager.get_client_info(client_id) if client is None or client_info is None: raise HTTPException(status.HTTP_404_NOT_FOUND) @@ -2769,8 +2348,8 @@ async def oauth_client_authorize( detail='Failed to re-register OAuth client', ) - client = oauth_client_manager.get_client(client_id) - client_info = oauth_client_manager.get_client_info(client_id) + client = await oauth_client_manager.get_client(client_id) + client_info = await oauth_client_manager.get_client_info(client_id) if client is None or client_info is None: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, @@ -2843,10 +2422,11 @@ async def oauth_backchannel_logout( @app.get('/manifest.json') async def get_manifest_json(): - if app.state.EXTERNAL_PWA_MANIFEST_URL: + external_pwa_manifest_url = getattr(app.state, 'EXTERNAL_PWA_MANIFEST_URL', None) + if external_pwa_manifest_url: session = await get_session() async with session.get( - app.state.EXTERNAL_PWA_MANIFEST_URL, + external_pwa_manifest_url, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: r.raise_for_status() @@ -2883,14 +2463,15 @@ async def get_manifest_json(): @app.get('/opensearch.xml') async def get_opensearch_xml(): + webui_url = await Config.get('webui.url') xml_content = rf""" {app.state.WEBUI_NAME} Search {app.state.WEBUI_NAME} UTF-8 - {app.state.config.WEBUI_URL}/static/favicon.png - - {app.state.config.WEBUI_URL} + {webui_url}/static/favicon.png + + {webui_url} """ return Response(content=xml_content, media_type='application/xml') @@ -3020,6 +2601,10 @@ applications.get_swagger_ui_html = swagger_ui_html if os.path.exists(FRONTEND_BUILD_DIR): mimetypes.add_type('text/javascript', '.js') + pyodide_dir = FRONTEND_BUILD_DIR / 'pyodide' + if os.path.exists(pyodide_dir): + app.mount('/pyodide', CORSStaticFiles(directory=pyodide_dir), name='pyodide') + app.mount( '/', SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True), diff --git a/backend/open_webui/migrations/env.py b/backend/open_webui/migrations/env.py index 6fcd9a64cd..87a1e54608 100644 --- a/backend/open_webui/migrations/env.py +++ b/backend/open_webui/migrations/env.py @@ -6,7 +6,7 @@ import logging.config import logging import alembic.context from open_webui.env import DATABASE_PASSWORD, DATABASE_URL, LOG_FORMAT -from open_webui.internal.db import extract_ssl_params_from_url, reattach_ssl_params_to_url +from open_webui.internal.db import enable_iam_token_auth, extract_ssl_params_from_url, reattach_ssl_params_to_url from open_webui.models.auths import Auth from open_webui.models.calendar import Calendar, CalendarEvent, CalendarEventAttendee # noqa: F401 from sqlalchemy import create_engine, engine_from_config, pool @@ -68,6 +68,7 @@ def _get_engine_connectable(): def run_migrations_online() -> None: """Execute migrations against a live database connection.""" live_connectable = _get_engine_connectable() + enable_iam_token_auth(live_connectable) with live_connectable.connect() as live_connection: alembic.context.configure( connection=live_connection, diff --git a/backend/open_webui/migrations/versions/242a2047eae0_update_chat_table.py b/backend/open_webui/migrations/versions/242a2047eae0_update_chat_table.py index e1c42bfb70..b496b72fdf 100644 --- a/backend/open_webui/migrations/versions/242a2047eae0_update_chat_table.py +++ b/backend/open_webui/migrations/versions/242a2047eae0_update_chat_table.py @@ -49,7 +49,7 @@ def upgrade(): # Step 3: Migrate data from 'old_chat' to 'chat' (only if old_chat exists) # Re-check columns after potential rename above - current_cols = {c['name'] for c in inspector.get_columns('chat')} + current_cols = {c['name'] for c in sa.inspect(conn).get_columns('chat')} if 'old_chat' in current_cols: chat_table = table( 'chat', @@ -76,8 +76,12 @@ def upgrade(): def downgrade(): + conn = op.get_bind() + columns = {col['name'] for col in sa.inspect(conn).get_columns('chat')} + # Step 1: Add 'old_chat' column back as Text - op.add_column('chat', sa.Column('old_chat', sa.Text(), nullable=True)) + if 'old_chat' not in columns: + op.add_column('chat', sa.Column('old_chat', sa.Text(), nullable=True)) # Step 2: Convert 'chat' JSON data back to text and store in 'old_chat' chat_table = table( @@ -87,14 +91,14 @@ def downgrade(): sa.Column('old_chat', sa.Text()), ) - connection = op.get_bind() - results = connection.execute(select(chat_table.c.id, chat_table.c.chat)) - for row in results: - text_data = json.dumps(row.chat) if row.chat is not None else None - connection.execute(sa.update(chat_table).where(chat_table.c.id == row.id).values(old_chat=text_data)) + if 'chat' in columns: + results = conn.execute(select(chat_table.c.id, chat_table.c.chat)) + for row in results: + text_data = json.dumps(row.chat) if row.chat is not None else None + conn.execute(sa.update(chat_table).where(chat_table.c.id == row.id).values(old_chat=text_data)) - # Step 3: Remove the new 'chat' JSON column - op.drop_column('chat', 'chat') + # Step 3: Remove the new 'chat' JSON column + op.drop_column('chat', 'chat') # Step 4: Rename 'old_chat' back to 'chat' op.alter_column('chat', 'old_chat', new_column_name='chat', existing_type=sa.Text()) diff --git a/backend/open_webui/migrations/versions/3ff2c63645b8_reshape_config_to_per_key_rows.py b/backend/open_webui/migrations/versions/3ff2c63645b8_reshape_config_to_per_key_rows.py new file mode 100644 index 0000000000..1bf3c9bb45 --- /dev/null +++ b/backend/open_webui/migrations/versions/3ff2c63645b8_reshape_config_to_per_key_rows.py @@ -0,0 +1,584 @@ +"""reshape config to per key rows + +Revision ID: 3ff2c63645b8 +Revises: 461111b60977 +Create Date: 2026-06-17 00:50:51.477073 + +""" + +import json +import time +from typing import Sequence, Union + +import sqlalchemy as sa +from alembic import op + + +# revision identifiers, used by Alembic. +revision: str = '3ff2c63645b8' +down_revision: Union[str, None] = '461111b60977' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +# Maps every dot-notation blob path to its legacy env/config key name. +# Built from the legacy persistent config declarations in config.py. +BLOB_PATH_TO_KEY = { + 'audio.stt.allowed_extensions': 'AUDIO_STT_ALLOWED_EXTENSIONS', + 'audio.stt.azure.api_key': 'AUDIO_STT_AZURE_API_KEY', + 'audio.stt.azure.base_url': 'AUDIO_STT_AZURE_BASE_URL', + 'audio.stt.azure.locales': 'AUDIO_STT_AZURE_LOCALES', + 'audio.stt.azure.max_speakers': 'AUDIO_STT_AZURE_MAX_SPEAKERS', + 'audio.stt.azure.region': 'AUDIO_STT_AZURE_REGION', + 'audio.stt.deepgram.api_key': 'DEEPGRAM_API_KEY', + 'audio.stt.engine': 'AUDIO_STT_ENGINE', + 'audio.stt.mistral.api_base_url': 'AUDIO_STT_MISTRAL_API_BASE_URL', + 'audio.stt.mistral.api_key': 'AUDIO_STT_MISTRAL_API_KEY', + 'audio.stt.mistral.use_chat_completions': 'AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS', + 'audio.stt.model': 'AUDIO_STT_MODEL', + 'audio.stt.openai.api_base_url': 'AUDIO_STT_OPENAI_API_BASE_URL', + 'audio.stt.openai.api_key': 'AUDIO_STT_OPENAI_API_KEY', + 'audio.stt.supported_content_types': 'AUDIO_STT_SUPPORTED_CONTENT_TYPES', + 'audio.stt.whisper_model': 'WHISPER_MODEL', + 'audio.tts.api_key': 'AUDIO_TTS_API_KEY', + 'audio.tts.azure.speech_base_url': 'AUDIO_TTS_AZURE_SPEECH_BASE_URL', + 'audio.tts.azure.speech_output_format': 'AUDIO_TTS_AZURE_SPEECH_OUTPUT_FORMAT', + 'audio.tts.azure.speech_region': 'AUDIO_TTS_AZURE_SPEECH_REGION', + 'audio.tts.engine': 'AUDIO_TTS_ENGINE', + 'audio.tts.mistral.api_base_url': 'AUDIO_TTS_MISTRAL_API_BASE_URL', + 'audio.tts.mistral.api_key': 'AUDIO_TTS_MISTRAL_API_KEY', + 'audio.tts.model': 'AUDIO_TTS_MODEL', + 'audio.tts.openai.api_base_url': 'AUDIO_TTS_OPENAI_API_BASE_URL', + 'audio.tts.openai.api_key': 'AUDIO_TTS_OPENAI_API_KEY', + 'audio.tts.openai.params': 'AUDIO_TTS_OPENAI_PARAMS', + 'audio.tts.split_on': 'AUDIO_TTS_SPLIT_ON', + 'audio.tts.voice': 'AUDIO_TTS_VOICE', + 'auth.admin.email': 'ADMIN_EMAIL', + 'auth.admin.show': 'SHOW_ADMIN_DETAILS', + 'auth.api_key.allowed_endpoints': 'API_KEYS_ALLOWED_ENDPOINTS', + 'auth.api_key.endpoint_restrictions': 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS', + 'auth.enable_api_keys': 'ENABLE_API_KEYS', + 'auth.jwt_expiry': 'JWT_EXPIRES_IN', + 'automations.enable': 'ENABLE_AUTOMATIONS', + 'automations.max_count': 'AUTOMATION_MAX_COUNT', + 'automations.min_interval': 'AUTOMATION_MIN_INTERVAL', + 'calendar.enable': 'ENABLE_CALENDAR', + 'channels.enable': 'ENABLE_CHANNELS', + 'code_execution.enable': 'ENABLE_CODE_EXECUTION', + 'code_execution.engine': 'CODE_EXECUTION_ENGINE', + 'code_execution.jupyter.auth': 'CODE_EXECUTION_JUPYTER_AUTH', + 'code_execution.jupyter.auth_password': 'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD', + 'code_execution.jupyter.auth_token': 'CODE_EXECUTION_JUPYTER_AUTH_TOKEN', + 'code_execution.jupyter.timeout': 'CODE_EXECUTION_JUPYTER_TIMEOUT', + 'code_execution.jupyter.url': 'CODE_EXECUTION_JUPYTER_URL', + 'code_interpreter.enable': 'ENABLE_CODE_INTERPRETER', + 'code_interpreter.engine': 'CODE_INTERPRETER_ENGINE', + 'code_interpreter.jupyter.auth': 'CODE_INTERPRETER_JUPYTER_AUTH', + 'code_interpreter.jupyter.auth_password': 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD', + 'code_interpreter.jupyter.auth_token': 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN', + 'code_interpreter.jupyter.timeout': 'CODE_INTERPRETER_JUPYTER_TIMEOUT', + 'code_interpreter.jupyter.url': 'CODE_INTERPRETER_JUPYTER_URL', + 'code_interpreter.prompt_template': 'CODE_INTERPRETER_PROMPT_TEMPLATE', + 'direct.enable': 'ENABLE_DIRECT_CONNECTIONS', + 'evaluation.arena.enable': 'ENABLE_EVALUATION_ARENA_MODELS', + 'evaluation.arena.models': 'EVALUATION_ARENA_MODELS', + 'file.image_compression_height': 'FILE_IMAGE_COMPRESSION_HEIGHT', + 'file.image_compression_width': 'FILE_IMAGE_COMPRESSION_WIDTH', + 'folders.enable': 'ENABLE_FOLDERS', + 'folders.max_file_count': 'FOLDER_MAX_FILE_COUNT', + 'google_drive.api_key': 'GOOGLE_DRIVE_API_KEY', + 'google_drive.client_id': 'GOOGLE_DRIVE_CLIENT_ID', + 'google_drive.enable': 'ENABLE_GOOGLE_DRIVE_INTEGRATION', + 'image_generation.automatic1111.api_auth': 'AUTOMATIC1111_API_AUTH', + 'image_generation.automatic1111.api_params': 'AUTOMATIC1111_PARAMS', + 'image_generation.automatic1111.base_url': 'AUTOMATIC1111_BASE_URL', + 'image_generation.comfyui.api_key': 'COMFYUI_API_KEY', + 'image_generation.comfyui.base_url': 'COMFYUI_BASE_URL', + 'image_generation.comfyui.nodes': 'COMFYUI_WORKFLOW_NODES', + 'image_generation.comfyui.workflow': 'COMFYUI_WORKFLOW', + 'image_generation.enable': 'ENABLE_IMAGE_GENERATION', + 'image_generation.engine': 'IMAGE_GENERATION_ENGINE', + 'image_generation.gemini.api_base_url': 'IMAGES_GEMINI_API_BASE_URL', + 'image_generation.gemini.api_key': 'IMAGES_GEMINI_API_KEY', + 'image_generation.gemini.endpoint_method': 'IMAGES_GEMINI_ENDPOINT_METHOD', + 'image_generation.model': 'IMAGE_GENERATION_MODEL', + 'image_generation.openai.api_base_url': 'IMAGES_OPENAI_API_BASE_URL', + 'image_generation.openai.api_key': 'IMAGES_OPENAI_API_KEY', + 'image_generation.openai.api_version': 'IMAGES_OPENAI_API_VERSION', + 'image_generation.openai.params': 'IMAGES_OPENAI_API_PARAMS', + 'image_generation.prompt.enable': 'ENABLE_IMAGE_PROMPT_GENERATION', + 'image_generation.size': 'IMAGE_SIZE', + 'image_generation.steps': 'IMAGE_STEPS', + 'images.edit.comfyui.api_key': 'IMAGES_EDIT_COMFYUI_API_KEY', + 'images.edit.comfyui.base_url': 'IMAGES_EDIT_COMFYUI_BASE_URL', + 'images.edit.comfyui.nodes': 'IMAGES_EDIT_COMFYUI_WORKFLOW_NODES', + 'images.edit.comfyui.workflow': 'IMAGES_EDIT_COMFYUI_WORKFLOW', + 'images.edit.enable': 'ENABLE_IMAGE_EDIT', + 'images.edit.engine': 'IMAGE_EDIT_ENGINE', + 'images.edit.gemini.api_base_url': 'IMAGES_EDIT_GEMINI_API_BASE_URL', + 'images.edit.gemini.api_key': 'IMAGES_EDIT_GEMINI_API_KEY', + 'images.edit.model': 'IMAGE_EDIT_MODEL', + 'images.edit.openai.api_base_url': 'IMAGES_EDIT_OPENAI_API_BASE_URL', + 'images.edit.openai.api_key': 'IMAGES_EDIT_OPENAI_API_KEY', + 'images.edit.openai.api_version': 'IMAGES_EDIT_OPENAI_API_VERSION', + 'images.edit.size': 'IMAGE_EDIT_SIZE', + 'ldap.enable': 'ENABLE_LDAP', + 'ldap.group.enable_creation': 'ENABLE_LDAP_GROUP_CREATION', + 'ldap.group.enable_management': 'ENABLE_LDAP_GROUP_MANAGEMENT', + 'ldap.server.app_dn': 'LDAP_APP_DN', + 'ldap.server.app_password': 'LDAP_APP_PASSWORD', + 'ldap.server.attribute_for_groups': 'LDAP_ATTRIBUTE_FOR_GROUPS', + 'ldap.server.attribute_for_mail': 'LDAP_ATTRIBUTE_FOR_MAIL', + 'ldap.server.attribute_for_username': 'LDAP_ATTRIBUTE_FOR_USERNAME', + 'ldap.server.ca_cert_file': 'LDAP_CA_CERT_FILE', + 'ldap.server.ciphers': 'LDAP_CIPHERS', + 'ldap.server.host': 'LDAP_SERVER_HOST', + 'ldap.server.label': 'LDAP_SERVER_LABEL', + 'ldap.server.port': 'LDAP_SERVER_PORT', + 'ldap.server.search_filter': 'LDAP_SEARCH_FILTER', + 'ldap.server.use_tls': 'LDAP_USE_TLS', + 'ldap.server.users_dn': 'LDAP_SEARCH_BASE', + 'ldap.server.validate_cert': 'LDAP_VALIDATE_CERT', + 'memories.enable': 'ENABLE_MEMORIES', + 'models.base_models_cache': 'ENABLE_BASE_MODELS_CACHE', + 'models.default_metadata': 'DEFAULT_MODEL_METADATA', + 'models.default_params': 'DEFAULT_MODEL_PARAMS', + 'notes.enable': 'ENABLE_NOTES', + # OAuth — direct paths + 'oauth.admin_roles': 'OAUTH_ADMIN_ROLES', + 'oauth.allowed_domains': 'OAUTH_ALLOWED_DOMAINS', + 'oauth.allowed_roles': 'OAUTH_ALLOWED_ROLES', + 'oauth.audience': 'OAUTH_AUDIENCE', + 'oauth.auto_redirect': 'OAUTH_AUTO_REDIRECT', + 'oauth.blocked_groups': 'OAUTH_BLOCKED_GROUPS', + 'oauth.client.timeout': 'OAUTH_CLIENT_TIMEOUT', + 'oauth.enable_group_creation': 'ENABLE_OAUTH_GROUP_CREATION', + 'oauth.enable_group_mapping': 'ENABLE_OAUTH_GROUP_MANAGEMENT', + 'oauth.enable_role_mapping': 'ENABLE_OAUTH_ROLE_MANAGEMENT', + 'oauth.enable_signup': 'ENABLE_OAUTH_SIGNUP', + 'oauth.group_default_share': 'OAUTH_GROUP_DEFAULT_SHARE', + 'oauth.merge_accounts_by_email': 'OAUTH_MERGE_ACCOUNTS_BY_EMAIL', + 'oauth.refresh_token_include_scope': 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', + 'oauth.roles_claim': 'OAUTH_ROLES_CLAIM', + 'oauth.update_email_on_login': 'OAUTH_UPDATE_EMAIL_ON_LOGIN', + 'oauth.update_name_on_login': 'OAUTH_UPDATE_NAME_ON_LOGIN', + 'oauth.update_picture_on_login': 'OAUTH_UPDATE_PICTURE_ON_LOGIN', + # OAuth — generic provider paths + 'oauth.client_id': 'OAUTH_CLIENT_ID', + 'oauth.client_secret': 'OAUTH_CLIENT_SECRET', + 'oauth.code_challenge_method': 'OAUTH_CODE_CHALLENGE_METHOD', + 'oauth.email_claim': 'OAUTH_EMAIL_CLAIM', + 'oauth.end_session_endpoint': 'OPENID_END_SESSION_ENDPOINT', + 'oauth.group_claim': 'OAUTH_GROUP_CLAIM', + 'oauth.picture_claim': 'OAUTH_PICTURE_CLAIM', + 'oauth.provider_name': 'OAUTH_PROVIDER_NAME', + 'oauth.provider_url': 'OPENID_PROVIDER_URL', + 'oauth.redirect_uri': 'OPENID_REDIRECT_URI', + 'oauth.scopes': 'OAUTH_SCOPES', + 'oauth.sub_claim': 'OAUTH_SUB_CLAIM', + 'oauth.timeout': 'OAUTH_TIMEOUT', + 'oauth.token_endpoint_auth_method': 'OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', + 'oauth.username_claim': 'OAUTH_USERNAME_CLAIM', + # OAuth — OIDC nested paths (flattened) + 'oauth.oidc.avatar_claim': 'OAUTH_PICTURE_CLAIM', + 'oauth.oidc.client_id': 'OAUTH_CLIENT_ID', + 'oauth.oidc.client_secret': 'OAUTH_CLIENT_SECRET', + 'oauth.oidc.code_challenge_method': 'OAUTH_CODE_CHALLENGE_METHOD', + 'oauth.oidc.email_claim': 'OAUTH_EMAIL_CLAIM', + 'oauth.oidc.end_session_endpoint': 'OPENID_END_SESSION_ENDPOINT', + 'oauth.oidc.group_claim': 'OAUTH_GROUP_CLAIM', # renamed from OAUTH_GROUPS_CLAIM + 'oauth.oidc.oauth_timeout': 'OAUTH_TIMEOUT', + 'oauth.oidc.provider_name': 'OAUTH_PROVIDER_NAME', + 'oauth.oidc.provider_url': 'OPENID_PROVIDER_URL', + 'oauth.oidc.redirect_uri': 'OPENID_REDIRECT_URI', + 'oauth.oidc.scopes': 'OAUTH_SCOPES', + 'oauth.oidc.sub_claim': 'OAUTH_SUB_CLAIM', + 'oauth.oidc.token_endpoint_auth_method': 'OAUTH_TOKEN_ENDPOINT_AUTH_METHOD', + 'oauth.oidc.username_claim': 'OAUTH_USERNAME_CLAIM', + # OAuth — provider-specific + 'oauth.feishu.client_id': 'FEISHU_CLIENT_ID', + 'oauth.feishu.client_secret': 'FEISHU_CLIENT_SECRET', + 'oauth.feishu.redirect_uri': 'FEISHU_REDIRECT_URI', + 'oauth.feishu.scope': 'FEISHU_OAUTH_SCOPE', + 'oauth.github.client_id': 'GITHUB_CLIENT_ID', + 'oauth.github.client_secret': 'GITHUB_CLIENT_SECRET', + 'oauth.github.redirect_uri': 'GITHUB_CLIENT_REDIRECT_URI', + 'oauth.github.scope': 'GITHUB_CLIENT_SCOPE', + 'oauth.google.client_id': 'GOOGLE_CLIENT_ID', + 'oauth.google.client_secret': 'GOOGLE_CLIENT_SECRET', + 'oauth.google.redirect_uri': 'GOOGLE_REDIRECT_URI', + 'oauth.google.scope': 'GOOGLE_OAUTH_SCOPE', + 'oauth.microsoft.client_id': 'MICROSOFT_CLIENT_ID', + 'oauth.microsoft.client_secret': 'MICROSOFT_CLIENT_SECRET', + 'oauth.microsoft.login_base_url': 'MICROSOFT_CLIENT_LOGIN_BASE_URL', + 'oauth.microsoft.picture_url': 'MICROSOFT_CLIENT_PICTURE_URL', + 'oauth.microsoft.redirect_uri': 'MICROSOFT_REDIRECT_URI', + 'oauth.microsoft.scope': 'MICROSOFT_OAUTH_SCOPE', + 'oauth.microsoft.tenant_id': 'MICROSOFT_CLIENT_TENANT_ID', + # Ollama / OpenAI + 'ollama.api_configs': 'OLLAMA_API_CONFIGS', + 'ollama.base_urls': 'OLLAMA_BASE_URLS', + 'ollama.enable': 'ENABLE_OLLAMA_API', + 'onedrive.enable': 'ENABLE_ONEDRIVE_INTEGRATION', + 'onedrive.sharepoint_tenant_id': 'ONEDRIVE_SHAREPOINT_TENANT_ID', + 'onedrive.sharepoint_url': 'ONEDRIVE_SHAREPOINT_URL', + 'openai.api_base_urls': 'OPENAI_API_BASE_URLS', + 'openai.api_configs': 'OPENAI_API_CONFIGS', + 'openai.api_keys': 'OPENAI_API_KEYS', + 'openai.enable': 'ENABLE_OPENAI_API', + # RAG + 'rag.content_extraction_engine': 'CONTENT_EXTRACTION_ENGINE', + 'rag.datalab_marker_use_llm': 'DATALAB_MARKER_USE_LLM', + 'rag.mistral_ocr_api_base_url': 'MISTRAL_OCR_API_BASE_URL', + 'rag.azure_openai.api_key': 'RAG_AZURE_OPENAI_API_KEY', + 'rag.azure_openai.api_version': 'RAG_AZURE_OPENAI_API_VERSION', + 'rag.azure_openai.base_url': 'RAG_AZURE_OPENAI_BASE_URL', + 'rag.bypass_embedding_and_retrieval': 'BYPASS_EMBEDDING_AND_RETRIEVAL', + 'rag.chunk_min_size_target': 'CHUNK_MIN_SIZE_TARGET', + 'rag.chunk_overlap': 'CHUNK_OVERLAP', + 'rag.chunk_size': 'CHUNK_SIZE', + 'rag.datalab_marker_additional_config': 'DATALAB_MARKER_ADDITIONAL_CONFIG', + 'rag.datalab_marker_api_base_url': 'DATALAB_MARKER_API_BASE_URL', + 'rag.datalab_marker_api_key': 'DATALAB_MARKER_API_KEY', + 'rag.datalab_marker_disable_image_extraction': 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION', + 'rag.datalab_marker_force_ocr': 'DATALAB_MARKER_FORCE_OCR', + 'rag.datalab_marker_format_lines': 'DATALAB_MARKER_FORMAT_LINES', + 'rag.datalab_marker_output_format': 'DATALAB_MARKER_OUTPUT_FORMAT', + 'rag.datalab_marker_paginate': 'DATALAB_MARKER_PAGINATE', + 'rag.datalab_marker_skip_cache': 'DATALAB_MARKER_SKIP_CACHE', + 'rag.datalab_marker_strip_existing_ocr': 'DATALAB_MARKER_STRIP_EXISTING_OCR', + 'rag.docling_api_key': 'DOCLING_API_KEY', + 'rag.docling_params': 'DOCLING_PARAMS', + 'rag.docling_server_url': 'DOCLING_SERVER_URL', + 'rag.document_intelligence_endpoint': 'DOCUMENT_INTELLIGENCE_ENDPOINT', + 'rag.document_intelligence_key': 'DOCUMENT_INTELLIGENCE_KEY', + 'rag.document_intelligence_model': 'DOCUMENT_INTELLIGENCE_MODEL', + 'rag.embedding_batch_size': 'RAG_EMBEDDING_BATCH_SIZE', + 'rag.embedding_concurrent_requests': 'RAG_EMBEDDING_CONCURRENT_REQUESTS', + 'rag.embedding_engine': 'RAG_EMBEDDING_ENGINE', + 'rag.embedding_model': 'RAG_EMBEDDING_MODEL', + 'rag.enable_async_embedding': 'ENABLE_ASYNC_EMBEDDING', + 'rag.enable_hybrid_search': 'ENABLE_RAG_HYBRID_SEARCH', + 'rag.enable_hybrid_search_enriched_texts': 'ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS', + 'rag.enable_markdown_header_text_splitter': 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER', + 'rag.external_document_loader_api_key': 'EXTERNAL_DOCUMENT_LOADER_API_KEY', + 'rag.external_document_loader_url': 'EXTERNAL_DOCUMENT_LOADER_URL', + 'rag.external_reranker_api_key': 'RAG_EXTERNAL_RERANKER_API_KEY', + 'rag.external_reranker_timeout': 'RAG_EXTERNAL_RERANKER_TIMEOUT', + 'rag.external_reranker_url': 'RAG_EXTERNAL_RERANKER_URL', + 'rag.file.allowed_extensions': 'RAG_ALLOWED_FILE_EXTENSIONS', + 'rag.file.max_count': 'RAG_FILE_MAX_COUNT', + 'rag.file.max_size': 'RAG_FILE_MAX_SIZE', + 'rag.full_context': 'RAG_FULL_CONTEXT', + 'rag.hybrid_bm25_weight': 'RAG_HYBRID_BM25_WEIGHT', + 'rag.mineru_api_key': 'MINERU_API_KEY', + 'rag.mineru_api_mode': 'MINERU_API_MODE', + 'rag.mineru_api_timeout': 'MINERU_API_TIMEOUT', + 'rag.mineru_api_url': 'MINERU_API_URL', + 'rag.mineru_file_extensions': 'MINERU_FILE_EXTENSIONS', + 'rag.mineru_params': 'MINERU_PARAMS', + 'rag.mistral_ocr_api_key': 'MISTRAL_OCR_API_KEY', + 'rag.ollama.key': 'RAG_OLLAMA_API_KEY', + 'rag.ollama.url': 'RAG_OLLAMA_BASE_URL', + 'rag.openai_api_base_url': 'RAG_OPENAI_API_BASE_URL', + 'rag.openai_api_key': 'RAG_OPENAI_API_KEY', + 'rag.paddleocr_vl_base_url': 'PADDLEOCR_VL_BASE_URL', + 'rag.paddleocr_vl_token': 'PADDLEOCR_VL_TOKEN', + 'rag.pdf_extract_images': 'PDF_EXTRACT_IMAGES', + 'rag.pdf_loader_mode': 'PDF_LOADER_MODE', + 'rag.relevance_threshold': 'RAG_RELEVANCE_THRESHOLD', + 'rag.reranking_batch_size': 'RAG_RERANKING_BATCH_SIZE', + 'rag.reranking_engine': 'RAG_RERANKING_ENGINE', + 'rag.reranking_model': 'RAG_RERANKING_MODEL', + 'rag.template': 'RAG_TEMPLATE', + 'rag.text_splitter': 'RAG_TEXT_SPLITTER', + 'rag.tika_server_url': 'TIKA_SERVER_URL', + 'rag.tiktoken_encoding_name': 'TIKTOKEN_ENCODING_NAME', + 'rag.top_k': 'RAG_TOP_K', + 'rag.top_k_reranker': 'RAG_TOP_K_RERANKER', + # RAG — Web + 'rag.web.fetch.max_content_length': 'WEB_FETCH_MAX_CONTENT_LENGTH', + 'rag.web.loader.concurrent_requests': 'WEB_LOADER_CONCURRENT_REQUESTS', + 'rag.web.loader.engine': 'WEB_LOADER_ENGINE', + 'rag.web.loader.external_web_loader_api_key': 'EXTERNAL_WEB_LOADER_API_KEY', + 'rag.web.loader.external_web_loader_url': 'EXTERNAL_WEB_LOADER_URL', + 'rag.web.loader.firecrawl_api_key': 'FIRECRAWL_API_KEY', + 'rag.web.loader.firecrawl_api_url': 'FIRECRAWL_API_BASE_URL', + 'rag.web.loader.firecrawl_timeout': 'FIRECRAWL_TIMEOUT', + 'rag.web.loader.playwright_timeout': 'PLAYWRIGHT_TIMEOUT', + 'rag.web.loader.playwright_ws_url': 'PLAYWRIGHT_WS_URL', + 'rag.web.loader.ssl_verification': 'ENABLE_WEB_LOADER_SSL_VERIFICATION', + 'rag.web.loader.timeout': 'WEB_LOADER_TIMEOUT', + 'rag.web.search.azure_ai_search_api_key': 'AZURE_AI_SEARCH_API_KEY', + 'rag.web.search.azure_ai_search_endpoint': 'AZURE_AI_SEARCH_ENDPOINT', + 'rag.web.search.azure_ai_search_index_name': 'AZURE_AI_SEARCH_INDEX_NAME', + 'rag.web.search.bing_search_v7_endpoint': 'BING_SEARCH_V7_ENDPOINT', + 'rag.web.search.bing_search_v7_subscription_key': 'BING_SEARCH_V7_SUBSCRIPTION_KEY', + 'rag.web.search.bocha_search_api_key': 'BOCHA_SEARCH_API_KEY', + 'rag.web.search.brave_search_api_key': 'BRAVE_SEARCH_API_KEY', + 'rag.web.search.brave_search_context_tokens': 'BRAVE_SEARCH_CONTEXT_TOKENS', + 'rag.web.search.bypass_embedding_and_retrieval': 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL', + 'rag.web.search.bypass_web_loader': 'BYPASS_WEB_SEARCH_WEB_LOADER', + 'rag.web.search.concurrent_requests': 'WEB_SEARCH_CONCURRENT_REQUESTS', + 'rag.web.search.ddgs_backend': 'DDGS_BACKEND', + 'rag.web.search.domain.filter_list': 'WEB_SEARCH_DOMAIN_FILTER_LIST', + 'rag.web.search.enable': 'ENABLE_WEB_SEARCH', + 'rag.web.search.engine': 'WEB_SEARCH_ENGINE', + 'rag.web.search.exa_api_key': 'EXA_API_KEY', + 'rag.web.search.external_web_search_api_key': 'EXTERNAL_WEB_SEARCH_API_KEY', + 'rag.web.search.external_web_search_url': 'EXTERNAL_WEB_SEARCH_URL', + 'rag.web.search.google_pse_api_key': 'GOOGLE_PSE_API_KEY', + 'rag.web.search.google_pse_engine_id': 'GOOGLE_PSE_ENGINE_ID', + 'rag.web.search.jina_api_base_url': 'JINA_API_BASE_URL', + 'rag.web.search.jina_api_key': 'JINA_API_KEY', + 'rag.web.search.kagi_search_api_key': 'KAGI_SEARCH_API_KEY', + 'rag.web.search.linkup_api_key': 'LINKUP_API_KEY', + 'rag.web.search.linkup_search_params': 'LINKUP_SEARCH_PARAMS', + 'rag.web.search.mojeek_search_api_key': 'MOJEEK_SEARCH_API_KEY', + 'rag.web.search.ollama_cloud_api_key': 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY', + 'rag.web.search.perplexity_api_key': 'PERPLEXITY_API_KEY', + 'rag.web.search.perplexity_model': 'PERPLEXITY_MODEL', + 'rag.web.search.perplexity_search_api_url': 'PERPLEXITY_SEARCH_API_URL', + 'rag.web.search.perplexity_search_context_usage': 'PERPLEXITY_SEARCH_CONTEXT_USAGE', + 'rag.web.search.result_count': 'WEB_SEARCH_RESULT_COUNT', + 'rag.web.search.searchapi_api_key': 'SEARCHAPI_API_KEY', + 'rag.web.search.searchapi_engine': 'SEARCHAPI_ENGINE', + 'rag.web.search.searxng_language': 'SEARXNG_LANGUAGE', + 'rag.web.search.searxng_query_url': 'SEARXNG_QUERY_URL', + 'rag.web.search.serpapi_api_key': 'SERPAPI_API_KEY', + 'rag.web.search.serpapi_engine': 'SERPAPI_ENGINE', + 'rag.web.search.serper_api_key': 'SERPER_API_KEY', + 'rag.web.search.serply_api_key': 'SERPLY_API_KEY', + 'rag.web.search.serpstack_api_key': 'SERPSTACK_API_KEY', + 'rag.web.search.serpstack_https': 'SERPSTACK_HTTPS', + 'rag.web.search.sougou_api_sid': 'SOUGOU_API_SID', + 'rag.web.search.sougou_api_sk': 'SOUGOU_API_SK', + 'rag.web.search.tavily_api_key': 'TAVILY_API_KEY', + 'rag.web.search.tavily_extract_depth': 'TAVILY_EXTRACT_DEPTH', + 'rag.web.search.trust_env': 'WEB_SEARCH_TRUST_ENV', + 'rag.web.search.yacy_password': 'YACY_PASSWORD', + 'rag.web.search.yacy_query_url': 'YACY_QUERY_URL', + 'rag.web.search.yacy_username': 'YACY_USERNAME', + 'rag.web.search.yandex_web_search_api_key': 'YANDEX_WEB_SEARCH_API_KEY', + 'rag.web.search.yandex_web_search_config': 'YANDEX_WEB_SEARCH_CONFIG', + 'rag.web.search.yandex_web_search_url': 'YANDEX_WEB_SEARCH_URL', + 'rag.web.search.youcom_api_key': 'YOUCOM_API_KEY', + 'rag.youtube_loader_language': 'YOUTUBE_LOADER_LANGUAGE', + 'rag.youtube_loader_proxy_url': 'YOUTUBE_LOADER_PROXY_URL', + # Tasks + 'task.autocomplete.enable': 'ENABLE_AUTOCOMPLETE_GENERATION', + 'task.autocomplete.input_max_length': 'AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH', + 'task.autocomplete.prompt_template': 'AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE', + 'task.follow_up.enable': 'ENABLE_FOLLOW_UP_GENERATION', + 'task.follow_up.prompt_template': 'FOLLOW_UP_GENERATION_PROMPT_TEMPLATE', + 'task.image.prompt_template': 'IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE', + 'task.model.default': 'TASK_MODEL', + 'task.model.external': 'TASK_MODEL_EXTERNAL', + 'task.query.prompt_template': 'QUERY_GENERATION_PROMPT_TEMPLATE', + 'task.query.retrieval.enable': 'ENABLE_RETRIEVAL_QUERY_GENERATION', + 'task.query.search.enable': 'ENABLE_SEARCH_QUERY_GENERATION', + 'task.tags.enable': 'ENABLE_TAGS_GENERATION', + 'task.tags.prompt_template': 'TAGS_GENERATION_PROMPT_TEMPLATE', + 'task.title.enable': 'ENABLE_TITLE_GENERATION', + 'task.title.prompt_template': 'TITLE_GENERATION_PROMPT_TEMPLATE', + 'task.tools.prompt_template': 'TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE', + 'task.voice.prompt.enable': 'ENABLE_VOICE_MODE_PROMPT', + 'task.voice.prompt_template': 'VOICE_MODE_PROMPT_TEMPLATE', + # Misc + 'terminal_server.connections': 'TERMINAL_SERVER_CONNECTIONS', + 'tool_server.connections': 'TOOL_SERVER_CONNECTIONS', + 'ui.banners': 'WEBUI_BANNERS', + 'ui.default_group_id': 'DEFAULT_GROUP_ID', + 'ui.default_locale': 'DEFAULT_LOCALE', + 'ui.default_models': 'DEFAULT_MODELS', + 'ui.default_pinned_models': 'DEFAULT_PINNED_MODELS', + 'ui.default_user_role': 'DEFAULT_USER_ROLE', + 'ui.enable_community_sharing': 'ENABLE_COMMUNITY_SHARING', + 'ui.enable_login_form': 'ENABLE_LOGIN_FORM', + 'ui.enable_message_rating': 'ENABLE_MESSAGE_RATING', + 'ui.enable_password_change_form': 'ENABLE_PASSWORD_CHANGE_FORM', + 'ui.enable_signup': 'ENABLE_SIGNUP', + 'ui.enable_user_webhooks': 'ENABLE_USER_WEBHOOKS', + 'ui.model_order_list': 'MODEL_ORDER_LIST', + 'ui.pending_user_overlay_content': 'PENDING_USER_OVERLAY_CONTENT', + 'ui.pending_user_overlay_title': 'PENDING_USER_OVERLAY_TITLE', + 'ui.prompt_suggestions': 'DEFAULT_PROMPT_SUGGESTIONS', + 'ui.watermark': 'RESPONSE_WATERMARK', + 'user.permissions': 'USER_PERMISSIONS', + 'users.enable_status': 'ENABLE_USER_STATUS', + 'webhook_url': 'WEBHOOK_URL', + 'webui.url': 'WEBUI_URL', +} + + +STORAGE_KEY_REWRITES = { + 'oauth.refresh_token_include_scope': 'oauth.refresh_token.include_scope', + 'rag.openai_api_base_url': 'rag.openai.api_base_url', + 'rag.openai_api_key': 'rag.openai.api_key', + 'rag.ollama.url': 'rag.ollama.base_url', + 'rag.ollama.key': 'rag.ollama.api_key', + 'oauth.oidc.avatar_claim': 'oauth.picture_claim', + 'oauth.oidc.client_id': 'oauth.client_id', + 'oauth.oidc.client_secret': 'oauth.client_secret', + 'oauth.oidc.code_challenge_method': 'oauth.code_challenge_method', + 'oauth.oidc.email_claim': 'oauth.email_claim', + 'oauth.oidc.end_session_endpoint': 'oauth.end_session_endpoint', + 'oauth.oidc.group_claim': 'oauth.group_claim', + 'oauth.oidc.oauth_timeout': 'oauth.timeout', + 'oauth.oidc.provider_name': 'oauth.provider_name', + 'oauth.oidc.provider_url': 'oauth.provider_url', + 'oauth.oidc.redirect_uri': 'oauth.redirect_uri', + 'oauth.oidc.scopes': 'oauth.scopes', + 'oauth.oidc.sub_claim': 'oauth.sub_claim', + 'oauth.oidc.token_endpoint_auth_method': 'oauth.token_endpoint_auth_method', + 'oauth.oidc.username_claim': 'oauth.username_claim', +} + + +LEGACY_KEY_TO_STORAGE_KEY = { + legacy_key: STORAGE_KEY_REWRITES.get(blob_path, blob_path) for blob_path, legacy_key in BLOB_PATH_TO_KEY.items() +} + + +def _walk_blob(data: dict, prefix: str = '') -> dict: + """Recursively walk a nested config blob, preserving known config values. + + Some config values are intentionally dictionaries, e.g. OPENAI_API_CONFIGS + and OLLAMA_API_CONFIGS. Once the current path is a known config key, keep + that value intact instead of flattening its internals into orphaned rows. + """ + result = {} + for key, value in data.items(): + path = f'{prefix}{key}' if not prefix else f'{prefix}.{key}' + if path in BLOB_PATH_TO_KEY or path in LEGACY_KEY_TO_STORAGE_KEY: + result[path] = value + elif isinstance(value, dict): + result.update(_walk_blob(value, path)) + else: + result[path] = value + return result + + +def upgrade() -> None: + """Reshape config from single-row JSON blob to per-key rows.""" + conn = op.get_bind() + inspector = sa.inspect(conn) + table_names = set(inspector.get_table_names()) + config_columns = ( + {column['name'] for column in inspector.get_columns('config')} if 'config' in table_names else set() + ) + has_old_config = {'id', 'data'}.issubset(config_columns) + has_new_config = {'key', 'value'}.issubset(config_columns) + + # Ad-hoc table reference for reading the old schema + old_config = sa.table( + 'config', + sa.column('id', sa.Integer), + sa.column('data', sa.JSON), + ) + + # 1. Read existing blob + blob_data = {} + if has_old_config: + try: + result = conn.execute(sa.select(old_config.c.data).order_by(old_config.c.id.desc()).limit(1)) + row = result.fetchone() + if row and row[0]: + raw = row[0] + blob_data = json.loads(raw) if isinstance(raw, str) else raw + except Exception: + pass # Table might be partially migrated or empty + + # 2. Preserve old blob table for rollback/inspection, then create per-key table. + if has_old_config: + if 'config_old' in table_names: + op.drop_table('config_old') + op.rename_table('config', 'config_old') + + # 3. Create new per-key table + new_config = ( + sa.table( + 'config', + sa.column('key', sa.Text), + sa.column('value', sa.JSON()), + sa.column('updated_at', sa.BigInteger), + ) + if has_new_config + else op.create_table( + 'config', + sa.Column('key', sa.Text(), primary_key=True), + sa.Column('value', sa.JSON(), nullable=False), + sa.Column('updated_at', sa.BigInteger(), nullable=True), + ) + ) + + # 4. Flatten blob and insert per-key rows + if blob_data: + flat = _walk_blob(blob_data) + + # Keep stable dot-notation paths as the database keys. + # Known legacy env-style keys are rewritten to their dotted keys; unknown + # keys are still copied so custom/future config is not silently lost. + rows = {} + for blob_path, value in flat.items(): + if blob_path in BLOB_PATH_TO_KEY: + storage_key = STORAGE_KEY_REWRITES.get(blob_path, blob_path) + elif blob_path in LEGACY_KEY_TO_STORAGE_KEY: + storage_key = LEGACY_KEY_TO_STORAGE_KEY[blob_path] + else: + storage_key = STORAGE_KEY_REWRITES.get(blob_path, blob_path) + + if storage_key not in rows: + rows[storage_key] = value + + # Batch insert via SQLAlchemy table reference + if rows: + now = int(time.time()) + op.bulk_insert( + new_config, + [{'key': k, 'value': v, 'updated_at': now} for k, v in rows.items()], + ) + + +def downgrade() -> None: + """Restore preserved old single-row config table when available.""" + conn = op.get_bind() + inspector = sa.inspect(conn) + table_names = set(inspector.get_table_names()) + + if 'config_old' in table_names: + if 'config' in table_names: + op.drop_table('config') + op.rename_table('config_old', 'config') + return + + config_columns = ( + {column['name'] for column in inspector.get_columns('config')} if 'config' in table_names else set() + ) + has_per_key_config = {'key', 'value'}.issubset(config_columns) + + blob_data = {} + if has_per_key_config: + config = sa.table( + 'config', + sa.column('key', sa.Text), + sa.column('value', sa.JSON), + ) + for key, value in conn.execute(sa.select(config.c.key, config.c.value)): + blob_data[key] = json.loads(value) if isinstance(value, str) else value + op.drop_table('config') + + if 'config' in table_names and not has_per_key_config: + return + + old_config = op.create_table( + 'config', + sa.Column('id', sa.Integer(), primary_key=True), + sa.Column('data', sa.JSON(), nullable=False), + sa.Column('version', sa.Integer(), nullable=False, server_default='0'), + sa.Column('created_at', sa.DateTime(), nullable=False, server_default=sa.func.now()), + sa.Column('updated_at', sa.DateTime(), nullable=True), + ) + + if blob_data: + op.bulk_insert(old_config, [{'data': blob_data, 'version': 0}]) diff --git a/backend/open_webui/migrations/versions/42e2978c7933_add_memory_path_and_meta.py b/backend/open_webui/migrations/versions/42e2978c7933_add_memory_path_and_meta.py new file mode 100644 index 0000000000..fc10262090 --- /dev/null +++ b/backend/open_webui/migrations/versions/42e2978c7933_add_memory_path_and_meta.py @@ -0,0 +1,40 @@ +"""add memory path and meta + +Revision ID: 42e2978c7933 +Revises: 7b3f2a9c1d4e +Create Date: 2026-06-29 05:35:50.565887 + +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +revision: str = '42e2978c7933' +down_revision: Union[str, None] = '7b3f2a9c1d4e' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('memory')} + + if 'path' not in columns: + op.add_column('memory', sa.Column('path', sa.Text(), nullable=True)) + if 'meta' not in columns: + op.add_column('memory', sa.Column('meta', sa.JSON(), nullable=True)) + + +def downgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('memory')} + + if 'meta' in columns: + op.drop_column('memory', 'meta') + if 'path' in columns: + op.drop_column('memory', 'path') diff --git a/backend/open_webui/migrations/versions/4c5ce3d2f27f_add_context_summary_to_chat_message.py b/backend/open_webui/migrations/versions/4c5ce3d2f27f_add_context_summary_to_chat_message.py new file mode 100644 index 0000000000..31a693cac6 --- /dev/null +++ b/backend/open_webui/migrations/versions/4c5ce3d2f27f_add_context_summary_to_chat_message.py @@ -0,0 +1,37 @@ +"""add context summary to chat message + +Revision ID: 4c5ce3d2f27f +Revises: 3ff2c63645b8 +Create Date: 2026-06-18 23:48:08.310063 + +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '4c5ce3d2f27f' +down_revision: Union[str, None] = '3ff2c63645b8' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('chat_message')} + + if 'context_summary' not in columns: + op.add_column('chat_message', sa.Column('context_summary', sa.Text(), nullable=True)) + + +def downgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('chat_message')} + + if 'context_summary' in columns: + op.drop_column('chat_message', 'context_summary') diff --git a/backend/open_webui/migrations/versions/7b3f2a9c1d4e_add_memory_type.py b/backend/open_webui/migrations/versions/7b3f2a9c1d4e_add_memory_type.py new file mode 100644 index 0000000000..ca01fbef8f --- /dev/null +++ b/backend/open_webui/migrations/versions/7b3f2a9c1d4e_add_memory_type.py @@ -0,0 +1,44 @@ +"""add memory type + +Revision ID: 7b3f2a9c1d4e +Revises: 4c5ce3d2f27f +Create Date: 2026-06-25 00:00:00.000000 + +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +revision: str = '7b3f2a9c1d4e' +down_revision: Union[str, None] = '4c5ce3d2f27f' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('memory')} + indexes = {index['name'] for index in inspector.get_indexes('memory')} + + if 'type' not in columns: + op.add_column('memory', sa.Column('type', sa.String(), server_default='context', nullable=False)) + + if 'ix_memory_type' not in indexes: + op.create_index('ix_memory_type', 'memory', ['type']) + + +def downgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + columns = {column['name'] for column in inspector.get_columns('memory')} + indexes = {index['name'] for index in inspector.get_indexes('memory')} + + if 'ix_memory_type' in indexes: + op.drop_index('ix_memory_type', table_name='memory') + + if 'type' in columns: + op.drop_column('memory', 'type') diff --git a/backend/open_webui/models/auths.py b/backend/open_webui/models/auths.py index 5e363352bd..6538c1dbf9 100644 --- a/backend/open_webui/models/auths.py +++ b/backend/open_webui/models/auths.py @@ -6,6 +6,7 @@ import logging import uuid from typing import Optional +import bcrypt from open_webui.internal.db import Base, JSONField, get_async_db_context from open_webui.models.users import User, UserModel, UserProfileImageResponse, Users from open_webui.utils.validate import validate_profile_image_url @@ -15,6 +16,11 @@ from sqlalchemy.ext.asyncio import AsyncSession log = logging.getLogger(__name__) +# Pre-computed hash verified on signin paths that lack a real credential +# (unknown user, inactive account) so response timing cannot reveal +# whether an account exists (CWE-208). +PLACEHOLDER_HASH = bcrypt.hashpw(b'placeholder', bcrypt.gensalt()).decode('utf-8') + class Auth(Base): # credential ↔ user linkage """Maps a user ID to an email/password pair with an active flag.""" @@ -142,13 +148,15 @@ class AuthsTable: log.info('authenticate_user: %s', email) resolved = await Users.get_user_by_email(email, db=db) if not resolved: + await verify_password(PLACEHOLDER_HASH) return # load the credential row and verify the password hash async with get_async_db_context(db) as session: credential = await session.get(Auth, resolved.id) if not credential or not credential.active: + await verify_password(PLACEHOLDER_HASH) return - if not verify_password(credential.password): + if not await verify_password(credential.password): return return resolved diff --git a/backend/open_webui/models/chat_messages.py b/backend/open_webui/models/chat_messages.py index 8660e1e987..5579bdbe95 100644 --- a/backend/open_webui/models/chat_messages.py +++ b/backend/open_webui/models/chat_messages.py @@ -3,8 +3,10 @@ import time import uuid from typing import Any, Optional +from sqlalchemy import select, delete, func, cast, Integer, distinct +from sqlalchemy.ext.asyncio import AsyncSession from open_webui.internal.db import Base, get_async_db_context -from open_webui.utils.response import normalize_usage +from open_webui.utils.response import merge_usage, normalize_usage from pydantic import BaseModel, ConfigDict from sqlalchemy import ( JSON, @@ -107,6 +109,9 @@ class ChatMessage(Base): # Usage (tokens, timing, etc.) usage = Column(JSON, nullable=True) + # Context compaction checkpoint + context_summary = Column(Text, nullable=True) + # Timestamps created_at = Column(BigInteger, index=True) updated_at = Column(BigInteger) @@ -141,6 +146,7 @@ class ChatMessageModel(BaseModel): status_history: Optional[list] = None error: Optional[dict | str] = None usage: Optional[dict] = None + context_summary: Optional[str] = None created_at: int updated_at: int @@ -192,13 +198,13 @@ class ChatMessageTable: existing.status_history = data.get('status_history') or data.get('statusHistory') if 'error' in data: existing.error = data.get('error') + if 'context_summary' in data or 'contextSummary' in data: + existing.context_summary = data.get('context_summary') or data.get('contextSummary') # Extract and normalize usage usage = get_usage(data) if usage: - # Deep-merge: preserve existing keys not present in new data - # This prevents background tasks (follow-ups, title, tags) - # from accidentally clearing the primary response's token counts - existing.usage = {**(existing.usage or {}), **usage} + existing_usage = normalize_usage(existing.usage or {}) if existing.usage else {} + existing.usage = existing_usage if usage == existing_usage else merge_usage(existing_usage, usage) existing.updated_at = now await db.commit() await db.refresh(existing) @@ -223,6 +229,7 @@ class ChatMessageTable: status_history=data.get('status_history') or data.get('statusHistory'), error=data.get('error'), usage=usage, + context_summary=data.get('context_summary') or data.get('contextSummary'), created_at=timestamp, updated_at=now, ) @@ -249,6 +256,7 @@ class ChatMessageTable: 'parent_id': 'parentId', 'model_id': 'model', 'status_history': 'statusHistory', + 'context_summary': 'contextSummary', 'created_at': 'timestamp', } # DB-internal columns excluded from the reconstructed message dict. @@ -440,6 +448,44 @@ class ChatMessageTable: result = await db.execute(stmt) return {row.model_id: row.count for row in result.all()} + async def get_unique_counts_by_model( + self, + start_date: Optional[int] = None, + end_date: Optional[int] = None, + group_id: Optional[str] = None, + db: Optional[AsyncSession] = None, + ) -> dict[str, dict]: + """Count distinct users and chats per model.""" + async with get_async_db_context(db) as db: + from open_webui.models.groups import GroupMember + + stmt = select( + ChatMessage.model_id, + func.count(distinct(ChatMessage.user_id)).label('unique_users'), + func.count(distinct(ChatMessage.chat_id)).label('unique_chats'), + ).filter( + ChatMessage.role == 'assistant', + ChatMessage.model_id.isnot(None), + ) + + if start_date: + stmt = stmt.filter(ChatMessage.created_at >= start_date) + if end_date: + stmt = stmt.filter(ChatMessage.created_at <= end_date) + if group_id: + group_users = select(GroupMember.user_id).filter(GroupMember.group_id == group_id).scalar_subquery() + stmt = stmt.filter(ChatMessage.user_id.in_(group_users)) + + stmt = stmt.group_by(ChatMessage.model_id) + result = await db.execute(stmt) + return { + row.model_id: { + 'unique_users': row.unique_users, + 'unique_chats': row.unique_chats, + } + for row in result.all() + } + async def get_token_usage_by_model( self, start_date: Optional[int] = None, diff --git a/backend/open_webui/models/chats.py b/backend/open_webui/models/chats.py index f237ce58f7..52981d7e3f 100644 --- a/backend/open_webui/models/chats.py +++ b/backend/open_webui/models/chats.py @@ -34,6 +34,7 @@ from sqlalchemy import ( update, ) from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm.attributes import flag_modified from sqlalchemy.sql import exists from sqlalchemy.sql.expression import bindparam @@ -179,6 +180,7 @@ class ChatTitleIdResponse(BaseModel): updated_at: int created_at: int last_read_at: int | None = None + snippet: str | None = None class SharedChatResponse(BaseModel): @@ -294,6 +296,58 @@ class ChatTable: return changed + def _repair_chat_current_id(self, chat: dict) -> bool: + history = chat.get('history') + if not isinstance(history, dict): + return False + + messages = history.get('messages') + if not isinstance(messages, dict): + return False + + current_id = history.get('currentId') + current_message = messages.get(current_id) + output = [] + if isinstance(current_message, dict): + output = current_message.get('output') or [] + + output_role = next( + (item.get('role') for item in output if isinstance(item, dict) and item.get('role')), + None, + ) + current_is_bad_leaf = ( + isinstance(current_message, dict) + and output_role == 'assistant' + and current_message.get('parentId') is None + and not current_message.get('timestamp') + and len(messages) > 1 + ) + if ( + isinstance(current_message, dict) + and current_message.get('id') + and current_message.get('role') + and not current_is_bad_leaf + ): + return False + + latest_leaf_id = None + latest_timestamp = -1 + for message_id, message in messages.items(): + if not isinstance(message, dict) or not message.get('role'): + continue + + children_ids = message.get('childrenIds') if isinstance(message.get('childrenIds'), list) else [] + timestamp = message.get('timestamp') or 0 + if len(children_ids) == 0 and timestamp > latest_timestamp: + latest_leaf_id = message_id + latest_timestamp = timestamp + + if not latest_leaf_id or latest_leaf_id == current_id: + return False + + history['currentId'] = latest_leaf_id + return True + async def insert_new_chat( self, id: str, user_id: str, form_data: ChatForm, db: AsyncSession | None = None ) -> ChatModel | None: @@ -309,6 +363,7 @@ class ChatTable: 'folder_id': form_data.folder_id, 'created_at': int(time.time()), 'updated_at': int(time.time()), + 'last_read_at': int(time.time()), } ) @@ -445,7 +500,6 @@ class ChatTable: clean_title = self._clean_null_bytes(title) chat_item.title = clean_title chat_item.chat = {**(chat_item.chat or {}), 'title': clean_title} - chat_item.updated_at = int(time.time()) await session.commit() await session.refresh(chat_item) return ChatModel.model_validate(chat_item) @@ -497,6 +551,68 @@ class ChatTable: if msg.get('parentId') and msg['parentId'] not in messages_map } + @staticmethod + def merge_history(existing_history: dict | None, incoming_history: dict | None) -> dict: + existing = (existing_history or {}).get('messages') or {} + incoming = (incoming_history or {}).get('messages') or {} + merged = {**existing, **incoming} + merged = {message_id: message for message_id, message in merged.items() if isinstance(message, dict)} + + for message in merged.values(): + message['childrenIds'] = [] + for message_id, message in merged.items(): + parent_id = message.get('parentId') + if parent_id in merged: + merged[parent_id]['childrenIds'].append(message_id) + + current_id = (incoming_history or {}).get('currentId') + if current_id not in merged: + current_id = (existing_history or {}).get('currentId') + if current_id not in merged: + current_id = None + + return {**(existing_history or {}), **(incoming_history or {}), 'messages': merged, 'currentId': current_id} + + @staticmethod + def delete_message_from_history(history: dict, message_id: str) -> set[str]: + messages = history.get('messages') or {} + message = messages.get(message_id) + if not isinstance(message, dict): + return set() + + parent_id = message.get('parentId') + child_ids = [child_id for child_id in (message.get('childrenIds') or []) if child_id in messages] + grandchild_ids = [ + grandchild_id + for child_id in child_ids + for grandchild_id in (messages.get(child_id, {}).get('childrenIds') or []) + if grandchild_id in messages + ] + + if parent_id in messages: + messages[parent_id]['childrenIds'] = [ + child_id for child_id in (messages[parent_id].get('childrenIds') or []) if child_id != message_id + ] + grandchild_ids + + for grandchild_id in grandchild_ids: + messages[grandchild_id]['parentId'] = parent_id + + deleted_ids = {message_id, *child_ids} + for deleted_id in deleted_ids: + messages.pop(deleted_id, None) + + current_id = parent_id + child_ids = ( + [child_id for child_id, child in messages.items() if child.get('parentId') is None] + if current_id is None + else messages.get(current_id, {}).get('childrenIds', []) + ) + while child_ids: + current_id = child_ids[-1] + child_ids = messages.get(current_id, {}).get('childrenIds', []) + history['currentId'] = current_id if current_id in messages else None + return deleted_ids + async def backfill_messages_by_chat_id(self, chat_id: str, user_id: str, messages: dict[str, dict]) -> None: """Write messages to the ``chat_message`` table so future lookups use the fast path. Errors are logged but never raised. @@ -517,18 +633,11 @@ class ChatTable: async def reconcile_messages_by_chat_id(self, chat_id: str, user_id: str, messages: dict[str, dict]) -> None: """Sync ``chat_message`` rows with the committed JSON blob. - Upserts current messages via ``backfill_messages_by_chat_id`` - and deletes orphaned rows whose message_id no longer appears - in the blob. Best-effort: errors are logged but never raised. + Upserts current messages via ``backfill_messages_by_chat_id``. + Best-effort: errors are logged but never raised. """ try: await self.backfill_messages_by_chat_id(chat_id, user_id, messages) - - existing_map = await ChatMessages.get_messages_map_by_chat_id(chat_id) - if existing_map is not None: - orphaned_ids = set(existing_map.keys()) - set(messages.keys()) - if orphaned_ids: - await ChatMessages.delete_message_ids_by_chat_id(chat_id, orphaned_ids) except Exception as e: log.warning('Failed to reconcile chat_message rows for chat %s: %s', chat_id, e) @@ -606,14 +715,46 @@ class ChatTable: user_id = chat.user_id chat = chat.chat history = chat.get('history', {}) + messages = history.setdefault('messages', {}) - if message_id in history.get('messages', {}): - history['messages'][message_id] = { - **history['messages'][message_id], + if message_id in messages: + messages[message_id] = { + **messages[message_id], **message, } else: - history['messages'][message_id] = message + message_parent_id = message.get('parentId') + parent_id = message_parent_id + if parent_id is None: + for existing_id, existing_message in messages.items(): + if message_id in existing_message.get('childrenIds', []): + parent_id = existing_id + break + + parent = messages.get(parent_id) if parent_id else None + output = message.get('output') or [] + output_role = next( + (item.get('role') for item in output if isinstance(item, dict) and item.get('role')), + None, + ) + role = message.get('role') or output_role + if not role: + parent_role = parent.get('role') if parent else None + if parent_role == 'user': + role = 'assistant' + elif parent_role == 'assistant': + role = 'user' + else: + role = 'assistant' + + messages[message_id] = { + **message, + 'id': message.get('id') or message_id, + 'parentId': message_parent_id if message_parent_id is not None else parent_id, + 'childrenIds': message.get('childrenIds') if isinstance(message.get('childrenIds'), list) else [], + 'role': role, + 'timestamp': message.get('timestamp') or int(time.time()), + } history['currentId'] = message_id @@ -625,13 +766,33 @@ class ChatTable: message_id=message_id, chat_id=id, user_id=user_id, - data=history['messages'][message_id], + data=messages[message_id], ) except Exception as e: log.warning(f'Failed to write to chat_message table: {e}') return await self.update_chat_by_id(id, chat) + async def delete_message_from_chat_by_id_and_message_id(self, id: str, message_id: str) -> ChatModel | None: + chat_model = await self.get_chat_by_id(id) + if chat_model is None: + return None + + chat = chat_model.chat + history = chat.get('history', {}) + deleted_ids = self.delete_message_from_history(history, message_id) + if not deleted_ids: + return chat_model + + messages = history.get('messages') or {} + chat['history'] = history + updated_chat = await self.update_chat_by_id(id, chat) + + await self.backfill_messages_by_chat_id(id, chat_model.user_id, messages) + await ChatMessages.delete_message_ids_by_chat_id(id, deleted_ids) + + return updated_chat + async def add_message_status_to_chat_by_id_and_message_id( self, id: str, message_id: str, status: dict ) -> ChatModel | None: @@ -748,6 +909,7 @@ class ChatTable: chat = await session.get(Chat, id) chat.pinned = not chat.pinned chat.updated_at = int(time.time()) + chat.last_read_at = int(time.time()) await session.commit() await session.refresh(chat) return ChatModel.model_validate(chat) @@ -761,6 +923,7 @@ class ChatTable: chat.archived = not chat.archived chat.folder_id = None chat.updated_at = int(time.time()) + chat.last_read_at = int(time.time()) await session.commit() await session.refresh(chat) return ChatModel.model_validate(chat) @@ -829,6 +992,15 @@ class ChatTable: for chat in all_chats ] + async def count_archived_chats_by_user_id( + self, + user_id: str, + db: AsyncSession | None = None, + ) -> int: + async with get_async_db_context(db) as session: + result = await session.execute(select(func.count(Chat.id)).filter_by(user_id=user_id, archived=True)) + return result.scalar() or 0 + async def get_shared_chat_list_by_user_id( self, user_id: str, @@ -957,6 +1129,85 @@ class ChatTable: all_chats = result.scalars().all() return [ChatModel.model_validate(chat) for chat in all_chats] + async def get_chat_metas_by_chat_ids( + self, + chat_ids: list[str], + include_archived: bool = False, + db: AsyncSession | None = None, + ) -> list[dict]: + async with get_async_db_context(db) as session: + stmt = select(Chat.meta).filter(Chat.id.in_(chat_ids)) + if not include_archived: + stmt = stmt.filter_by(archived=False) + + result = await session.execute(stmt) + return [meta for meta in result.scalars().all() if isinstance(meta, dict)] + + async def get_chats_by_model_id( + self, + model_id: str, + filter: dict | None = None, + skip: int = 0, + limit: int = 50, + db: AsyncSession | None = None, + ) -> dict: + from open_webui.models.users import User + + async with get_async_db_context(db) as session: + chat_ids = ( + select(ChatMessage.chat_id).filter(ChatMessage.model_id == model_id).group_by(ChatMessage.chat_id) + ) + + if filter: + if filter.get('start_date'): + chat_ids = chat_ids.filter(ChatMessage.created_at >= filter.get('start_date')) + if filter.get('end_date'): + chat_ids = chat_ids.filter(ChatMessage.created_at <= filter.get('end_date')) + + chat_ids = chat_ids.subquery() + + stmt = ( + select(Chat.id, Chat.user_id, Chat.title, Chat.updated_at, User.name.label('user_name')) + .join(chat_ids, chat_ids.c.chat_id == Chat.id) + .outerjoin(User, User.id == Chat.user_id) + ) + + order_by = filter.get('order_by') if filter else None + direction = filter.get('direction') if filter else None + is_asc = direction == 'asc' + + if order_by == 'title': + primary_sort = Chat.title.asc() if is_asc else Chat.title.desc() + elif order_by == 'user_name': + primary_sort = User.name.asc() if is_asc else User.name.desc() + else: + primary_sort = Chat.updated_at.asc() if is_asc else Chat.updated_at.desc() + + stmt = stmt.order_by(primary_sort, Chat.id.asc()) + + count_result = await session.execute(select(func.count()).select_from(stmt.subquery())) + total = count_result.scalar() + + if skip: + stmt = stmt.offset(skip) + if limit: + stmt = stmt.limit(limit) + + result = await session.execute(stmt) + return { + 'items': [ + { + 'chat_id': chat.id, + 'user_id': chat.user_id, + 'user_name': chat.user_name, + 'first_message': chat.title, + 'updated_at': chat.updated_at, + } + for chat in result.all() + ], + 'total': total, + } + # retrieve conversation async def get_chat_by_id( self, @@ -970,7 +1221,10 @@ class ChatTable: if chat_item is None: return None - if self._sanitize_chat_row(chat_item): + repaired_history = self._repair_chat_current_id(chat_item.chat or {}) + if repaired_history: + flag_modified(chat_item, 'chat') + if self._sanitize_chat_row(chat_item) or repaired_history: await session.commit() await session.refresh(chat_item) @@ -1006,7 +1260,17 @@ class ChatTable: async with get_async_db_context(db) as session: result = await session.execute(select(Chat).filter_by(id=id, user_id=user_id)) chat = result.scalars().first() - return ChatModel.model_validate(chat) if chat else None + if not chat: + return None + + repaired_history = self._repair_chat_current_id(chat.chat or {}) + if repaired_history: + flag_modified(chat, 'chat') + if self._sanitize_chat_row(chat) or repaired_history: + await session.commit() + await session.refresh(chat) + + return ChatModel.model_validate(chat) except Exception: return None @@ -1353,6 +1617,42 @@ class ChatTable: for chat in all_chats ] + async def get_all_chats_by_folder_id( + self, + folder_id: str, + skip: int = 0, + limit: int = 60, + db: AsyncSession | None = None, + ) -> list[dict]: + """Get chats in a folder across ALL users. Returns dicts with user_id.""" + async with get_async_db_context(db) as session: + stmt = ( + select(Chat.id, Chat.title, Chat.user_id, Chat.updated_at, Chat.created_at, Chat.last_read_at) + .filter_by(folder_id=folder_id) + .filter(or_(Chat.pinned == False, Chat.pinned == None)) + .filter_by(archived=False) + .order_by(Chat.updated_at.desc(), Chat.id) + ) + + if skip: + stmt = stmt.offset(skip) + if limit: + stmt = stmt.limit(limit) + + result = await session.execute(stmt) + all_chats = result.all() + return [ + { + 'id': chat[0], + 'title': chat[1], + 'user_id': chat[2], + 'updated_at': chat[3], + 'created_at': chat[4], + 'last_read_at': chat[5], + } + for chat in all_chats + ] + async def get_chats_by_folder_ids_and_user_id( self, folder_ids: list[str], user_id: str, db: AsyncSession | None = None ) -> list[ChatModel]: @@ -1377,6 +1677,7 @@ class ChatTable: chat = await session.get(Chat, id) chat.folder_id = folder_id chat.updated_at = int(time.time()) + chat.last_read_at = int(time.time()) chat.pinned = False await session.commit() await session.refresh(chat) @@ -1521,6 +1822,21 @@ class ChatTable: log.info(f"Count of chats for folder '{folder_id}': {count}") return count + async def count_chats_by_folder_ids_and_user_id( + self, folder_ids: list[str], user_id: str, db: AsyncSession | None = None + ) -> int: + if not folder_ids: + return 0 + + async with get_async_db_context(db) as session: + result = await session.execute( + select(func.count(Chat.id)).filter(Chat.user_id == user_id, Chat.folder_id.in_(folder_ids)) + ) + count = result.scalar() + + log.info(f"Count of chats for folders '{folder_ids}': {count}") + return count + async def delete_tag_by_id_and_user_id_and_tag_name( self, id: str, user_id: str, tag_name: str, db: AsyncSession | None = None ) -> bool: diff --git a/backend/open_webui/models/config.py b/backend/open_webui/models/config.py new file mode 100644 index 0000000000..86d325c894 --- /dev/null +++ b/backend/open_webui/models/config.py @@ -0,0 +1,343 @@ +"""Database-backed configuration with per-key storage. + +Replaces the old single-row JSON blob machinery with a simple per-key model +mirroring cptr's Config. + +Each config key is stored as its own row: key TEXT PK, value JSON. +Reads are direct DB lookups. Writes are explicit awaited upserts that raise on +failure (no more fire-and-forget create_task). +""" + +from __future__ import annotations + +import logging +import time +from typing import Any, ClassVar + +from open_webui.internal.db import Base, get_async_db +from sqlalchemy import JSON, BigInteger, Column, Text, delete, select + +log = logging.getLogger(__name__) + +API_CONFIG_KEYS = ('openai.api_configs', 'ollama.api_configs') +DICT_CONFIG_KEY_ALIASES = { + 'openai.api_configs': ('OPENAI_API_CONFIGS',), + 'ollama.api_configs': ('OLLAMA_API_CONFIGS',), + 'rag.mineru_params': ('MINERU_PARAMS',), + 'rag.docling_params': ('DOCLING_PARAMS',), + 'web.search.linkup_search_params': ('LINKUP_SEARCH_PARAMS',), + 'image_generation.automatic1111.api_params': ('AUTOMATIC1111_PARAMS',), + 'image_generation.openai.params': ('IMAGES_OPENAI_API_PARAMS',), + 'audio.tts.openai.params': ('AUDIO_TTS_OPENAI_PARAMS',), + 'models.default_metadata': ('DEFAULT_MODEL_METADATA',), + 'models.default_params': ('DEFAULT_MODEL_PARAMS',), + 'user.permissions': ('USER_PERMISSIONS',), +} +DICT_CONFIG_KEYS = tuple(DICT_CONFIG_KEY_ALIASES) +API_CONFIG_FIELDS = ( + 'enable', + 'key', + 'prefix_id', + 'tags', + 'model_ids', + 'connection_type', + 'provider', + 'auth_type', + 'headers', + 'azure', + 'api_version', + 'extra_params', +) + + +def _split_api_config_fragment(fragment: str) -> tuple[str, list[str]] | None: + if not fragment: + return None + + first, _, rest = fragment.partition('.') + if first.isdigit() and rest: + return first, rest.split('.') + + match: tuple[int, str] | None = None + for field in API_CONFIG_FIELDS: + marker = f'.{field}' + marker_index = fragment.rfind(marker) + if marker_index != -1 and (match is None or marker_index > match[0]): + match = (marker_index, field) + + if match: + marker_index, field = match + connection_key = fragment[:marker_index] + field_path = fragment[marker_index + 1 :] + if connection_key: + return connection_key, field_path.split('.') + + return None + + +def _assign_path(target: dict, path: list[str], value: Any) -> None: + current = target + for part in path[:-1]: + next_value = current.get(part) + if not isinstance(next_value, dict): + next_value = {} + current[part] = next_value + current = next_value + current[path[-1]] = value + + +# ── Model ──────────────────────────────────────────────────────────────────── + + +class Config(Base): + """Per-key config storage. Each row is one config key.""" + + __tablename__ = 'config' + + key = Column(Text, primary_key=True) + value = Column(JSON, nullable=False) + updated_at = Column(BigInteger, nullable=True) + + DEFAULTS: ClassVar[dict[str, Any]] = {} + PERSISTENT_ENABLED: ClassVar[bool] = True + OAUTH_PERSISTENT_ENABLED: ClassVar[bool] = False + + # ── Class methods ──────────────────────────────────────── + + @classmethod + def configure( + cls, + *, + defaults: dict[str, Any] | None = None, + enable_persistent: bool = True, + enable_oauth_persistent: bool = False, + ) -> None: + cls.DEFAULTS = defaults or {} + cls.PERSISTENT_ENABLED = enable_persistent + cls.OAUTH_PERSISTENT_ENABLED = enable_oauth_persistent + + @classmethod + def default_value(cls, key: str, default: Any = None) -> Any: + return cls.DEFAULTS.get(key, default) + + @classmethod + def persistent_enabled_for(cls, key: str) -> bool: + if not cls.PERSISTENT_ENABLED: + return False + if key.startswith('oauth.') and not cls.OAUTH_PERSISTENT_ENABLED: + return False + return True + + @staticmethod + async def get(key: str, default: Any = None) -> Any: + """Get a config value by key. Returns default if not set.""" + if not Config.persistent_enabled_for(key): + return Config.default_value(key, default) + async with get_async_db() as db: + row = await db.get(Config, key) + return row.value if row else Config.default_value(key, default) + + @staticmethod + async def get_many(*keys: str) -> dict: + """Get multiple config values. Returns {key: value} for keys that exist.""" + disabled_values = { + key: Config.default_value(key) + for key in keys + if not Config.persistent_enabled_for(key) and key in Config.DEFAULTS + } + enabled_keys = {key for key in keys if Config.persistent_enabled_for(key)} + if not enabled_keys: + return disabled_values + async with get_async_db() as db: + result = await db.execute(select(Config).where(Config.key.in_(enabled_keys))) + values = {row.key: row.value for row in result.scalars().all()} + return { + key: values.get(key, Config.default_value(key)) + for key in keys + if key in values or key in Config.DEFAULTS or key in disabled_values + } + + @staticmethod + async def get_namespace(namespace: str) -> dict: + """Get all config keys under a dotted namespace.""" + default_values = { + key: value + for key, value in Config.DEFAULTS.items() + if key.startswith(f'{namespace}.') and not Config.persistent_enabled_for(key) + } + if not Config.PERSISTENT_ENABLED: + return default_values + async with get_async_db() as db: + result = await db.execute(select(Config).where(Config.key.like(f'{namespace}.%'))) + values = {row.key: row.value for row in result.scalars().all()} + values.update(default_values) + return values + + @staticmethod + async def get_all() -> dict: + """Get all config as {key: value}.""" + if not Config.PERSISTENT_ENABLED: + return dict(Config.DEFAULTS) + async with get_async_db() as db: + result = await db.execute(select(Config)) + values = {row.key: row.value for row in result.scalars().all()} + if not Config.OAUTH_PERSISTENT_ENABLED: + values.update({key: value for key, value in Config.DEFAULTS.items() if key.startswith('oauth.')}) + return values + + @staticmethod + async def upsert(updates: dict) -> None: + """Upsert multiple config key-value pairs. Raises on failure.""" + async with get_async_db() as db: + now = int(time.time()) + for key, value in updates.items(): + existing = await db.get(Config, key) + if existing: + existing.value = value + existing.updated_at = now + else: + db.add(Config(key=key, value=value, updated_at=now)) + await db.commit() + + @staticmethod + async def delete(key: str) -> bool: + """Delete a config key. Returns True if it existed.""" + async with get_async_db() as db: + row = await db.get(Config, key) + if row: + await db.delete(row) + await db.commit() + return True + return False + + @staticmethod + async def clear() -> None: + """Delete all config rows.""" + async with get_async_db() as db: + await db.execute(delete(Config)) + await db.commit() + + @staticmethod + async def seed_defaults(defaults: dict) -> None: + """Insert keys that don't yet exist in the DB. + + Called at startup to ensure all known config keys have values. + Existing DB values take precedence over defaults. + """ + async with get_async_db() as db: + result = await db.execute(select(Config.key)) + existing_keys = {row[0] for row in result.all()} + + now = int(time.time()) + new_count = 0 + for key, value in defaults.items(): + if key not in existing_keys: + db.add(Config(key=key, value=value, updated_at=now)) + existing_keys.add(key) + new_count += 1 + + if new_count: + await db.commit() + log.info('Seeded %d new config defaults', new_count) + + @staticmethod + async def rename_prefix(old_prefix: str, new_prefix: str) -> None: + """Move persisted config keys from one dotted prefix to another.""" + if not Config.PERSISTENT_ENABLED: + return + + async with get_async_db() as db: + result = await db.execute(select(Config).where(Config.key.like(f'{old_prefix}.%'))) + rows = result.scalars().all() + if not rows: + return + + now = int(time.time()) + moved_count = 0 + deleted_count = 0 + for row in rows: + new_key = f'{new_prefix}.{row.key.removeprefix(f"{old_prefix}.")}' + existing = await db.get(Config, new_key) + if existing is None: + db.add(Config(key=new_key, value=row.value, updated_at=now)) + moved_count += 1 + else: + deleted_count += 1 + await db.delete(row) + + await db.commit() + log.info( + 'Renamed %d config keys from %s.* to %s.*; deleted %d old duplicates', + moved_count, + old_prefix, + new_prefix, + deleted_count, + ) + + @staticmethod + async def repair_flattened_dict_configs() -> None: + """Reassemble dict config values flattened by the per-key migration.""" + if not Config.PERSISTENT_ENABLED: + return + + async with get_async_db() as db: + repaired_keys: list[str] = [] + orphan_keys: list[str] = [] + + for config_key, aliases in DICT_CONFIG_KEY_ALIASES.items(): + prefixes = (config_key, *aliases) + rows = [] + for key_prefix in prefixes: + result = await db.execute(select(Config).where(Config.key.like(f'{key_prefix}.%'))) + rows.extend(result.scalars().all()) + if not rows: + continue + + existing = await db.get(Config, config_key) + repaired = existing.value if existing and isinstance(existing.value, dict) else {} + + repaired_any = False + for row in rows: + fragment = None + for key_prefix in prefixes: + prefix = f'{key_prefix}.' + if row.key.startswith(prefix): + fragment = row.key.removeprefix(prefix) + break + if fragment is None: + continue + + if config_key in API_CONFIG_KEYS: + split = _split_api_config_fragment(fragment) + if not split: + continue + object_key, field_path = split + else: + object_key, field_path = None, fragment.split('.') + + target = repaired + if object_key is not None: + target = repaired.setdefault(object_key, {}) + if not isinstance(target, dict): + continue + + _assign_path(target, field_path, row.value) + orphan_keys.append(row.key) + repaired_any = True + + if not repaired_any: + continue + + if existing: + existing.value = repaired + existing.updated_at = int(time.time()) + else: + db.add(Config(key=config_key, value=repaired, updated_at=int(time.time()))) + repaired_keys.append(config_key) + + if orphan_keys: + await db.execute(delete(Config).where(Config.key.in_(orphan_keys))) + + if repaired_keys or orphan_keys: + await db.commit() + log.info('Repaired flattened dict config rows for %s', ', '.join(repaired_keys)) diff --git a/backend/open_webui/models/feedbacks.py b/backend/open_webui/models/feedbacks.py index d288980501..0bf1a6a139 100644 --- a/backend/open_webui/models/feedbacks.py +++ b/backend/open_webui/models/feedbacks.py @@ -133,6 +133,12 @@ class ModelHistoryEntry(BaseModel): lost: int +class ModelHistoryCounts(BaseModel): + date: str + won: int = 0 + lost: int = 0 + + class ModelHistoryResponse(BaseModel): model_id: str history: list[ModelHistoryEntry] @@ -216,12 +222,15 @@ class FeedbackTable: ) -> FeedbackListResponse: async with get_async_db_context(db) as db: stmt = select(Feedback, User).join(User, Feedback.user_id == User.id) + count_stmt = select(func.count(Feedback.id)).select_from(Feedback).join(User, Feedback.user_id == User.id) if filter: # Apply model_id filter (exact match) model_id = filter.get('model_id') if model_id: - stmt = stmt.filter(Feedback.data['model_id'].as_string() == model_id) + model_id_filter = Feedback.data['model_id'].as_string() == model_id + stmt = stmt.filter(model_id_filter) + count_stmt = count_stmt.filter(model_id_filter) order_by = filter.get('order_by') direction = filter.get('direction') @@ -250,9 +259,9 @@ class FeedbackTable: else: stmt = stmt.order_by(Feedback.created_at.desc()) - # Count BEFORE pagination - count_result = await db.execute(select(func.count()).select_from(stmt.subquery())) - total = count_result.scalar() + # Count before pagination without wrapping the ordered item query. + count_result = await db.execute(count_stmt) + total = count_result.scalar() or 0 if skip: stmt = stmt.offset(skip) @@ -375,6 +384,45 @@ class FeedbackTable: return result + async def get_model_feedback_counts_by_day( + self, + model_id: str, + start_date: Optional[int] = None, + db: Optional[AsyncSession] = None, + ) -> list[ModelHistoryCounts]: + """Get aggregated feedback counts per day for a model, preserving all matching days.""" + from collections import defaultdict + from datetime import datetime + + async with get_async_db_context(db) as db: + stmt = select(Feedback.created_at, Feedback.data).filter(Feedback.data['model_id'].as_string() == model_id) + if start_date is not None: + stmt = stmt.filter(Feedback.created_at >= start_date) + + result = await db.execute(stmt.order_by(Feedback.created_at.asc())) + rows = result.all() + + daily_counts = defaultdict(lambda: {'won': 0, 'lost': 0}) + + for created_at, data in rows: + if not data: + continue + + rating_str = str(data.get('rating', '')) + if rating_str not in ('1', '-1'): + continue + + date_str = datetime.fromtimestamp(created_at).strftime('%Y-%m-%d') + if rating_str == '1': + daily_counts[date_str]['won'] += 1 + else: + daily_counts[date_str]['lost'] += 1 + + return [ + ModelHistoryCounts(date=date_str, won=counts['won'], lost=counts['lost']) + for date_str, counts in sorted(daily_counts.items()) + ] + async def get_feedbacks_by_type(self, type: str, db: Optional[AsyncSession] = None) -> list[FeedbackModel]: async with get_async_db_context(db) as db: result = await db.execute(select(Feedback).filter_by(type=type).order_by(Feedback.updated_at.desc())) diff --git a/backend/open_webui/models/files.py b/backend/open_webui/models/files.py index 7fcc62558b..7f29fc5b7d 100644 --- a/backend/open_webui/models/files.py +++ b/backend/open_webui/models/files.py @@ -201,6 +201,18 @@ class FilesTable: result = await db.execute(select(File)) return [FileModel.model_validate(file) for file in result.scalars().all()] + async def count_files_by_user_id( + self, + user_id: str | None = None, + db: AsyncSession | None = None, + ) -> int: + async with get_async_db_context(db) as db: + stmt = select(func.count(File.id)) + if user_id: + stmt = stmt.filter_by(user_id=user_id) + result = await db.execute(stmt) + return result.scalar() or 0 + async def check_access_by_user_id(self, id, user_id, permission='write', db: AsyncSession | None = None) -> bool: file = await self.get_file_by_id(id, db=db) if not file: diff --git a/backend/open_webui/models/folders.py b/backend/open_webui/models/folders.py index 1688b8bd46..a06a5c51f8 100644 --- a/backend/open_webui/models/folders.py +++ b/backend/open_webui/models/folders.py @@ -6,7 +6,7 @@ from typing import Optional from open_webui.internal.db import Base, JSONField, get_async_db_context from pydantic import BaseModel, ConfigDict -from sqlalchemy import JSON, BigInteger, Boolean, Column, Text, delete, func, select +from sqlalchemy import JSON, BigInteger, Boolean, Column, Text, delete, func, select, or_, and_ from sqlalchemy.ext.asyncio import AsyncSession log = logging.getLogger(__name__) @@ -62,6 +62,20 @@ class FolderNameIdResponse(BaseModel): updated_at: int +class SharedFolderResponse(BaseModel): + id: str + name: str + parent_id: Optional[str] = None + user_id: str + owner_name: Optional[str] = None + permission: str = 'read' + access_grants: list = [] + is_expanded: bool = False + meta: Optional[dict] = None + created_at: int + updated_at: int + + #################### # Forms #################### @@ -130,6 +144,52 @@ class FolderTable: except Exception: return None + async def get_folder_by_id(self, id: str, db: Optional[AsyncSession] = None) -> Optional[FolderModel]: + """Fetch folder by ID only (no user_id filter). Used for shared access.""" + try: + async with get_async_db_context(db) as db: + result = await db.execute(select(Folder).filter_by(id=id)) + folder = result.scalars().first() + if not folder: + return None + return FolderModel.model_validate(folder) + except Exception: + return None + + async def get_shared_folder_ids_for_user( + self, user_id: str, user_group_ids: set[str], db: Optional[AsyncSession] = None + ) -> dict[str, str]: + """ + Returns {folder_id: highest_permission} for all folders shared with user. + Checks direct user grants, group grants, and public (user:*) grants. + """ + from open_webui.models.access_grants import AccessGrant + + async with get_async_db_context(db) as db: + conditions = [ + and_(AccessGrant.principal_type == 'user', AccessGrant.principal_id == '*'), + and_(AccessGrant.principal_type == 'user', AccessGrant.principal_id == user_id), + ] + if user_group_ids: + conditions.append( + and_(AccessGrant.principal_type == 'group', AccessGrant.principal_id.in_(user_group_ids)) + ) + result = await db.execute( + select(AccessGrant).filter( + AccessGrant.resource_type == 'folder', + or_(*conditions), + ) + ) + grants = result.scalars().all() + + # Build {folder_id: highest_permission} ('write' > 'read') + folder_perms = {} + for g in grants: + existing = folder_perms.get(g.resource_id) + if existing != 'write': + folder_perms[g.resource_id] = g.permission + return folder_perms + async def get_children_folders_by_id_and_user_id( self, id: str, user_id: str, db: Optional[AsyncSession] = None ) -> Optional[list[FolderModel]]: @@ -188,6 +248,25 @@ class FolderTable: result = await db.execute(select(Folder).filter_by(parent_id=parent_id, user_id=user_id)) return [FolderModel.model_validate(folder) for folder in result.scalars().all()] + async def get_folder_ids_by_id_and_user_id_in_subtree( + self, id: str, user_id: str, db: Optional[AsyncSession] = None + ) -> list[str]: + async with get_async_db_context(db) as db: + result = await db.execute(select(Folder).filter_by(id=id, user_id=user_id)) + folder = result.scalars().first() + if not folder: + return [] + + folder_ids = [folder.id] + folders = [FolderModel.model_validate(folder)] + while folders: + current_folder = folders.pop() + children = await self.get_folders_by_parent_id_and_user_id(current_folder.id, user_id, db=db) + folder_ids.extend(child.id for child in children) + folders.extend(children) + + return folder_ids + async def update_folder_parent_id_by_id_and_user_id( self, id: str, diff --git a/backend/open_webui/models/functions.py b/backend/open_webui/models/functions.py index c419dd3f93..8f0f7e0d1b 100644 --- a/backend/open_webui/models/functions.py +++ b/backend/open_webui/models/functions.py @@ -7,7 +7,8 @@ import time # local imports from open_webui.internal.db import Base, JSONField, get_async_db_context -from open_webui.models.users import UserModel, UserResponse, Users +from open_webui.models.users import UserResponse, Users +from open_webui.utils.valves import decrypt_valves, encrypt_valves from pydantic import BaseModel, ConfigDict from sqlalchemy import BigInteger, Boolean, Column, Index, String, Text, delete, select, update from sqlalchemy.ext.asyncio import AsyncSession @@ -143,7 +144,8 @@ class FunctionsTable: functions: list[FunctionWithValvesModel], db: AsyncSession | None = None, ) -> list[FunctionWithValvesModel]: - # Synchronize functions for a user by updating existing ones, inserting new ones, and removing those that are no longer present. + # Synchronize functions by updating existing ones, inserting new ones, + # and removing those that are no longer present. try: async with get_async_db_context(db) as db: # Get existing functions @@ -156,24 +158,15 @@ class FunctionsTable: # Update or insert functions for func in functions: + func_data = func.model_dump() + func_data['valves'] = encrypt_valves(func_data['valves']) if func_data.get('valves') else None + func_data['user_id'] = user_id + func_data['updated_at'] = int(time.time()) + if func.id in existing_ids: - await db.execute( - update(Function) - .filter_by(id=func.id) - .values( - **func.model_dump(), - user_id=user_id, - updated_at=int(time.time()), - ) - ) + await db.execute(update(Function).filter_by(id=func.id).values(**func_data)) else: - new_func = Function( - **{ - **func.model_dump(), - 'user_id': user_id, - 'updated_at': int(time.time()), - } - ) + new_func = Function(**func_data) db.add(new_func) # Remove functions that are no longer present @@ -227,7 +220,15 @@ class FunctionsTable: functions = result.scalars().all() if include_valves: - return [FunctionWithValvesModel.model_validate(function) for function in functions] + return [ + FunctionWithValvesModel.model_validate( + { + **FunctionModel.model_validate(function).model_dump(), + 'valves': decrypt_valves(function.valves), + } + ) + for function in functions + ] else: return [FunctionModel.model_validate(function) for function in functions] @@ -283,7 +284,7 @@ class FunctionsTable: async with get_async_db_context(db) as db: try: function = await db.get(Function, id) - return function.valves if function.valves else {} + return decrypt_valves(function.valves if function else None) except Exception as e: log.exception(f'Error getting function valves by id {id}: {e}') return None @@ -300,7 +301,7 @@ class FunctionsTable: async with get_async_db_context(db) as db: result = await db.execute(select(Function.id, Function.valves).filter(Function.id.in_(ids))) functions = result.all() - return {f.id: (f.valves if f.valves else {}) for f in functions} + return {f.id: decrypt_valves(f.valves) for f in functions} except Exception as e: log.exception(f'Error batch-fetching function valves: {e}') return {} @@ -311,7 +312,7 @@ class FunctionsTable: async with get_async_db_context(db) as db: try: function = await db.get(Function, id) - function.valves = valves + function.valves = encrypt_valves(valves) function.updated_at = int(time.time()) await db.commit() await db.refresh(function) @@ -355,8 +356,8 @@ class FunctionsTable: if 'valves' not in user_settings['functions']: user_settings['functions']['valves'] = {} - return user_settings['functions']['valves'].get(id, {}) - except Exception as e: + return decrypt_valves(user_settings['functions']['valves'].get(id)) + except Exception: log.exception(f'Error getting user values by id {id} and user id {user_id}') return None @@ -373,12 +374,12 @@ class FunctionsTable: if 'valves' not in user_settings['functions']: user_settings['functions']['valves'] = {} - user_settings['functions']['valves'][id] = valves + user_settings['functions']['valves'][id] = encrypt_valves(valves) # Update the user settings in the database await Users.update_user_by_id(user_id, {'settings': user_settings}, db=db) - return user_settings['functions']['valves'][id] + return valves except Exception as e: log.exception(f'Error updating user valves by id {id} and user_id {user_id}: {e}') return None diff --git a/backend/open_webui/models/knowledge.py b/backend/open_webui/models/knowledge.py index 84cf4b7ae8..f6650e2258 100644 --- a/backend/open_webui/models/knowledge.py +++ b/backend/open_webui/models/knowledge.py @@ -4,6 +4,7 @@ import time import uuid from typing import Optional +from open_webui.config import RAG_FILE_CONTENT_SEARCH_MAX_CHARS from open_webui.internal.db import Base, JSONField, get_async_db_context from open_webui.models.access_grants import AccessGrantModel, AccessGrants from open_webui.models.files import ( @@ -31,6 +32,7 @@ from sqlalchemy import ( update, ) from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import defer log = logging.getLogger(__name__) @@ -286,6 +288,17 @@ class KnowledgeTable: elif view_option == 'shared': stmt = stmt.filter(Knowledge.user_id != user_id) + source = filter.get('source') + if source == 'external': + stmt = stmt.filter(Knowledge.meta['source'].as_string() == 'external') + elif source == 'local': + stmt = stmt.filter( + or_( + Knowledge.meta.is_(None), + Knowledge.meta['source'].as_string() != 'external', + ) + ) + stmt = AccessGrants.has_permission_filter( db=db, query=stmt, @@ -369,6 +382,7 @@ class KnowledgeTable: # to avoid PostgreSQL "invalid memory alloc request # size" on large extracted-content rows (#24670). content_text = File.data['content'].as_string() + content_text = func.substr(content_text, 1, RAG_FILE_CONTENT_SEARCH_MAX_CHARS) search_filter = or_( File.filename.ilike(f'%{q}%'), content_text.ilike(f'%{q}%'), @@ -405,6 +419,7 @@ class KnowledgeTable: if limit: stmt = stmt.limit(limit) + stmt = stmt.options(defer(File.data)) result = await db.execute(stmt) rows = result.all() @@ -412,7 +427,13 @@ class KnowledgeTable: for file, user, knowledge in rows: items.append( FileUserResponse( - **FileModel.model_validate(file).model_dump(), + id=file.id, + user_id=file.user_id, + hash=file.hash, + filename=file.filename, + meta=file.meta, + created_at=file.created_at, + updated_at=file.updated_at, user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None), collection=(await self._to_knowledge_model(knowledge, db=db)).model_dump(), ) @@ -554,6 +575,7 @@ class KnowledgeTable: # to avoid PostgreSQL memory allocation failures on # large content (#24670). content_text = File.data['content'].as_string() + content_text = func.substr(content_text, 1, RAG_FILE_CONTENT_SEARCH_MAX_CHARS) stmt = stmt.filter( or_( File.filename.ilike(f'%{query_key}%'), @@ -592,17 +614,23 @@ class KnowledgeTable: if limit: stmt = stmt.limit(limit) + stmt = stmt.options(defer(File.data)) result = await db.execute(stmt) items = result.all() - files = [] - for file, user in items: - files.append( - FileUserResponse( - **FileModel.model_validate(file).model_dump(), - user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None), - ) + files = [ + FileUserResponse( + id=file.id, + user_id=file.user_id, + hash=file.hash, + filename=file.filename, + meta=file.meta, + created_at=file.created_at, + updated_at=file.updated_at, + user=(UserResponse(**UserModel.model_validate(user).model_dump()) if user else None), ) + for file, user in items + ] return KnowledgeFileListResponse( items=files, @@ -765,6 +793,25 @@ class KnowledgeTable: log.exception(e) return None + async def update_knowledge_meta_by_id( + self, id: str, meta: dict, db: Optional[AsyncSession] = None + ) -> Optional[KnowledgeModel]: + try: + async with get_async_db_context(db) as db: + await db.execute( + update(Knowledge) + .filter_by(id=id) + .values( + meta=meta, + updated_at=int(time.time()), + ) + ) + await db.commit() + return await self.get_knowledge_by_id(id=id, db=db) + except Exception as e: + log.exception(e) + return None + async def delete_knowledge_by_id(self, id: str, db: Optional[AsyncSession] = None) -> bool: try: async with get_async_db_context(db) as db: diff --git a/backend/open_webui/models/memories.py b/backend/open_webui/models/memories.py index 2337371f12..ad32330f9f 100644 --- a/backend/open_webui/models/memories.py +++ b/backend/open_webui/models/memories.py @@ -4,11 +4,11 @@ from __future__ import annotations import time import uuid -from typing import Optional +from typing import Literal from open_webui.internal.db import Base, get_async_db_context from pydantic import BaseModel, ConfigDict -from sqlalchemy import BigInteger, Column, String, Text, delete, select +from sqlalchemy import JSON, BigInteger, Column, String, Text, delete, select from sqlalchemy.ext.asyncio import AsyncSession @@ -19,7 +19,10 @@ class Memory(Base): # user memory store id = Column(String, primary_key=True, unique=True) user_id = Column(String, index=True) + type = Column(String, default='context', server_default='context', index=True) + path = Column(Text, nullable=True) content = Column(Text) # free-form text learned from conversation + meta = Column(JSON, nullable=True) updated_at = Column(BigInteger) # epoch seconds created_at = Column(BigInteger) # epoch seconds @@ -29,17 +32,27 @@ class MemoryModel(BaseModel): id: str user_id: str + type: Literal['user', 'context'] = 'context' + path: str | None = None content: str + meta: dict | None = None updated_at: int # timestamp in epoch created_at: int # timestamp in epoch model_config = ConfigDict(from_attributes=True) # allows ORM mapping class MemoriesTable: + @staticmethod + def normalize_memory_type(memory_type: str | None = None) -> str: + return 'user' if memory_type == 'user' else 'context' + async def insert_new_memory( self, user_id: str, content: str, + memory_type: str | None = None, + path: str | None = None, + meta: dict | None = None, db: AsyncSession | None = None, ) -> MemoryModel | None: """Persist a new memory entry and return the created model.""" @@ -48,7 +61,10 @@ class MemoriesTable: record = Memory( id=str(uuid.uuid4()), user_id=user_id, + type=self.normalize_memory_type(memory_type), + path=path, content=content, + meta=meta, created_at=now, updated_at=now, ) @@ -61,7 +77,11 @@ class MemoriesTable: self, id: str, user_id: str, - content: str, + content: str | None, + memory_type: str | None = None, + path: str | None = None, + update_path: bool = False, + meta: dict | None = None, db: AsyncSession | None = None, ) -> MemoryModel | None: async with get_async_db_context(db) as db: @@ -70,7 +90,14 @@ class MemoriesTable: if not memory or memory.user_id != user_id: return None - memory.content = content + if content is not None: + memory.content = content + if memory_type is not None: + memory.type = self.normalize_memory_type(memory_type) + if update_path: + memory.path = path + if meta is not None: + memory.meta = {**(memory.meta or {}), **meta} memory.updated_at = int(time.time()) await db.commit() @@ -139,5 +166,104 @@ class MemoriesTable: except Exception: return False + async def apply_memory_operations( + self, + user_id: str, + operations: list[dict], + db: AsyncSession | None = None, + ) -> list[dict]: + now = int(time.time()) + results: list[dict] = [] + + async with get_async_db_context(db) as db: + for operation in operations: + action = operation.get('action') + + if action == 'add': + content = operation.get('content', '').strip() + memory_type = self.normalize_memory_type(operation.get('type')) + path = operation.get('path') + result = await db.execute( + select(Memory).filter_by(user_id=user_id, content=content, type=memory_type, path=path) + ) + existing = result.scalars().first() + if existing: + results.append( + { + 'action': action, + 'status': 'skipped', + 'memory': MemoryModel.model_validate(existing), + 'reason': 'duplicate', + } + ) + continue + + memory = Memory( + id=str(uuid.uuid4()), + user_id=user_id, + type=memory_type, + path=path, + content=content, + meta=operation.get('meta'), + created_at=now, + updated_at=now, + ) + db.add(memory) + await db.flush() + results.append( + {'action': action, 'status': 'created', 'memory': MemoryModel.model_validate(memory)} + ) + + elif action == 'replace': + memory_id = operation.get('id') + content = operation.get('content', '').strip() + memory = await db.get(Memory, memory_id) + if not memory or memory.user_id != user_id: + raise ValueError(f'Memory not found: {memory_id}') + + memory.content = content + if operation.get('type') is not None: + memory.type = self.normalize_memory_type(operation.get('type')) + if 'path' in operation: + memory.path = operation.get('path') + if operation.get('meta') is not None: + memory.meta = {**(memory.meta or {}), **operation.get('meta')} + memory.updated_at = now + await db.flush() + results.append( + {'action': action, 'status': 'updated', 'memory': MemoryModel.model_validate(memory)} + ) + + elif action == 'move': + memory_id = operation.get('id') + memory = await db.get(Memory, memory_id) + if not memory or memory.user_id != user_id: + raise ValueError(f'Memory not found: {memory_id}') + + memory.path = operation.get('path') + if operation.get('meta') is not None: + memory.meta = {**(memory.meta or {}), **operation.get('meta')} + memory.updated_at = now + await db.flush() + results.append( + {'action': action, 'status': 'updated', 'memory': MemoryModel.model_validate(memory)} + ) + + elif action == 'remove': + memory_id = operation.get('id') + memory = await db.get(Memory, memory_id) + if not memory or memory.user_id != user_id: + raise ValueError(f'Memory not found: {memory_id}') + + await db.delete(memory) + results.append({'action': action, 'status': 'deleted', 'id': memory_id}) + + else: + raise ValueError(f'Unsupported memory operation: {action}') + + await db.commit() + + return results + Memories = MemoriesTable() # user memory registry diff --git a/backend/open_webui/models/messages.py b/backend/open_webui/models/messages.py index 342abed2f8..dc43dfe1e9 100644 --- a/backend/open_webui/models/messages.py +++ b/backend/open_webui/models/messages.py @@ -328,7 +328,8 @@ class MessageTable: async with get_async_db_context(db) as db: message = await db.get(Message, parent_id) - if not message: + # Thread parent must belong to the requested channel; never disclose a foreign-channel message. + if not message or message.channel_id != channel_id: return [] result = await db.execute( @@ -500,6 +501,71 @@ class MessageTable: return [Reactions(**reaction) for reaction in reactions.values()] + async def get_reactions_by_message_ids( + self, ids: list[str], db: Optional[AsyncSession] = None + ) -> dict[str, list[Reactions]]: + """Batch-fetch reactions for multiple messages in a single query. + + Returns a dict mapping each message_id to its list of Reactions. + Messages with no reactions map to an empty list. + """ + if not ids: + return {} + + async with get_async_db_context(db) as db: + result = await db.execute( + select(MessageReaction, User) + .join(User, MessageReaction.user_id == User.id) + .filter(MessageReaction.message_id.in_(ids)) + ) + rows = result.all() + + # Group by (message_id, reaction_name) + grouped: dict[str, dict[str, dict]] = {mid: {} for mid in ids} + for reaction, user in rows: + mid = reaction.message_id + if mid not in grouped: + grouped[mid] = {} + if reaction.name not in grouped[mid]: + grouped[mid][reaction.name] = { + 'name': reaction.name, + 'users': [], + 'count': 0, + } + grouped[mid][reaction.name]['users'].append( + { + 'id': user.id, + 'name': user.name, + } + ) + grouped[mid][reaction.name]['count'] += 1 + + return {mid: [Reactions(**r) for r in reactions.values()] for mid, reactions in grouped.items()} + + async def get_thread_reply_counts_by_message_ids( + self, ids: list[str], db: Optional[AsyncSession] = None + ) -> dict[str, tuple[int, int | None]]: + """Batch-fetch reply counts and latest reply timestamps for multiple parent messages. + + Returns a dict mapping each parent message_id to a + (reply_count, latest_reply_created_at) tuple. + Messages with no replies are omitted from the result. + """ + if not ids: + return {} + + async with get_async_db_context(db) as db: + result = await db.execute( + select( + Message.parent_id, + func.count(Message.id), + func.max(Message.created_at), + ) + .filter(Message.parent_id.in_(ids)) + .group_by(Message.parent_id) + ) + return {row[0]: (row[1], row[2]) for row in result.all()} + async def remove_reaction_by_id_and_user_id_and_name( self, id: str, user_id: str, name: str, db: Optional[AsyncSession] = None ) -> bool: diff --git a/backend/open_webui/models/models.py b/backend/open_webui/models/models.py index 0fab100c46..9acd0c9b70 100755 --- a/backend/open_webui/models/models.py +++ b/backend/open_webui/models/models.py @@ -229,10 +229,25 @@ class ModelsTable: ) return models - async def get_base_models(self, db: AsyncSession | None = None) -> list[ModelModel]: + @staticmethod + def _meta_has_tag(meta: dict | None, tag: str) -> bool: + if not meta: + return False + + for raw_tag in meta.get('tags', []): + name = raw_tag.get('name') if isinstance(raw_tag, dict) else str(raw_tag) + if name == tag: + return True + + return False + + async def get_base_models(self, tag: str | None = None, db: AsyncSession | None = None) -> list[ModelModel]: async with get_async_db_context(db) as db: - result = await db.execute(select(Model).filter(Model.base_model_id == None)) + result = await db.execute(select(Model).filter(Model.base_model_id.is_(None))) all_models = result.scalars().all() + if tag: + all_models = [model for model in all_models if self._meta_has_tag(model.meta, tag)] + model_ids = [model.id for model in all_models] grants_map = await AccessGrants.get_grants_by_resources('model', model_ids, db=db) return [ @@ -395,11 +410,14 @@ class ModelsTable: self, user_id: str, is_admin: bool = False, + is_base_model: bool = False, db: AsyncSession | None = None, ) -> set[str]: """Extract unique tag names from model meta, querying only the meta column.""" async with get_async_db_context(db) as db: - stmt = select(Model.meta).filter(Model.base_model_id != None) + stmt = select(Model.meta).filter( + Model.base_model_id.is_(None) if is_base_model else Model.base_model_id.is_not(None) + ) if not is_admin: user_groups = await Groups.get_groups_by_member_id(user_id, db=db) diff --git a/backend/open_webui/models/shared_chats.py b/backend/open_webui/models/shared_chats.py index 9132f11301..a6ceebb8b0 100644 --- a/backend/open_webui/models/shared_chats.py +++ b/backend/open_webui/models/shared_chats.py @@ -201,5 +201,15 @@ class SharedChatsTable: except Exception: return False + async def delete_all_by_user_id(self, user_id: str, db: Optional[AsyncSession] = None) -> bool: + """Delete all shared chats created by a user.""" + try: + async with get_async_db_context(db) as db: + await db.execute(delete(SharedChat).filter_by(user_id=user_id)) + await db.commit() + return True + except Exception: + return False + SharedChats = SharedChatsTable() diff --git a/backend/open_webui/models/tools.py b/backend/open_webui/models/tools.py index d575cc1439..a6468f1876 100644 --- a/backend/open_webui/models/tools.py +++ b/backend/open_webui/models/tools.py @@ -10,6 +10,7 @@ from open_webui.internal.db import Base, JSONField, get_async_db_context from open_webui.models.access_grants import AccessGrantModel, AccessGrants from open_webui.models.groups import Groups from open_webui.models.users import UserResponse, Users +from open_webui.utils.valves import decrypt_valves, encrypt_valves from pydantic import BaseModel, ConfigDict, Field from sqlalchemy import BigInteger, Column, String, Text, delete, select, update from sqlalchemy.ext.asyncio import AsyncSession @@ -35,6 +36,7 @@ class Tool(Base): # database table definition class ToolMeta(BaseModel): description: str | None = None manifest: dict | None = {} + has_user_valves: bool = False class ToolModel(BaseModel): @@ -231,8 +233,8 @@ class ToolsTable: try: async with get_async_db_context(db) as db: tool = await db.get(Tool, id) - return tool.valves if tool.valves else {} - except Exception as e: + return decrypt_valves(tool.valves if tool else None) + except Exception: log.exception(f'Error getting tool valves by id {id}') return None @@ -241,7 +243,9 @@ class ToolsTable: ) -> ToolValves | None: try: async with get_async_db_context(db) as db: - await db.execute(update(Tool).filter_by(id=id).values(valves=valves, updated_at=int(time.time()))) + await db.execute( + update(Tool).filter_by(id=id).values(valves=encrypt_valves(valves), updated_at=int(time.time())) + ) await db.commit() return await self.get_tool_by_id(id, db=db) except Exception: @@ -260,7 +264,7 @@ class ToolsTable: if 'valves' not in user_settings['tools']: user_settings['tools']['valves'] = {} - return user_settings['tools']['valves'].get(id, {}) + return decrypt_valves(user_settings['tools']['valves'].get(id)) except Exception as e: log.exception(f'Error getting user values by id {id} and user_id {user_id}: {e}') return None @@ -278,12 +282,12 @@ class ToolsTable: if 'valves' not in user_settings['tools']: user_settings['tools']['valves'] = {} - user_settings['tools']['valves'][id] = valves + user_settings['tools']['valves'][id] = encrypt_valves(valves) # Update the user settings in the database await Users.update_user_by_id(user_id, {'settings': user_settings}, db=db) - return user_settings['tools']['valves'][id] + return valves except Exception as e: log.exception(f'Error updating user valves by id {id} and user_id {user_id}: {e}') return None diff --git a/backend/open_webui/models/users.py b/backend/open_webui/models/users.py index bd64887ad8..b0a9627a82 100644 --- a/backend/open_webui/models/users.py +++ b/backend/open_webui/models/users.py @@ -279,6 +279,11 @@ class UsersTable: oauth: dict | None = None, db: AsyncSession | None = None, ) -> UserModel | None: + try: + profile_image_url = validate_profile_image_url(profile_image_url) + except ValueError: + profile_image_url = '/user.png' + async with get_async_db_context(db) as session: user = UserModel( **{ @@ -606,6 +611,11 @@ class UsersTable: profile_image_url: str, db: AsyncSession | None = None, ) -> UserModel | None: + try: + profile_image_url = validate_profile_image_url(profile_image_url) + except ValueError: + profile_image_url = '/user.png' + async with get_async_db_context(db) as session: user = await session.get(User, id) if user is None: diff --git a/backend/open_webui/retrieval/external.py b/backend/open_webui/retrieval/external.py new file mode 100644 index 0000000000..dcfc575fc8 --- /dev/null +++ b/backend/open_webui/retrieval/external.py @@ -0,0 +1,378 @@ +import asyncio +import logging +import re +import time +from typing import Any, Optional + +from open_webui.models.config import Config +from open_webui.models.knowledge import KnowledgeModel + +log = logging.getLogger(__name__) + +EXTERNAL_KNOWLEDGE_CONNECTIONS_CONFIG_KEY = 'external_knowledge.connections' +IDENTIFIER_RE = re.compile(r'^[A-Za-z_][A-Za-z0-9_]*$') + + +async def _get_external_connection(connection_id: str) -> Optional[dict]: + connections = await Config.get(EXTERNAL_KNOWLEDGE_CONNECTIONS_CONFIG_KEY, []) or [] + return next((connection for connection in connections if connection.get('id') == connection_id), None) + + +def _get_path(data: Any, path: Optional[str], default=None): + if not path: + return default + value = data + for part in path.split('.'): + if isinstance(value, dict): + value = value.get(part, default) + else: + return default + return value + + +def _normalize_result(result: dict, mapping: dict, knowledge: KnowledgeModel, distance: Optional[float] = None) -> dict: + content = _get_path(result, mapping.get('content_field', 'content'), '') + title = _get_path(result, mapping.get('title_field', 'title'), None) + source = _get_path(result, mapping.get('source_field', 'source'), None) + url = _get_path(result, mapping.get('url_field', 'url'), None) + document_id = _get_path(result, mapping.get('document_id_field', 'document_id'), None) + page = _get_path(result, mapping.get('page_field', 'page'), None) + metadata = _get_path(result, mapping.get('metadata_field', 'metadata'), {}) or {} + score = _get_path(result, mapping.get('score_field', 'score'), distance) + + if not isinstance(metadata, dict): + metadata = {'external_metadata': metadata} + + source_name = source or title or metadata.get('source') or metadata.get('name') or knowledge.name + metadata.update( + { + 'name': title or source_name, + 'source': source_name, + 'url': url, + 'file_id': document_id or f'external-{knowledge.id}', + 'knowledge_id': knowledge.id, + 'knowledge_name': knowledge.name, + 'external': True, + } + ) + if page is not None: + metadata['page'] = page + if document_id is not None: + metadata['document_id'] = document_id + + return { + 'content': content, + 'metadata': metadata, + 'distance': score, + } + + +def _source_config(knowledge: KnowledgeModel) -> dict: + external = (knowledge.meta or {}).get('external', {}) + source = external.get('source') or {} + return source.get('config') or {} + + +def _root_field(path: Optional[str]) -> Optional[str]: + if not path: + return None + return path.split('.')[0] + + +def _safe_identifier(value: str, label: str) -> str: + if not value or not IDENTIFIER_RE.match(value): + raise RuntimeError(f'Invalid {label}') + return value + + +async def _retrieve_qdrant(connection, auth_config, knowledge, query, count, embedding_function) -> list[dict]: + try: + from qdrant_client import QdrantClient + except ImportError as exc: + raise RuntimeError('qdrant-client is not installed') from exc + + if not embedding_function: + raise RuntimeError('Embedding function is not configured') + + config = connection.get('config') or {} + external = (knowledge.meta or {}).get('external', {}) + source = external.get('source') or {} + collection_name = source.get('name') + if not collection_name: + raise RuntimeError('External source collection is not configured') + source_config = _source_config(knowledge) + vector_field = source_config.get('vector_field') or None + + vector = await embedding_function(query) + + def _search(): + client = QdrantClient( + url=connection.get('endpoint'), + api_key=(auth_config or {}).get('api_key'), + timeout=config.get('timeout') or 30, + ) + return client.query_points( + collection_name=collection_name, + query=vector, + using=vector_field, + limit=count, + ) + + response = await asyncio.to_thread(_search) + mapping = { + 'content_field': source_config.get('content_field') or 'payload.text', + 'metadata_field': source_config.get('metadata_field') or 'payload.metadata', + 'document_id_field': source_config.get('document_id_field') or 'id', + 'score_field': 'score', + } + + normalized = [] + for point in response.points: + normalized.append(_normalize_result(point.model_dump(), mapping, knowledge, distance=point.score)) + return normalized + + +async def _retrieve_milvus(connection, auth_config, knowledge, query, count, embedding_function) -> list[dict]: + try: + from pymilvus import MilvusClient + except ImportError as exc: + raise RuntimeError('pymilvus is not installed') from exc + + if not embedding_function: + raise RuntimeError('Embedding function is not configured') + + config = connection.get('config') or {} + external = (knowledge.meta or {}).get('external', {}) + source = external.get('source') or {} + collection_name = source.get('name') + if not collection_name: + raise RuntimeError('Milvus collection is not configured') + source_config = _source_config(knowledge) + vector_field = source_config.get('vector_field') or 'vector' + content_field = source_config.get('content_field') or 'data.text' + metadata_field = source_config.get('metadata_field') or 'metadata' + + vector = await embedding_function(query) + + def _search(): + client_kwargs = { + 'uri': connection.get('endpoint'), + } + token = (auth_config or {}).get('api_key') or (auth_config or {}).get('token') + if token: + client_kwargs['token'] = token + if config.get('db_name'): + client_kwargs['db_name'] = config.get('db_name') + + client = MilvusClient(**client_kwargs) + output_fields = { + field + for field in ( + _root_field(content_field), + _root_field(metadata_field), + _root_field(source_config.get('document_id_field')), + ) + if field and field != vector_field + } + kwargs = { + 'collection_name': collection_name, + 'data': [vector], + 'anns_field': vector_field, + 'limit': count, + 'output_fields': list(output_fields), + } + return client.search(**kwargs) + + response = await asyncio.to_thread(_search) + mapping = { + 'content_field': content_field, + 'metadata_field': metadata_field, + 'document_id_field': source_config.get('document_id_field') or 'id', + 'score_field': 'distance', + } + + normalized = [] + for hit in response[0] if response else []: + item = dict(hit) + entity = item.get('entity') or {} + result = { + **entity, + 'id': item.get('id') or entity.get('id'), + 'distance': item.get('distance'), + } + normalized.append(_normalize_result(result, mapping, knowledge, distance=item.get('distance'))) + return normalized + + +async def _retrieve_pgvector(connection, auth_config, knowledge, query, count, embedding_function) -> list[dict]: + try: + import psycopg + from pgvector.psycopg import register_vector + from psycopg.rows import dict_row + except ImportError as exc: + raise RuntimeError('psycopg and pgvector are required for pgvector retrieval') from exc + + if not embedding_function: + raise RuntimeError('Embedding function is not configured') + + config = connection.get('config') or {} + external = (knowledge.meta or {}).get('external', {}) + source = external.get('source') or {} + collection_name = source.get('name') + if not collection_name: + raise RuntimeError('pgvector collection is not configured') + source_config = _source_config(knowledge) + table_name = source_config.get('table_name') or 'document_chunk' + collection_field = source_config.get('collection_field') or 'collection_name' + content_field = source_config.get('content_field') or 'text' + vector_field = source_config.get('vector_field') or 'vector' + metadata_field = source_config.get('metadata_field') or 'vmetadata' + document_id_field = source_config.get('document_id_field') or 'id' + + vector = await embedding_function(query) + + def _search(): + from psycopg import sql + + table_identifier = sql.SQL('.').join( + sql.Identifier(_safe_identifier(part, 'table name')) for part in table_name.split('.') + ) + collection_identifier = sql.Identifier(_safe_identifier(collection_field, 'collection field')) + content_identifier = sql.Identifier(_safe_identifier(content_field, 'content field')) + vector_identifier = sql.Identifier(_safe_identifier(vector_field, 'vector field')) + document_id_identifier = sql.Identifier(_safe_identifier(document_id_field, 'document id field')) + metadata_sql = ( + sql.Identifier(_safe_identifier(metadata_field, 'metadata field')) + if metadata_field + else sql.SQL("'{}'::jsonb") + ) + + with psycopg.connect( + connection.get('endpoint'), + row_factory=dict_row, + connect_timeout=config.get('timeout') or 30, + ) as conn: + register_vector(conn) + with conn.cursor() as cur: + cur.execute( + sql.SQL( + """ + SELECT {document_id} AS id, + {content} AS content, + {metadata} AS metadata, + {vector_column} <=> %s AS distance + FROM {table_name} + WHERE {collection} = %s + ORDER BY distance ASC + LIMIT %s + """ + ).format( + document_id=document_id_identifier, + content=content_identifier, + metadata=metadata_sql, + vector_column=vector_identifier, + table_name=table_identifier, + collection=collection_identifier, + ), + (vector, collection_name, count), + ) + return cur.fetchall() + + rows = await asyncio.to_thread(_search) + mapping = { + 'content_field': 'content', + 'metadata_field': 'metadata', + 'document_id_field': 'id', + 'score_field': 'distance', + } + return [_normalize_result(row, mapping, knowledge, distance=row.get('distance')) for row in rows] + + +async def retrieve_external_knowledge( + request, + knowledge: KnowledgeModel, + queries: list[str], + count: int, + user=None, +) -> dict: + external = (knowledge.meta or {}).get('external', {}) + connection_id = external.get('connection_id') + if not connection_id: + raise RuntimeError('External knowledge connection is not configured') + + connection = await _get_external_connection(connection_id) + if not connection: + raise RuntimeError('External knowledge connection not found') + + return await retrieve_external_knowledge_for_connection(request, knowledge, connection, queries, count, user=user) + + +async def retrieve_external_knowledge_for_connection( + request, + knowledge: KnowledgeModel, + connection: dict, + queries: list[str], + count: int, + user=None, +) -> dict: + auth_config = connection.get('auth_config') or {} + if not connection.get('enabled', True): + raise RuntimeError('External knowledge connection is disabled') + + started_at = time.monotonic() + chunks = [] + provider = (connection.get('provider') or '').lower() + + for query in queries: + if provider == 'qdrant': + chunks.extend( + await _retrieve_qdrant( + connection, + auth_config, + knowledge, + query, + count, + getattr(request.app.state, 'EMBEDDING_FUNCTION', None), + ) + ) + elif provider == 'milvus': + chunks.extend( + await _retrieve_milvus( + connection, + auth_config, + knowledge, + query, + count, + getattr(request.app.state, 'EMBEDDING_FUNCTION', None), + ) + ) + elif provider == 'pgvector': + chunks.extend( + await _retrieve_pgvector( + connection, + auth_config, + knowledge, + query, + count, + getattr(request.app.state, 'EMBEDDING_FUNCTION', None), + ) + ) + else: + raise RuntimeError(f'Unsupported external knowledge provider: {connection.get("provider")}') + + chunks = chunks[:count] + log.info( + 'external_knowledge_retrieval knowledge_id=%s connection_id=%s provider=%s user_id=%s latency_ms=%s result_count=%s', + knowledge.id, + connection.get('id'), + connection.get('provider'), + getattr(user, 'id', None), + round((time.monotonic() - started_at) * 1000), + len(chunks), + ) + + return { + 'documents': [[chunk['content'] for chunk in chunks]], + 'metadatas': [[chunk['metadata'] for chunk in chunks]], + 'distances': [[chunk['distance'] for chunk in chunks]], + } diff --git a/backend/open_webui/retrieval/loaders/external_document.py b/backend/open_webui/retrieval/loaders/external_document.py index ddafc3124b..2dd70dbd4b 100644 --- a/backend/open_webui/retrieval/loaders/external_document.py +++ b/backend/open_webui/retrieval/loaders/external_document.py @@ -6,7 +6,7 @@ from urllib.parse import quote import requests from langchain_core.document_loaders import BaseLoader from langchain_core.documents import Document -from open_webui.utils.headers import include_user_info_headers +from open_webui.utils.headers import get_custom_headers, include_user_info_headers log = logging.getLogger(__name__) @@ -19,6 +19,8 @@ class ExternalDocumentLoader(BaseLoader): api_key: str, mime_type=None, user=None, + headers=None, + metadata=None, **kwargs, ) -> None: self.url = url @@ -28,6 +30,8 @@ class ExternalDocumentLoader(BaseLoader): self.mime_type = mime_type self.user = user + self.headers = headers + self.metadata = metadata def load(self) -> List[Document]: with open(self.file_path, 'rb') as f: @@ -45,6 +49,8 @@ class ExternalDocumentLoader(BaseLoader): except Exception: pass + headers.update(get_custom_headers(self.headers, self.user, self.metadata)) + if self.user is not None: headers = include_user_info_headers(headers, self.user) diff --git a/backend/open_webui/retrieval/loaders/main.py b/backend/open_webui/retrieval/loaders/main.py index ee4166d120..c5eeb32e91 100644 --- a/backend/open_webui/retrieval/loaders/main.py +++ b/backend/open_webui/retrieval/loaders/main.py @@ -17,7 +17,12 @@ from langchain_community.document_loaders import ( YoutubeLoader, ) from langchain_core.documents import Document -from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, GLOBAL_LOG_LEVEL, REQUESTS_VERIFY +from open_webui.env import ( + AIOHTTP_CLIENT_SESSION_SSL, + GLOBAL_LOG_LEVEL, + MINERU_MAX_MARKDOWN_BYTES, + REQUESTS_VERIFY, +) from open_webui.retrieval.loaders.datalab_marker import DatalabMarkerLoader from open_webui.retrieval.loaders.external_document import ExternalDocumentLoader from open_webui.retrieval.loaders.mineru import MinerULoader @@ -183,6 +188,7 @@ class DoclingLoader: self.params = params or {} def load(self) -> list[Document]: + page_break_marker = '\f' with open(self.file_path, 'rb') as f: headers = {} if self.api_key: @@ -199,6 +205,7 @@ class DoclingLoader: }, data={ 'image_export_mode': 'placeholder', + 'md_page_break_placeholder': page_break_marker, **self.params, }, headers=headers, @@ -207,9 +214,19 @@ class DoclingLoader: if r.ok: result = r.json() document_data = result.get('document', {}) - text = document_data.get('md_content', '') + md_content = document_data.get('md_content', '') + text = md_content or '' metadata = {'Content-Type': self.mime_type} if self.mime_type else {} + if page_break_marker in md_content: + documents = [ + Document(page_content=page.strip(), metadata={**metadata, 'page': page_idx}) + for page_idx, page in enumerate(md_content.split(page_break_marker)) + if page.strip() + ] + if documents: + log.debug('Docling extracted text: %s', text) + return documents log.debug('Docling extracted text: %s', text) return [Document(page_content=text, metadata=metadata)] @@ -229,6 +246,7 @@ class Loader: def __init__(self, engine: str = '', **kwargs): self.engine = engine self.user = kwargs.get('user', None) + self.metadata = kwargs.get('metadata', {}) self.kwargs = kwargs def load(self, filename: str, file_content_type: str, file_path: str) -> list[Document]: @@ -404,6 +422,12 @@ class Loader: api_key=self.kwargs.get('EXTERNAL_DOCUMENT_LOADER_API_KEY'), mime_type=file_content_type, user=self.user, + headers=self.kwargs.get('EXTERNAL_DOCUMENT_LOADER_HEADERS'), + metadata={ + **self.metadata, + 'file_name': filename, + 'file_content_type': file_content_type, + }, ) elif self.engine == 'tika' and self.kwargs.get('TIKA_SERVER_URL'): if self._is_text_file(file_ext, file_content_type): @@ -511,7 +535,6 @@ class Loader: mineru_timeout = int(mineru_timeout) except ValueError: mineru_timeout = 300 - loader = MinerULoader( file_path=file_path, api_mode=self.kwargs.get('MINERU_API_MODE', 'local'), @@ -519,6 +542,7 @@ class Loader: api_key=self.kwargs.get('MINERU_API_KEY', ''), params=self.kwargs.get('MINERU_PARAMS', {}), timeout=mineru_timeout, + max_markdown_bytes=MINERU_MAX_MARKDOWN_BYTES, ) elif ( self.engine == 'mistral_ocr' @@ -529,6 +553,7 @@ class Loader: base_url=self.kwargs.get('MISTRAL_OCR_API_BASE_URL'), api_key=self.kwargs.get('MISTRAL_OCR_API_KEY'), file_path=file_path, + use_base64=self.kwargs.get('MISTRAL_OCR_USE_BASE64', False), ) elif self.engine == 'paddleocr_vl' and self.kwargs.get('PADDLEOCR_VL_TOKEN') != '': loader = PaddleOCRVLLoader( diff --git a/backend/open_webui/retrieval/loaders/microsoft_web_iq.py b/backend/open_webui/retrieval/loaders/microsoft_web_iq.py new file mode 100644 index 0000000000..fdf10e6332 --- /dev/null +++ b/backend/open_webui/retrieval/loaders/microsoft_web_iq.py @@ -0,0 +1,110 @@ +import logging +import time +from collections.abc import Iterator +from typing import Any +from urllib.parse import urlparse + +import requests +from langchain_core.document_loaders import BaseLoader +from langchain_core.documents import Document + +log = logging.getLogger(__name__) + +DEFAULT_MICROSOFT_WEB_IQ_API_BASE_URL = 'https://api.microsoft.ai/v3' +MICROSOFT_BROWSE_RETRY_STATUS_CODES = {202, 429, 500, 502, 503, 504} +MICROSOFT_BROWSE_MAX_RETRIES = 2 + + +class MicrosoftWebIQLoader(BaseLoader): + def __init__( + self, + urls: str | list[str], + api_base_url: str, + api_key: str, + language: str = 'en', + verify_ssl: bool = True, + timeout: Any = None, + continue_on_failure: bool = True, + ) -> None: + self.urls = urls if isinstance(urls, list) else [urls] + self.api_base_url = (api_base_url or DEFAULT_MICROSOFT_WEB_IQ_API_BASE_URL).rstrip('/') + self.api_key = api_key + self.language = language + self.verify_ssl = verify_ssl + self.timeout = timeout + self.continue_on_failure = continue_on_failure + + def lazy_load(self) -> Iterator[Document]: + for url in self.urls: + try: + doc = self._browse_url(url) + if doc is not None: + yield doc + except Exception as e: + if self.continue_on_failure: + log.warning(f'Error browsing {url} with Microsoft Web IQ: {e}') + else: + raise e + + def _browse_url(self, url: str) -> Document | None: + headers = { + 'host': urlparse(self.api_base_url).netloc or 'api.microsoft.ai', + 'x-apikey': self.api_key, + 'content-type': 'application/json', + } + payload = { + 'url': url, + 'contentFormat': 'markdown', + 'liveCrawl': 'fallback', + 'renderDynamicPages': True, + 'language': self.language, + } + try: + request_timeout = float(self.timeout) + except (TypeError, ValueError): + request_timeout = 60 + request_timeout = request_timeout if request_timeout > 0 else 60 + + data: dict[str, Any] = {} + for attempt in range(MICROSOFT_BROWSE_MAX_RETRIES + 1): + response = requests.post( + f'{self.api_base_url}/browse', + json=payload, + headers=headers, + timeout=request_timeout, + verify=self.verify_ssl, + ) + + if response.status_code in MICROSOFT_BROWSE_RETRY_STATUS_CODES and attempt < MICROSOFT_BROWSE_MAX_RETRIES: + try: + body = response.json() + except Exception: + body = {} + retry_after = body.get('retryAfter') if isinstance(body, dict) else None + retry_after = retry_after or response.headers.get('Retry-After') + try: + delay = min(10.0, max(0.0, float(str(retry_after).rstrip('s')))) + except (TypeError, ValueError): + delay = min(8.0, float(2**attempt)) + log.warning( + 'Microsoft Browse %s returned HTTP %s; retrying in %.1fs', + url, + response.status_code, + delay, + ) + time.sleep(delay) + continue + + response.raise_for_status() + data = response.json() + break + + content = data.get('content') or '' + if not isinstance(content, str) or not content.strip(): + return None + + metadata = {'source': data.get('url') or url} + if data.get('title'): + metadata['title'] = data['title'] + + return Document(page_content=content, metadata=metadata) diff --git a/backend/open_webui/retrieval/loaders/mineru.py b/backend/open_webui/retrieval/loaders/mineru.py index 63608f9bf9..c641ac9a72 100644 --- a/backend/open_webui/retrieval/loaders/mineru.py +++ b/backend/open_webui/retrieval/loaders/mineru.py @@ -28,20 +28,22 @@ class MinerULoader: api_key: str = '', params: dict = None, timeout: Optional[int] = 300, + max_markdown_bytes: Optional[int] = None, ): self.file_path = file_path self.api_mode = api_mode.lower() self.api_url = api_url.rstrip('/') self.api_key = api_key self.timeout = timeout + self.max_markdown_bytes = max_markdown_bytes # Parse params dict with defaults self.params = params or {} - self.enable_ocr = params.get('enable_ocr', False) - self.enable_formula = params.get('enable_formula', True) - self.enable_table = params.get('enable_table', True) - self.language = params.get('language', 'en') - self.model_version = params.get('model_version', 'pipeline') + self.enable_ocr = self.params.get('enable_ocr', False) + self.enable_formula = self.params.get('enable_formula', True) + self.enable_table = self.params.get('enable_table', True) + self.language = self.params.get('language', 'en') + self.model_version = self.params.get('model_version', 'pipeline') self.page_ranges = self.params.pop('page_ranges', '') @@ -435,67 +437,77 @@ class MinerULoader: detail=f'Error downloading results: {str(e)}', ) - # Save ZIP to temporary file and extract + # Save ZIP to temporary file before reading. + tmp_zip_path = None + markdown_content = None try: with tempfile.NamedTemporaryFile(delete=False, suffix='.zip') as tmp_zip: tmp_zip.write(response.content) tmp_zip_path = tmp_zip.name - with tempfile.TemporaryDirectory() as tmp_dir: - # Extract ZIP - with zipfile.ZipFile(tmp_zip_path, 'r') as zip_ref: - zip_ref.extractall(tmp_dir) + with zipfile.ZipFile(tmp_zip_path, 'r') as zip_ref: + members = zip_ref.infolist() + all_files = [member.filename for member in members] + md_members = [member for member in members if member.filename.endswith('.md')] + read_errors = [] - # Find markdown file - search recursively for any .md file - markdown_content = None - found_md_path = None - - # First, list all files in the ZIP for debugging - all_files = [] - for root, dirs, files in os.walk(tmp_dir): - for file in files: - full_path = os.path.join(root, file) - all_files.append(full_path) - # Look for any .md file - if file.endswith('.md'): - found_md_path = full_path - log.info(f'Found markdown file at: {full_path}') - try: - with open(full_path, 'r', encoding='utf-8') as f: - markdown_content = f.read() - if markdown_content: # Use the first non-empty markdown file - break - except Exception as e: - log.warning(f'Failed to read {full_path}: {e}') + for member in md_members: + log.info(f'Found markdown file in ZIP: {member.filename}') + try: + with zip_ref.open(member, 'r') as f: + if self.max_markdown_bytes is None: + content = f.read() + else: + content = f.read(self.max_markdown_bytes + 1) + if len(content) > self.max_markdown_bytes: + raise HTTPException( + status.HTTP_502_BAD_GATEWAY, + detail=f'Markdown file in results ZIP is too large: {member.filename}', + ) + markdown_content = content.decode('utf-8') + except UnicodeDecodeError as e: + read_errors.append(f'{member.filename}: {e}') + log.warning(f'Failed to decode {member.filename}: {e}') + continue + except HTTPException: + raise + except Exception as e: + read_errors.append(f'{member.filename}: {e}') + log.warning(f'Failed to read {member.filename}: {e}') + continue if markdown_content: break if markdown_content is None: log.error(f'Available files in ZIP: {all_files}') - # Try to provide more helpful error message - md_files = [f for f in all_files if f.endswith('.md')] - if md_files: - error_msg = f"Found .md files but couldn't read them: {md_files}" + if read_errors: + error_msg = f"Found .md files but couldn't read them: {read_errors}" else: error_msg = f'No .md files found in ZIP. Available files: {all_files}' raise HTTPException( status.HTTP_502_BAD_GATEWAY, detail=error_msg, ) - - # Clean up temporary ZIP file - os.unlink(tmp_zip_path) - except zipfile.BadZipFile as e: raise HTTPException( status.HTTP_502_BAD_GATEWAY, detail=f'Invalid ZIP file received: {e}', ) + except HTTPException: + raise except Exception as e: raise HTTPException( status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f'Error extracting ZIP: {str(e)}', ) + finally: + if tmp_zip_path: + try: + os.unlink(tmp_zip_path) + except FileNotFoundError: + pass + except Exception as e: + log.warning(f'Failed to remove temporary ZIP file {tmp_zip_path}: {e}') if not markdown_content: raise HTTPException( diff --git a/backend/open_webui/retrieval/loaders/mistral.py b/backend/open_webui/retrieval/loaders/mistral.py index 465ea5d91e..d9eb740d91 100644 --- a/backend/open_webui/retrieval/loaders/mistral.py +++ b/backend/open_webui/retrieval/loaders/mistral.py @@ -1,4 +1,5 @@ import asyncio +import base64 import logging import os import sys @@ -37,6 +38,7 @@ class MistralLoader: timeout: int = 300, # 5 minutes default max_retries: int = 3, enable_debug_logging: bool = False, + use_base64: bool = False, ): """ Initializes the loader with enhanced features. @@ -47,6 +49,7 @@ class MistralLoader: timeout: Request timeout in seconds. max_retries: Maximum number of retry attempts. enable_debug_logging: Enable detailed debug logs. + use_base64: Send the document as a data URL instead of uploading it first. """ if not api_key: raise ValueError('API key cannot be empty.') @@ -59,6 +62,7 @@ class MistralLoader: self.timeout = timeout self.max_retries = max_retries self.debug = enable_debug_logging + self.use_base64 = use_base64 # PERFORMANCE OPTIMIZATION: Differentiated timeouts for different operations # This prevents long-running OCR operations from affecting quick operations @@ -261,33 +265,32 @@ class MistralLoader: url = f'{self.base_url}/files' async def upload_request(): - # Create multipart writer for streaming upload - writer = aiohttp.MultipartWriter('form-data') + # Open inside the request so the handle stays valid for the whole + # streamed POST and is closed right after. + with open(self.file_path, 'rb') as f: + writer = aiohttp.MultipartWriter('form-data') - # Add purpose field - purpose_part = writer.append('ocr') - purpose_part.set_content_disposition('form-data', name='purpose') + # Add purpose field + purpose_part = writer.append('ocr') + purpose_part.set_content_disposition('form-data', name='purpose') - # Add file part with streaming - file_part = writer.append_payload( - aiohttp.streams.FilePayload( - self.file_path, - filename=self.file_name, - content_type='application/pdf', - ) - ) - file_part.set_content_disposition('form-data', name='file', filename=self.file_name) + # Stream the file. aiohttp builds a payload from the file object; + # the previous aiohttp.streams.FilePayload was removed upstream + # (payloads live in aiohttp.payload and there is no FilePayload), + # so this path raised AttributeError on every async OCR upload. + file_part = writer.append(f, {'Content-Type': 'application/pdf'}) + file_part.set_content_disposition('form-data', name='file', filename=self.file_name) - self._debug_log(f'Uploading file: {self.file_name} ({self.file_size:,} bytes)') + self._debug_log(f'Uploading file: {self.file_name} ({self.file_size:,} bytes)') - async with session.post( - url, - data=writer, - headers=self.headers, - timeout=aiohttp.ClientTimeout(total=self.upload_timeout), - ssl=AIOHTTP_CLIENT_SESSION_SSL, - ) as response: - return await self._handle_response_async(response) + async with session.post( + url, + data=writer, + headers=self.headers, + timeout=aiohttp.ClientTimeout(total=self.upload_timeout), + ssl=AIOHTTP_CLIENT_SESSION_SSL, + ) as response: + return await self._handle_response_async(response) response_data = await self._retry_request_async(upload_request) @@ -417,6 +420,11 @@ class MistralLoader: return await self._retry_request_async(ocr_request) + def _get_file_data_url(self) -> str: + with open(self.file_path, 'rb') as f: + encoded_file = base64.b64encode(f.read()).decode('utf-8') + return f'data:application/pdf;base64,{encoded_file}' + def _delete_file(self, file_id: str) -> None: """Deletes the file from Mistral storage (sync version).""" log.info(f'Deleting uploaded file ID: {file_id}') @@ -566,6 +574,12 @@ class MistralLoader: start_time = time.time() try: + if self.use_base64: + documents = self._process_results(self._process_ocr(self._get_file_data_url())) + total_time = time.time() - start_time + log.info(f'Sync OCR workflow completed in {total_time:.2f}s, produced {len(documents)} documents') + return documents + # 1. Upload file file_id = self._upload_file() @@ -617,6 +631,13 @@ class MistralLoader: try: async with self._get_session() as session: + if self.use_base64: + ocr_response = await self._process_ocr_async(session, self._get_file_data_url()) + documents = self._process_results(ocr_response) + total_time = time.time() - start_time + log.info(f'Async OCR workflow completed in {total_time:.2f}s, produced {len(documents)} documents') + return documents + # 1. Upload file with streaming file_id = await self._upload_file_async(session) diff --git a/backend/open_webui/retrieval/utils.py b/backend/open_webui/retrieval/utils.py index 2db9f47c53..2788d4dd0c 100644 --- a/backend/open_webui/retrieval/utils.py +++ b/backend/open_webui/retrieval/utils.py @@ -39,11 +39,13 @@ from open_webui.models.chats import Chats from open_webui.models.files import Files from open_webui.models.knowledge import Knowledges from open_webui.models.notes import Notes +from open_webui.models.config import Config from open_webui.models.users import UserModel from open_webui.retrieval.loaders.youtube import YoutubeLoader from open_webui.retrieval.vector.async_client import ASYNC_VECTOR_DB_CLIENT +from open_webui.retrieval.external import retrieve_external_knowledge from open_webui.retrieval.vector.factory import VECTOR_DB_CLIENT -from open_webui.retrieval.vector.main import GetResult +from open_webui.retrieval.vector.main import GetResult, SearchResult from open_webui.retrieval.web.utils import get_web_loader from open_webui.utils.access_control.files import has_access_to_file from open_webui.utils.headers import include_user_info_headers @@ -63,65 +65,84 @@ def is_youtube_url(url: str) -> bool: return re.match(youtube_regex, url) is not None -def get_loader(request, url: str): +LOADER_CONFIG_KEYS = { + 'youtube_language': 'rag.youtube_loader_language', + 'youtube_proxy_url': 'rag.youtube_loader_proxy_url', + 'web_loader_ssl_verification': 'web.loader.ssl_verification', + 'web_loader_concurrent_requests': 'web.loader.concurrent_requests', + 'web_search_trust_env': 'web.search.trust_env', + 'CONTENT_EXTRACTION_ENGINE': 'rag.content_extraction_engine', + 'DATALAB_MARKER_API_KEY': 'rag.datalab_marker_api_key', + 'DATALAB_MARKER_API_BASE_URL': 'rag.datalab_marker_api_base_url', + 'DATALAB_MARKER_ADDITIONAL_CONFIG': 'rag.datalab_marker_additional_config', + 'DATALAB_MARKER_SKIP_CACHE': 'rag.datalab_marker_skip_cache', + 'DATALAB_MARKER_FORCE_OCR': 'rag.datalab_marker_force_ocr', + 'DATALAB_MARKER_PAGINATE': 'rag.datalab_marker_paginate', + 'DATALAB_MARKER_STRIP_EXISTING_OCR': 'rag.datalab_marker_strip_existing_ocr', + 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': 'rag.datalab_marker_disable_image_extraction', + 'DATALAB_MARKER_FORMAT_LINES': 'rag.datalab_marker_format_lines', + 'DATALAB_MARKER_USE_LLM': 'rag.datalab_marker_use_llm', + 'DATALAB_MARKER_OUTPUT_FORMAT': 'rag.datalab_marker_output_format', + 'EXTERNAL_DOCUMENT_LOADER_URL': 'rag.external_document_loader_url', + 'EXTERNAL_DOCUMENT_LOADER_API_KEY': 'rag.external_document_loader_api_key', + 'EXTERNAL_DOCUMENT_LOADER_HEADERS': 'rag.external_document_loader_headers', + 'TIKA_SERVER_URL': 'rag.tika_server_url', + 'DOCLING_SERVER_URL': 'rag.docling_server_url', + 'DOCLING_API_KEY': 'rag.docling_api_key', + 'DOCLING_PARAMS': 'rag.docling_params', + 'PDF_EXTRACT_IMAGES': 'rag.pdf_extract_images', + 'PDF_LOADER_MODE': 'rag.pdf_loader_mode', + 'DOCUMENT_INTELLIGENCE_ENDPOINT': 'rag.document_intelligence_endpoint', + 'DOCUMENT_INTELLIGENCE_KEY': 'rag.document_intelligence_key', + 'DOCUMENT_INTELLIGENCE_MODEL': 'rag.document_intelligence_model', + 'MISTRAL_OCR_API_BASE_URL': 'rag.mistral_ocr_api_base_url', + 'MISTRAL_OCR_API_KEY': 'rag.mistral_ocr_api_key', + 'MISTRAL_OCR_USE_BASE64': 'rag.mistral_ocr_use_base64', + 'PADDLEOCR_VL_BASE_URL': 'rag.paddleocr_vl_base_url', + 'PADDLEOCR_VL_TOKEN': 'rag.paddleocr_vl_token', + 'MINERU_API_MODE': 'rag.mineru_api_mode', + 'MINERU_API_URL': 'rag.mineru_api_url', + 'MINERU_API_KEY': 'rag.mineru_api_key', + 'MINERU_API_TIMEOUT': 'rag.mineru_api_timeout', + 'MINERU_PARAMS': 'rag.mineru_params', + 'MINERU_FILE_EXTENSIONS': 'rag.mineru_file_extensions', +} + + +async def get_loader_config(): + values = await Config.get_many(*LOADER_CONFIG_KEYS.values()) + return {name: values.get(key) for name, key in LOADER_CONFIG_KEYS.items()} + + +def get_loader(request, url: str, config: dict): if is_youtube_url(url): return YoutubeLoader( url, - language=request.app.state.config.YOUTUBE_LOADER_LANGUAGE, - proxy_url=request.app.state.config.YOUTUBE_LOADER_PROXY_URL, + language=config.get('youtube_language'), + proxy_url=config.get('youtube_proxy_url'), ) - else: - return get_web_loader( - url, - verify_ssl=request.app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION, - requests_per_second=request.app.state.config.WEB_LOADER_CONCURRENT_REQUESTS, - trust_env=request.app.state.config.WEB_SEARCH_TRUST_ENV, - ) - - -def build_loader_from_config(request): - """Build a Loader instance with the admin's configured extraction engine settings.""" - from open_webui.retrieval.loaders.main import Loader - - config = request.app.state.config - return Loader( - engine=config.CONTENT_EXTRACTION_ENGINE, - DATALAB_MARKER_API_KEY=config.DATALAB_MARKER_API_KEY, - DATALAB_MARKER_API_BASE_URL=config.DATALAB_MARKER_API_BASE_URL, - DATALAB_MARKER_ADDITIONAL_CONFIG=config.DATALAB_MARKER_ADDITIONAL_CONFIG, - DATALAB_MARKER_SKIP_CACHE=config.DATALAB_MARKER_SKIP_CACHE, - DATALAB_MARKER_FORCE_OCR=config.DATALAB_MARKER_FORCE_OCR, - DATALAB_MARKER_PAGINATE=config.DATALAB_MARKER_PAGINATE, - DATALAB_MARKER_STRIP_EXISTING_OCR=config.DATALAB_MARKER_STRIP_EXISTING_OCR, - DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION=config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, - DATALAB_MARKER_FORMAT_LINES=config.DATALAB_MARKER_FORMAT_LINES, - DATALAB_MARKER_USE_LLM=config.DATALAB_MARKER_USE_LLM, - DATALAB_MARKER_OUTPUT_FORMAT=config.DATALAB_MARKER_OUTPUT_FORMAT, - EXTERNAL_DOCUMENT_LOADER_URL=config.EXTERNAL_DOCUMENT_LOADER_URL, - EXTERNAL_DOCUMENT_LOADER_API_KEY=config.EXTERNAL_DOCUMENT_LOADER_API_KEY, - TIKA_SERVER_URL=config.TIKA_SERVER_URL, - DOCLING_SERVER_URL=config.DOCLING_SERVER_URL, - DOCLING_API_KEY=config.DOCLING_API_KEY, - DOCLING_PARAMS=config.DOCLING_PARAMS, - PDF_EXTRACT_IMAGES=config.PDF_EXTRACT_IMAGES, - PDF_LOADER_MODE=config.PDF_LOADER_MODE, - DOCUMENT_INTELLIGENCE_ENDPOINT=config.DOCUMENT_INTELLIGENCE_ENDPOINT, - DOCUMENT_INTELLIGENCE_KEY=config.DOCUMENT_INTELLIGENCE_KEY, - DOCUMENT_INTELLIGENCE_MODEL=config.DOCUMENT_INTELLIGENCE_MODEL, - MISTRAL_OCR_API_BASE_URL=config.MISTRAL_OCR_API_BASE_URL, - MISTRAL_OCR_API_KEY=config.MISTRAL_OCR_API_KEY, - PADDLEOCR_VL_BASE_URL=config.PADDLEOCR_VL_BASE_URL, - PADDLEOCR_VL_TOKEN=config.PADDLEOCR_VL_TOKEN, - MINERU_API_MODE=config.MINERU_API_MODE, - MINERU_API_URL=config.MINERU_API_URL, - MINERU_API_KEY=config.MINERU_API_KEY, - MINERU_API_TIMEOUT=config.MINERU_API_TIMEOUT, - MINERU_PARAMS=config.MINERU_PARAMS, - MINERU_FILE_EXTENSIONS=config.MINERU_FILE_EXTENSIONS, + return get_web_loader( + url, + verify_ssl=config.get('web_loader_ssl_verification'), + requests_per_second=config.get('web_loader_concurrent_requests'), + trust_env=config.get('web_search_trust_env'), ) -def _extract_text_from_binary_response(request, response: requests.Response, url: str) -> tuple[str, list]: +def build_loader_from_config(request, config: dict): + """Build a Loader instance with the admin's configured extraction engine settings.""" + from open_webui.retrieval.loaders.main import Loader + + loader_config = {key: config.get(key) for key in LOADER_CONFIG_KEYS if key.isupper()} + return Loader( + engine=loader_config['CONTENT_EXTRACTION_ENGINE'], + **{key: value for key, value in loader_config.items() if key != 'CONTENT_EXTRACTION_ENGINE'}, + ) + + +def _extract_text_from_binary_response( + request, response: requests.Response, url: str, loader_config: dict +) -> tuple[str, list]: """Download response body to a temp file and extract text using the Loader pipeline.""" import mimetypes import tempfile @@ -150,7 +171,7 @@ def _extract_text_from_binary_response(request, response: requests.Response, url tmp_path = tmp.name try: - loader = build_loader_from_config(request) + loader = build_loader_from_config(request, loader_config) docs = loader.load(filename, content_type, tmp_path) for doc in docs: doc.metadata['source'] = url @@ -170,8 +191,17 @@ def _is_text_content_type(content_type: str) -> bool: return not ct # empty / missing → assume HTML -def get_content_from_url(request, url: str) -> str: - from open_webui.retrieval.web.utils import validate_url +async def get_content_from_url(request, url: str) -> str: + loader_config = await get_loader_config() + + # The rest of this function performs synchronous, blocking work: an SSRF-guarded + # `requests` probe and a synchronous document loader (`loader.load()`). Run it in a + # worker thread so the event loop stays free while waiting on network/parsing. + return await asyncio.to_thread(_get_content_from_url_sync, request, url, loader_config) + + +def _get_content_from_url_sync(request, url: str, loader_config): + from open_webui.retrieval.web.utils import validate_url, _SSRFSafeAdapter # Validate URL before making any request (blocks private IPs, non-HTTP, filter list) validate_url(url) @@ -183,7 +213,7 @@ def get_content_from_url(request, url: str) -> str: # when allow_redirects=False, causing the binary-content path to run # and produce empty docs → HTTP 400. if is_youtube_url(url): - loader = get_loader(request, url) + loader = get_loader(request, url, loader_config) docs = loader.load() content = ' '.join([doc.page_content for doc in docs]) return content, docs @@ -194,7 +224,11 @@ def get_content_from_url(request, url: str) -> str: # re-validation would let an attacker reach private IPs (RFC1918, loopback, # cloud-metadata 169.254.169.254) via a public host that redirects internally. try: - response = requests.get(url, stream=True, timeout=30, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS) + # Probe through the connect-time SSRF guard; bare requests.get re-resolves (DNS-rebinding gap). + session = requests.Session() + session.mount('http://', _SSRFSafeAdapter()) + session.mount('https://', _SSRFSafeAdapter()) + response = session.get(url, stream=True, timeout=30, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS) response.raise_for_status() content_type = response.headers.get('Content-Type', '') except Exception: @@ -205,14 +239,14 @@ def get_content_from_url(request, url: str) -> str: if response is None or _is_text_content_type(content_type): if response is not None: response.close() - loader = get_loader(request, url) + loader = get_loader(request, url, loader_config) docs = loader.load() content = ' '.join([doc.page_content for doc in docs]) return content, docs # Binary content (PDF, DOCX, XLSX, PPTX, etc.) — download and extract try: - return _extract_text_from_binary_response(request, response, url) + return _extract_text_from_binary_response(request, response, url, loader_config) finally: response.close() @@ -255,21 +289,7 @@ class VectorSearchRetriever(BaseRetriever): limit=self.top_k, ) - ids = result.ids[0] - metadatas = result.metadatas[0] - documents = result.documents[0] - - results = [] - for idx in range(len(ids)): - metadata = metadatas[idx] - metadata[CHUNK_HASH_KEY] = _content_hash(documents[idx]) - results.append( - Document( - metadata=metadata, - page_content=documents[idx], - ) - ) - return results + return _search_result_to_documents(result) def query_doc(collection_name: str, query_embedding: list[float], k: int, user: UserModel = None): @@ -338,9 +358,96 @@ def get_enriched_texts(collection_result: GetResult) -> list[str]: return enriched_texts +def _search_result_to_documents(result: SearchResult | None) -> list[Document]: + ids = result.ids[0] if result and result.ids else [] + metadatas = result.metadatas[0] if result and result.metadatas else [] + documents = result.documents[0] if result and result.documents else [] + distances = result.distances[0] if result and result.distances else [] + + docs = [] + for idx in range(len(ids)): + document = documents[idx] + metadata = dict(metadatas[idx] or {}) + metadata[CHUNK_HASH_KEY] = _content_hash(document) + if idx < len(distances): + metadata.setdefault('score', distances[idx]) + docs.append(Document(metadata=metadata, page_content=document)) + return docs + + +def _supports_native_hybrid_search() -> bool: + supports_hybrid_search = getattr(ASYNC_VECTOR_DB_CLIENT, 'supports_hybrid_search', None) + if supports_hybrid_search is not None: + return bool(supports_hybrid_search) + return callable(getattr(ASYNC_VECTOR_DB_CLIENT, 'hybrid_search', None)) + + +async def query_doc_with_native_hybrid_search( + collection_name: str, + query: str, + embedding_function, + k: int, + reranking_function, + k_reranker: int, + r: float, + hybrid_bm25_weight: float, +) -> Optional[dict]: + try: + if not _supports_native_hybrid_search(): + return None + + query_vectors = [] + if hybrid_bm25_weight < 1: + query_vectors = [await embedding_function(query, RAG_EMBEDDING_QUERY_PREFIX)] + + result = await ASYNC_VECTOR_DB_CLIENT.hybrid_search( + collection_name=collection_name, + query=query, + vectors=query_vectors, + limit=k, + hybrid_bm25_weight=hybrid_bm25_weight, + ) + if result is None: + return None + + documents = _search_result_to_documents(result) + if not documents: + return {'distances': [[]], 'documents': [[]], 'metadatas': [[]]} + + compressor = RerankCompressor( + embedding_function=embedding_function, + top_n=k_reranker, + reranking_function=reranking_function, + r_score=r, + ) + compressed = await compressor.acompress_documents(documents, query) + + distances = [d.metadata.get('score') for d in compressed] + documents = [d.page_content for d in compressed] + metadatas = [d.metadata for d in compressed] + + if k < k_reranker: + sorted_items = sorted(zip(distances, documents, metadatas), key=lambda x: x[0], reverse=True) + sorted_items = sorted_items[:k] + + if sorted_items: + distances, documents, metadatas = map(list, zip(*sorted_items)) + else: + distances, documents, metadatas = [], [], [] + + return { + 'distances': [distances], + 'documents': [documents], + 'metadatas': [metadatas], + } + except Exception as e: + log.debug(f'Native hybrid search failed for {collection_name}, falling back to legacy hybrid search: {e}') + return None + + async def query_doc_with_hybrid_search( collection_name: str, - collection_result: GetResult, + collection_result: Optional[GetResult], query: str, embedding_function, k: int, @@ -349,8 +456,26 @@ async def query_doc_with_hybrid_search( r: float, hybrid_bm25_weight: float, enable_enriched_texts: bool = False, + native_hybrid_search: bool = True, ) -> dict: try: + if native_hybrid_search and not enable_enriched_texts: + native_result = await query_doc_with_native_hybrid_search( + collection_name=collection_name, + query=query, + embedding_function=embedding_function, + k=k, + reranking_function=reranking_function, + k_reranker=k_reranker, + r=r, + hybrid_bm25_weight=hybrid_bm25_weight, + ) + if native_result is not None: + return native_result + + if collection_result is None: + collection_result = await ASYNC_VECTOR_DB_CLIENT.get(collection_name=collection_name) + # First check if collection_result has the required attributes if ( not collection_result @@ -539,8 +664,15 @@ async def query_collection( embedding_function, k: int, ) -> dict: + config = await Config.get_many( + 'rag.enable_hybrid_search', + 'rag.top_k_reranker', + 'rag.relevance_threshold', + 'rag.hybrid_bm25_weight', + 'rag.enable_hybrid_search_enriched_texts', + ) # When request is provided, try hybrid search + reranking if enabled - if request and request.app.state.config.ENABLE_RAG_HYBRID_SEARCH: + if request and config.get('rag.enable_hybrid_search'): try: reranking_function = ( (lambda query, documents: request.app.state.RERANKING_FUNCTION(query, documents)) @@ -553,10 +685,10 @@ async def query_collection( embedding_function=embedding_function, k=k, reranking_function=reranking_function, - k_reranker=request.app.state.config.TOP_K_RERANKER, - r=request.app.state.config.RELEVANCE_THRESHOLD, - hybrid_bm25_weight=request.app.state.config.HYBRID_BM25_WEIGHT, - enable_enriched_texts=request.app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, + k_reranker=config.get('rag.top_k_reranker'), + r=config.get('rag.relevance_threshold'), + hybrid_bm25_weight=config.get('rag.hybrid_bm25_weight'), + enable_enriched_texts=config.get('rag.enable_hybrid_search_enriched_texts'), ) except Exception as e: log.debug(f'Hybrid search failed, falling back to vector search: {e}') @@ -623,6 +755,28 @@ async def query_collection_with_hybrid_search( ) -> dict: results = [] error = False + + if not enable_enriched_texts: + + async def process_native_query(collection_name, query): + result = await query_doc_with_native_hybrid_search( + collection_name=collection_name, + query=query, + embedding_function=embedding_function, + k=k, + reranking_function=reranking_function, + k_reranker=k_reranker, + r=r, + hybrid_bm25_weight=hybrid_bm25_weight, + ) + return result + + native_task_results = await asyncio.gather( + *[process_native_query(collection_name, query) for collection_name in collection_names for query in queries] + ) + if native_task_results and all(result is not None for result in native_task_results): + return merge_and_sort_query_results(native_task_results, k=k) + # Fetch every collection's contents once up front so the # per-query/per-document loop below can reuse them. Each fetch # offloads to a worker thread, so run them concurrently with @@ -657,6 +811,7 @@ async def query_collection_with_hybrid_search( r=r, hybrid_bm25_weight=hybrid_bm25_weight, enable_enriched_texts=enable_enriched_texts, + native_hybrid_search=False, ) return result, None except Exception as e: @@ -927,15 +1082,15 @@ def get_embedding_function( concurrent_requests=0, ) -> Awaitable: if embedding_engine == '': - if embedding_function is None: - raise ValueError( - 'No embedding model is loaded. Set RAG_EMBEDDING_MODEL to a valid ' - 'SentenceTransformer model name, or configure an external ' - 'RAG_EMBEDDING_ENGINE (ollama, openai, azure_openai).' - ) - # Sentence transformers: CPU-bound sync operation async def async_embedding_function(query, prefix=None, user=None): + # Deferred so a missing local model degrades RAG instead of crashing boot. + if embedding_function is None: + raise ValueError( + 'No embedding model is loaded. Set RAG_EMBEDDING_MODEL to a valid ' + 'SentenceTransformer model name, or configure an external ' + 'RAG_EMBEDDING_ENGINE (ollama, openai, azure_openai).' + ) return await asyncio.to_thread( ( lambda query, prefix=None: embedding_function.encode( @@ -1165,6 +1320,7 @@ async def get_sources_from_items( ): log.debug(f'items: {items} {queries} {embedding_function} {reranking_function} {full_context}') + bypass_embedding_and_retrieval = await Config.get('rag.bypass_embedding_and_retrieval') extracted_collections = [] query_results = [] @@ -1244,14 +1400,14 @@ async def get_sources_from_items( } elif item.get('type') == 'url': - content, docs = get_content_from_url(request, item.get('url')) + content, docs = await get_content_from_url(request, item.get('url')) if docs: query_result = { 'documents': [[content]], 'metadatas': [[{'url': item.get('url'), 'name': item.get('url')}]], } elif item.get('type') == 'file': - if item.get('context') == 'full' or request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL: + if item.get('context') == 'full' or bypass_embedding_and_retrieval: if item.get('file', {}).get('data', {}).get('content', ''): # Manual Full Mode Toggle # Used from chat file modal, we can assume that the file content will be available from item.get("file").get("data", {}).get("content") @@ -1323,50 +1479,61 @@ async def get_sources_from_items( permission='read', ) ): - if item.get('context') == 'full' or request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL: - if knowledge_base and ( - user.role == 'admin' - or knowledge_base.user_id == user.id - or await AccessGrants.has_access( - user_id=user.id, - resource_type='knowledge', - resource_id=knowledge_base.id, - permission='read', - ) - ): - files = await Knowledges.get_files_by_id(knowledge_base.id) + if (knowledge_base.meta or {}).get('source') == 'external': + query_result = await retrieve_external_knowledge( + request, + knowledge_base, + queries=queries, + count=k, + user=user, + ) + extracted_collections.append(knowledge_base.id) - documents = [] - metadatas = [] - for file in files: - documents.append(file.data.get('content', '')) - metadatas.append( - { - 'file_id': file.id, - 'name': file.filename, - 'source': file.filename, - } - ) - - query_result = { - 'documents': [documents], - 'metadatas': [metadatas], - } else: - if item.get('legacy'): - if BYPASS_RETRIEVAL_ACCESS_CONTROL: - collection_names = item.get('collection_names', []) - else: - # Legacy KB: item.collection_names is client-supplied. - # Validate against the KB's actual files to prevent - # cross-tenant collection name substitution. + if item.get('context') == 'full' or bypass_embedding_and_retrieval: + if knowledge_base and ( + user.role == 'admin' + or knowledge_base.user_id == user.id + or await AccessGrants.has_access( + user_id=user.id, + resource_type='knowledge', + resource_id=knowledge_base.id, + permission='read', + ) + ): files = await Knowledges.get_files_by_id(knowledge_base.id) - owned_names = {f'file-{f.id}' for f in files} - owned_names.add(knowledge_base.id) - valid_names = [n for n in (item.get('collection_names') or []) if n in owned_names] - collection_names = valid_names if valid_names else [knowledge_base.id] + + documents = [] + metadatas = [] + for file in files: + documents.append(file.data.get('content', '')) + metadatas.append( + { + 'file_id': file.id, + 'name': file.filename, + 'source': file.filename, + } + ) + + query_result = { + 'documents': [documents], + 'metadatas': [metadatas], + } else: - collection_names.append(item['id']) + if item.get('legacy'): + if BYPASS_RETRIEVAL_ACCESS_CONTROL: + collection_names = item.get('collection_names', []) + else: + # Legacy KB: item.collection_names is client-supplied. + # Validate against the KB's actual files to prevent + # cross-tenant collection name substitution. + files = await Knowledges.get_files_by_id(knowledge_base.id) + owned_names = {f'file-{f.id}' for f in files} + owned_names.add(knowledge_base.id) + valid_names = [n for n in (item.get('collection_names') or []) if n in owned_names] + collection_names = valid_names if valid_names else [knowledge_base.id] + else: + collection_names.append(item['id']) elif item.get('docs'): # BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL @@ -1374,6 +1541,10 @@ async def get_sources_from_items( 'documents': [[doc.get('content') for doc in item.get('docs')]], 'metadatas': [[doc.get('metadata') for doc in item.get('docs')]], } + elif item.get('type') == 'web_search' and item.get('collection_name'): + # Trusted server-generated collection; authorized by + # filter_accessible_collections below (allowlists web-search-*). + collection_names.append(item['collection_name']) elif item.get('collection_name'): if BYPASS_RETRIEVAL_ACCESS_CONTROL: collection_names.append(item['collection_name']) diff --git a/backend/open_webui/retrieval/vector/async_client.py b/backend/open_webui/retrieval/vector/async_client.py index 0bea6696a9..481f26e19f 100644 --- a/backend/open_webui/retrieval/vector/async_client.py +++ b/backend/open_webui/retrieval/vector/async_client.py @@ -82,6 +82,10 @@ class AsyncVectorDBClient: (e.g. already inside a worker thread).""" return self._sync + @property + def supports_hybrid_search(self) -> bool: + return type(self._sync).hybrid_search is not VectorDBBase.hybrid_search + async def has_collection(self, collection_name: str) -> bool: return await asyncio.to_thread(self._sync.has_collection, collection_name) @@ -103,6 +107,25 @@ class AsyncVectorDBClient: ) -> Optional[SearchResult]: return await asyncio.to_thread(self._sync.search, collection_name, vectors, filter, limit) + async def hybrid_search( + self, + collection_name: str, + query: str, + vectors: List[List[Union[float, int]]], + filter: Optional[Dict] = None, + limit: int = 10, + hybrid_bm25_weight: float = 0.5, + ) -> Optional[SearchResult]: + return await asyncio.to_thread( + self._sync.hybrid_search, + collection_name, + query, + vectors, + filter, + limit, + hybrid_bm25_weight, + ) + async def query( self, collection_name: str, diff --git a/backend/open_webui/retrieval/vector/dbs/chroma.py b/backend/open_webui/retrieval/vector/dbs/chroma.py index cd0a59eeaf..408a02111f 100755 --- a/backend/open_webui/retrieval/vector/dbs/chroma.py +++ b/backend/open_webui/retrieval/vector/dbs/chroma.py @@ -57,7 +57,11 @@ class ChromaClient(VectorDBBase): def has_collection(self, collection_name: str) -> bool: # Check if the collection exists based on the collection name. - collection_names = self.client.list_collections() + # chromadb's list_collections() returns Collection objects (1.x), so a + # bare `name in collections` membership test is always False — compare + # against the names. (hasattr guard tolerates versions that yield names.) + collections = self.client.list_collections() + collection_names = [c.name if hasattr(c, 'name') else c for c in collections] return collection_name in collection_names def delete_collection(self, collection_name: str): diff --git a/backend/open_webui/retrieval/vector/dbs/milvus.py b/backend/open_webui/retrieval/vector/dbs/milvus.py index 9b356b1c69..b0331e3eea 100644 --- a/backend/open_webui/retrieval/vector/dbs/milvus.py +++ b/backend/open_webui/retrieval/vector/dbs/milvus.py @@ -27,9 +27,15 @@ from open_webui.retrieval.vector.main import ( from open_webui.retrieval.vector.utils import process_metadata from pymilvus import Collection, DataType, FieldSchema, connections from pymilvus import MilvusClient as Client +from pymilvus.exceptions import MilvusException log = logging.getLogger(__name__) +# Milvus caps stored text length (here the chunk lives under the JSON `data` +# field). Clamp long chunks before insert so one oversized chunk can't fail the +# whole batch and leave the file with zero embeddings. +MILVUS_TEXT_MAX_LENGTH = 65535 + class MilvusClient(VectorDBBase): def __init__(self): @@ -270,18 +276,28 @@ class MilvusClient(VectorDBBase): self._create_collection(collection_name=collection_name, dimension=len(items[0]['vector'])) log.info(f'Inserting {len(items)} items into collection {self.collection_prefix}_{collection_name}.') - return self.client.insert( - collection_name=f'{self.collection_prefix}_{collection_name}', - data=[ + data = [] + for item in items: + text = item['text'] or '' + if len(text) > MILVUS_TEXT_MAX_LENGTH: + log.warning(f'Milvus: truncating text id={item["id"]} {len(text)}->{MILVUS_TEXT_MAX_LENGTH} chars') + text = text[:MILVUS_TEXT_MAX_LENGTH] + data.append( { 'id': item['id'], 'vector': item['vector'], - 'data': {'text': item['text']}, + 'data': {'text': text}, 'metadata': process_metadata(item['metadata']), } - for item in items - ], - ) + ) + try: + return self.client.insert( + collection_name=f'{self.collection_prefix}_{collection_name}', + data=data, + ) + except MilvusException as e: + log.error(f'Milvus insert failed for {self.collection_prefix}_{collection_name} ({len(items)} items): {e}') + raise def upsert(self, collection_name: str, items: list[VectorItem]): # Update the items in the collection, if the items are not present, insert them. If the collection does not exist, it will be created. @@ -298,18 +314,28 @@ class MilvusClient(VectorDBBase): self._create_collection(collection_name=collection_name, dimension=len(items[0]['vector'])) log.info(f'Upserting {len(items)} items into collection {self.collection_prefix}_{collection_name}.') - return self.client.upsert( - collection_name=f'{self.collection_prefix}_{collection_name}', - data=[ + data = [] + for item in items: + text = item['text'] or '' + if len(text) > MILVUS_TEXT_MAX_LENGTH: + log.warning(f'Milvus: truncating text id={item["id"]} {len(text)}->{MILVUS_TEXT_MAX_LENGTH} chars') + text = text[:MILVUS_TEXT_MAX_LENGTH] + data.append( { 'id': item['id'], 'vector': item['vector'], - 'data': {'text': item['text']}, + 'data': {'text': text}, 'metadata': process_metadata(item['metadata']), } - for item in items - ], - ) + ) + try: + return self.client.upsert( + collection_name=f'{self.collection_prefix}_{collection_name}', + data=data, + ) + except MilvusException as e: + log.error(f'Milvus upsert failed for {self.collection_prefix}_{collection_name} ({len(items)} items): {e}') + raise def delete( self, diff --git a/backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py b/backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py index af64919b6e..6549c58c62 100644 --- a/backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py +++ b/backend/open_webui/retrieval/vector/dbs/milvus_multitenancy.py @@ -31,10 +31,15 @@ from pymilvus import ( connections, utility, ) +from pymilvus.exceptions import MilvusException log = logging.getLogger(__name__) RESOURCE_ID_FIELD = 'resource_id' +# Milvus VARCHAR hard cap for the `text` field (see _create_shared_collection). +# Chunks longer than this are truncated before insert so one oversized chunk +# can't fail the whole batch (and leave the file with zero embeddings). +MILVUS_TEXT_MAX_LENGTH = 65535 # Milvus expressions are SQL-like strings with no parameterized-query API; # values get interpolated into single-quoted literals. Reject anything that @@ -169,17 +174,34 @@ class MilvusClient(VectorDBBase): self._ensure_collection(mt_collection, dimension) collection = Collection(mt_collection) - entities = [ - { - 'id': item['id'], - 'vector': item['vector'], - 'text': item['text'], - 'metadata': item['metadata'], - RESOURCE_ID_FIELD: resource_id, - } - for item in items - ] - collection.insert(entities) + entities = [] + for item in items: + text = item['text'] or '' + if len(text) > MILVUS_TEXT_MAX_LENGTH: + log.warning( + f'Milvus: truncating text id={item["id"]} ' + f'{len(text)}->{MILVUS_TEXT_MAX_LENGTH} chars ' + f'(collection={mt_collection}, resource_id={resource_id})' + ) + text = text[:MILVUS_TEXT_MAX_LENGTH] + entities.append( + { + 'id': item['id'], + 'vector': item['vector'], + 'text': text, + 'metadata': item['metadata'], + RESOURCE_ID_FIELD: resource_id, + } + ) + + try: + collection.insert(entities) + except MilvusException as e: + log.error( + f'Milvus insert failed (collection={mt_collection}, ' + f'resource_id={resource_id}, items={len(entities)}): {e}' + ) + raise def search( self, diff --git a/backend/open_webui/retrieval/vector/dbs/pgvector.py b/backend/open_webui/retrieval/vector/dbs/pgvector.py index 861d49bc1b..b37d774f72 100644 --- a/backend/open_webui/retrieval/vector/dbs/pgvector.py +++ b/backend/open_webui/retrieval/vector/dbs/pgvector.py @@ -24,7 +24,7 @@ from open_webui.retrieval.vector.main import ( VectorDBBase, VectorItem, ) -from open_webui.retrieval.vector.utils import process_metadata +from open_webui.retrieval.vector.utils import merge_hybrid_search_results, process_metadata from open_webui.utils.misc import sanitize_text_for_db from pgvector.sqlalchemy import HALFVEC, Vector from sqlalchemy import ( @@ -153,6 +153,7 @@ class PgvectorClient(VectorDBBase): index_method, index_options = self._vector_index_configuration() self._ensure_vector_index(index_method, index_options) + self._ensure_text_search_index() self.session.execute( text( @@ -236,6 +237,19 @@ class PgvectorClient(VectorDBBase): f' {index_options}' if index_options else '', ) + def _ensure_text_search_index(self) -> None: + if PGVECTOR_PGCRYPTO: + return + + self.session.execute( + text(""" + CREATE INDEX IF NOT EXISTS idx_document_chunk_text_search + ON document_chunk + USING GIN (to_tsvector('simple', coalesce(text, ''))); + """) + ) + log.info("Ensured text search index 'idx_document_chunk_text_search'.") + def check_vector_length(self) -> None: """ Check if the VECTOR_LENGTH matches the existing vector column dimension in the database. @@ -521,6 +535,71 @@ class PgvectorClient(VectorDBBase): log.exception(f'Error during search: {e}') return None + def hybrid_search( + self, + collection_name: str, + query: str, + vectors: List[List[float]], + filter: Optional[Dict[str, Any]] = None, + limit: int = 10, + hybrid_bm25_weight: float = 0.5, + ) -> Optional[SearchResult]: + if PGVECTOR_PGCRYPTO or filter: + return None + + try: + limit = max(1, limit) + vectors = [self.adjust_vector_length(vector) for vector in vectors] if vectors else [] + num_queries = len(vectors) if vectors else 1 + bm25_weight = min(max(hybrid_bm25_weight, 0.0), 1.0) + vector_weight = 1.0 - bm25_weight + + vector_result = None + if vector_weight > 0 and vectors: + vector_result = self.search(collection_name=collection_name, vectors=vectors, limit=limit) + + fts_results = [] + if bm25_weight > 0 and query and query.strip(): + fts_rows = self.session.execute( + text(""" + WITH fts_query AS ( + SELECT plainto_tsquery('simple', :query) AS query + ) + SELECT + document_chunk.id AS id, + document_chunk.text AS text, + document_chunk.vmetadata AS vmetadata, + ts_rank_cd( + to_tsvector('simple', coalesce(document_chunk.text, '')), + fts_query.query + ) AS rank + FROM document_chunk, fts_query + WHERE document_chunk.collection_name = :collection_name + AND to_tsvector('simple', coalesce(document_chunk.text, '')) @@ fts_query.query + ORDER BY rank DESC + LIMIT :limit + """), + { + 'collection_name': collection_name, + 'query': query, + 'limit': limit, + }, + ) + fts_results = [dict(row) for row in fts_rows.mappings().all()] + self.session.rollback() + + return merge_hybrid_search_results( + vector_result=vector_result, + fts_results=fts_results, + num_queries=num_queries, + limit=limit, + hybrid_bm25_weight=hybrid_bm25_weight, + ) + except Exception as e: + self.session.rollback() + log.exception(f'Error during hybrid search: {e}') + return None + def query(self, collection_name: str, filter: Dict[str, Any], limit: Optional[int] = None) -> Optional[GetResult]: try: if PGVECTOR_PGCRYPTO: diff --git a/backend/open_webui/retrieval/vector/main.py b/backend/open_webui/retrieval/vector/main.py index 38ea699514..dd284eae1a 100644 --- a/backend/open_webui/retrieval/vector/main.py +++ b/backend/open_webui/retrieval/vector/main.py @@ -63,6 +63,18 @@ class VectorDBBase(ABC): """Search for similar vectors in a collection.""" pass + def hybrid_search( + self, + collection_name: str, + query: str, + vectors: List[List[Union[float, int]]], + filter: Optional[Dict] = None, + limit: int = 10, + hybrid_bm25_weight: float = 0.5, + ) -> Optional[SearchResult]: + """Search using a backend-native hybrid keyword/vector implementation when available.""" + return None + @abstractmethod def query(self, collection_name: str, filter: Dict, limit: Optional[int] = None) -> Optional[GetResult]: """Query vectors from a collection using metadata filter.""" diff --git a/backend/open_webui/retrieval/vector/utils.py b/backend/open_webui/retrieval/vector/utils.py index 4915b024c3..31b5b0748c 100644 --- a/backend/open_webui/retrieval/vector/utils.py +++ b/backend/open_webui/retrieval/vector/utils.py @@ -1,5 +1,7 @@ -from datetime import datetime +import datetime as dt +from typing import Any +from open_webui.retrieval.vector.main import SearchResult from open_webui.utils.misc import sanitize_text_for_db KEYS_TO_EXCLUDE = ['content', 'pages', 'tables', 'paragraphs', 'sections', 'figures'] @@ -21,9 +23,71 @@ def process_metadata( # Skip large fields if key in KEYS_TO_EXCLUDE: continue + if value is None: + continue # Convert non-serializable fields to strings - if isinstance(value, (datetime, list, dict)): + if isinstance(value, (dt.datetime, list, dict)): result[key] = sanitize_text_for_db(str(value)) else: result[key] = sanitize_text_for_db(value) return result + + +def merge_hybrid_search_results( + vector_result: SearchResult | None, + fts_results: list[dict[str, Any]], + num_queries: int, + limit: int, + hybrid_bm25_weight: float, +) -> SearchResult: + rank_constant = 60.0 + bm25_weight = min(max(hybrid_bm25_weight, 0.0), 1.0) + vector_weight = 1.0 - bm25_weight + + ids = [[] for _ in range(num_queries)] + distances = [[] for _ in range(num_queries)] + documents = [[] for _ in range(num_queries)] + metadatas = [[] for _ in range(num_queries)] + + for qid in range(num_queries): + candidates: dict[str, dict[str, Any]] = {} + + if vector_result and vector_result.ids and qid < len(vector_result.ids): + for rank, item_id in enumerate(vector_result.ids[qid] or [], start=1): + score = vector_weight / (rank_constant + rank) if vector_weight > 0 else 0 + if score <= 0: + continue + + candidate = candidates.setdefault( + item_id, + { + 'score': 0.0, + 'document': vector_result.documents[qid][rank - 1], + 'metadata': vector_result.metadatas[qid][rank - 1], + }, + ) + candidate['score'] += score + + for rank, row in enumerate(fts_results, start=1): + score = bm25_weight / (rank_constant + rank) if bm25_weight > 0 else 0 + if score <= 0: + continue + + item_id = row['id'] + candidate = candidates.setdefault( + item_id, + { + 'score': 0.0, + 'document': row['text'], + 'metadata': row['vmetadata'], + }, + ) + candidate['score'] += score + + ranked = sorted(candidates.items(), key=lambda item: item[1]['score'], reverse=True)[:limit] + ids[qid] = [item_id for item_id, _ in ranked] + distances[qid] = [candidate['score'] for _, candidate in ranked] + documents[qid] = [candidate['document'] for _, candidate in ranked] + metadatas[qid] = [candidate['metadata'] for _, candidate in ranked] + + return SearchResult(ids=ids, distances=distances, documents=documents, metadatas=metadatas) diff --git a/backend/open_webui/retrieval/web/main.py b/backend/open_webui/retrieval/web/main.py index a55c62c8b5..56f796db58 100644 --- a/backend/open_webui/retrieval/web/main.py +++ b/backend/open_webui/retrieval/web/main.py @@ -4,7 +4,7 @@ from urllib.parse import urlparse import validators from open_webui.retrieval.web.utils import resolve_hostname -from open_webui.utils.misc import is_string_allowed +from open_webui.utils.misc import is_host_allowed from pydantic import BaseModel @@ -32,7 +32,7 @@ def get_filtered_results(results, filter_list): except Exception: pass - if is_string_allowed(hostnames, filter_list): + if is_host_allowed(hostnames, filter_list): filtered_results.append(result) continue diff --git a/backend/open_webui/retrieval/web/microsoft_web_iq.py b/backend/open_webui/retrieval/web/microsoft_web_iq.py new file mode 100644 index 0000000000..c4188b684c --- /dev/null +++ b/backend/open_webui/retrieval/web/microsoft_web_iq.py @@ -0,0 +1,60 @@ +from __future__ import annotations + +import logging +from urllib.parse import urlparse + +import requests +from open_webui.retrieval.web.main import SearchResult, get_filtered_results +from open_webui.utils.headers import include_user_info_headers + +log = logging.getLogger(__name__) + +DEFAULT_MICROSOFT_WEB_IQ_API_BASE_URL = 'https://api.microsoft.ai/v3' + + +def search_microsoft_web_iq( + api_base_url: str, + api_key: str, + query: str, + count: int, + filter_list: list[str | None] | None = None, + language: str = 'en', + user=None, +) -> list[SearchResult]: + try: + api_base_url = (api_base_url or DEFAULT_MICROSOFT_WEB_IQ_API_BASE_URL).rstrip('/') + headers = { + 'host': urlparse(api_base_url).netloc or 'api.microsoft.ai', + 'x-apikey': api_key, + 'content-type': 'application/json', + } + if user is not None: + headers = include_user_info_headers(headers, user) + + response = requests.post( + f'{api_base_url}/search/web', + json={ + 'query': query, + 'maxResults': count, + 'language': language, + 'contentFormat': 'passage', + }, + headers=headers, + ) + response.raise_for_status() + + results = response.json().get('webResults', []) + if filter_list: + results = get_filtered_results(results, filter_list) + + return [ + SearchResult( + link=result['url'], + title=result.get('title'), + snippet=result.get('content'), + ) + for result in results + ] + except Exception as e: + log.error(f'Error searching with Microsoft Web IQ API: {e}') + return [] diff --git a/backend/open_webui/retrieval/web/perplexity.py b/backend/open_webui/retrieval/web/perplexity.py index 05f2d5d51c..79f8b7b600 100644 --- a/backend/open_webui/retrieval/web/perplexity.py +++ b/backend/open_webui/retrieval/web/perplexity.py @@ -38,9 +38,7 @@ def search_perplexity( """ - # Handle ConfigVar object - if hasattr(api_key, '__str__'): - api_key = str(api_key) + api_key = str(api_key) try: url = 'https://api.perplexity.ai/chat/completions' diff --git a/backend/open_webui/retrieval/web/perplexity_search.py b/backend/open_webui/retrieval/web/perplexity_search.py index f3284f9586..ad38565621 100644 --- a/backend/open_webui/retrieval/web/perplexity_search.py +++ b/backend/open_webui/retrieval/web/perplexity_search.py @@ -29,12 +29,8 @@ def search_perplexity_search( """ - # Handle ConfigVar object - if hasattr(api_key, '__str__'): - api_key = str(api_key) - - if hasattr(api_url, '__str__'): - api_url = str(api_url) + api_key = str(api_key) + api_url = str(api_url) try: url = api_url diff --git a/backend/open_webui/retrieval/web/serphouse.py b/backend/open_webui/retrieval/web/serphouse.py new file mode 100644 index 0000000000..7b8ae59ac0 --- /dev/null +++ b/backend/open_webui/retrieval/web/serphouse.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from open_webui.retrieval.web.main import SearchResult, get_filtered_results +from open_webui.utils.session_pool import get_session + + +async def search_serphouse( + api_key: str, + domain: str, + query: str, + count: int, + filter_list: list[str | None] | None = None, +) -> list[SearchResult]: + """Query SERPHouse and return normalised organic results.""" + session = await get_session() + async with session.get( + 'https://api.serphouse.com/serp/live', + params={ + 'q': query, + 'domain': (domain or 'google.com').strip() or 'google.com', + 'device': 'desktop', + 'serp_type': 'web', + 'page': 1, + 'num_result': count, + }, + headers={'Authorization': f'Bearer {api_key}', 'Accept': 'application/json'}, + ) as response: + response.raise_for_status() + payload = await response.json() + + organic = payload.get('results', {}).get('results', {}).get('organic', []) + organic = sorted(organic, key=lambda item: item.get('position', 0)) + if filter_list: + organic = get_filtered_results(organic, filter_list) + + return [ + SearchResult( + link=item.get('link', ''), + title=item.get('title'), + snippet=item.get('snippet'), + ) + for item in organic[:count] + if item.get('link') + ] diff --git a/backend/open_webui/retrieval/web/utils.py b/backend/open_webui/retrieval/web/utils.py index afa73a9e0e..0cb10eb9a6 100644 --- a/backend/open_webui/retrieval/web/utils.py +++ b/backend/open_webui/retrieval/web/utils.py @@ -21,7 +21,6 @@ from typing import ( import aiohttp import aiohttp.resolver import certifi -import requests import urllib3.connection import urllib3.connectionpool import validators @@ -31,12 +30,15 @@ from langchain_community.document_loaders import PlaywrightURLLoader, WebBaseLoa from langchain_community.document_loaders.base import BaseLoader from langchain_core.documents import Document from open_webui.config import ( - ENABLE_RAG_LOCAL_WEB_FETCH, + ENABLE_LOCAL_WEB_FETCH, EXTERNAL_WEB_LOADER_API_KEY, EXTERNAL_WEB_LOADER_URL, FIRECRAWL_API_BASE_URL, FIRECRAWL_API_KEY, FIRECRAWL_TIMEOUT, + MICROSOFT_WEB_IQ_API_BASE_URL, + MICROSOFT_WEB_IQ_API_KEY, + MICROSOFT_WEB_IQ_LANGUAGE, PLAYWRIGHT_TIMEOUT, PLAYWRIGHT_WS_URL, TAVILY_API_KEY, @@ -46,11 +48,17 @@ from open_webui.config import ( WEB_LOADER_TIMEOUT, ) from open_webui.constants import ERROR_MESSAGES -from open_webui.env import AIOHTTP_CLIENT_ALLOW_REDIRECTS, AIOHTTP_CLIENT_SESSION_SSL, USER_AGENT +from open_webui.env import ( + AIOHTTP_CLIENT_ALLOW_REDIRECTS, + AIOHTTP_CLIENT_SESSION_SSL, + AIOHTTP_CLIENT_TIMEOUT, + USER_AGENT, +) from open_webui.retrieval.loaders.external_web import ExternalWebLoader +from open_webui.retrieval.loaders.microsoft_web_iq import MicrosoftWebIQLoader from open_webui.retrieval.loaders.tavily import TavilyLoader from open_webui.retrieval.web.firecrawl import scrape_firecrawl_url -from open_webui.utils.misc import is_string_allowed +from open_webui.utils.misc import is_host_allowed log = logging.getLogger(__name__) @@ -88,12 +96,14 @@ def validate_url(url: Union[str, Sequence[str]]): # Blocklist check using unified filtering logic if WEB_FETCH_FILTER_LIST: - if not is_string_allowed(url, WEB_FETCH_FILTER_LIST): + # Match on the parsed hostname, not the full URL: a path component would + # otherwise let any URL slip past a hostname-based block/allow entry. + if not is_host_allowed(parsed_url.hostname, WEB_FETCH_FILTER_LIST): log.warning(f'URL blocked by filter list: {url}') raise ValueError(ERROR_MESSAGES.INVALID_URL) - if not ENABLE_RAG_LOCAL_WEB_FETCH: - # Local web fetch is disabled, filter out any URLs that resolve to private IP addresses + if not ENABLE_LOCAL_WEB_FETCH: + # Local web fetch is disabled, filter out URLs that resolve to non-global IP addresses. parsed_url = urllib.parse.urlparse(url) # Get IPv4 and IPv6 addresses ipv4_addresses, ipv6_addresses = resolve_hostname(parsed_url.hostname) @@ -134,7 +144,7 @@ def _ssrf_safe_new_conn(self): infos = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM) if not infos: raise OSError(f'getaddrinfo for {host!r} returned empty list') - if not ENABLE_RAG_LOCAL_WEB_FETCH: + if not ENABLE_LOCAL_WEB_FETCH: for _, _, _, _, sa in infos: if not ipaddress.ip_address(sa[0]).is_global: raise ValueError(ERROR_MESSAGES.INVALID_URL) @@ -190,13 +200,26 @@ class _SSRFSafeResolver(aiohttp.resolver.DefaultResolver): async def resolve(self, host, port=0, family=socket.AF_INET): results = await super().resolve(host, port, family) - if not ENABLE_RAG_LOCAL_WEB_FETCH: + if not ENABLE_LOCAL_WEB_FETCH: for entry in results: if not ipaddress.ip_address(entry['host']).is_global: raise ValueError(ERROR_MESSAGES.INVALID_URL) return results +def get_ssrf_safe_session() -> aiohttp.ClientSession: + """A one-off aiohttp session that re-validates the connect-time IP via _SSRFSafeResolver, + defeating DNS rebinding. Use for validate_url-gated fetches of user-supplied URLs that must + not use the shared (rebinding-vulnerable) pool. Use as a context manager so it is closed: + ``async with get_ssrf_safe_session() as session: ...``. + """ + return aiohttp.ClientSession( + connector=aiohttp.TCPConnector(resolver=_SSRFSafeResolver()), + timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT), + trust_env=True, + ) + + def extract_metadata(soup, url): metadata = {'source': url} if title := soup.find('title'): @@ -303,8 +326,9 @@ class SafeFireCrawlLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): self.params = params or {} def lazy_load(self) -> Iterator[Document]: - try: - for url in self.web_paths: + for url in self.web_paths: + try: + self._sync_wait_for_rate_limit() doc = scrape_firecrawl_url( self.api_url, self.api_key, @@ -315,28 +339,39 @@ class SafeFireCrawlLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): ) if doc is not None: yield doc - except Exception as e: - if self.continue_on_failure: - log.warning(f'Error extracting content from URLs with Firecrawl: {e}') - else: - raise e + except Exception as e: + if self.continue_on_failure: + log.warning(f'Error extracting content from {url} with Firecrawl: {e}') + continue + raise async def alazy_load(self): - try: - docs = await run_in_threadpool(lambda: list(self.lazy_load())) - for doc in docs: - yield doc - except Exception as e: - if self.continue_on_failure: - log.warning(f'Error extracting content from URLs with Firecrawl: {e}') - else: - raise e + for url in self.web_paths: + try: + await self._wait_for_rate_limit() + doc = await run_in_threadpool( + scrape_firecrawl_url, + self.api_url, + self.api_key, + url, + verify_ssl=self.verify_ssl, + timeout=self.timeout, + params=self.params, + ) + if doc is not None: + yield doc + except Exception as e: + if self.continue_on_failure: + log.warning(f'Error extracting content from {url} with Firecrawl: {e}') + continue + raise class SafeTavilyLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): def __init__( self, web_paths: Union[str, List[str]], + api_base_url: str, api_key: str, extract_depth: Literal['basic', 'advanced'] = 'basic', continue_on_failure: bool = True, @@ -370,6 +405,7 @@ class SafeTavilyLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): # Store parameters for creating TavilyLoader instances self.web_paths = web_paths if isinstance(web_paths, list) else [web_paths] + self.api_base_url = api_base_url self.api_key = api_key self.extract_depth = extract_depth self.continue_on_failure = continue_on_failure @@ -445,6 +481,67 @@ class SafeTavilyLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): raise e +class SafeMicrosoftWebIQLoader(BaseLoader, RateLimitMixin, URLProcessingMixin): + def __init__( + self, + web_paths: Union[str, List[str]], + api_key: str, + language: str = 'en', + verify_ssl: bool = True, + trust_env: bool = False, + requests_per_second: Optional[float] = None, + continue_on_failure: bool = True, + timeout: Optional[int] = None, + ): + self.web_paths = web_paths if isinstance(web_paths, list) else [web_paths] + self.api_key = api_key + self.language = language + self.verify_ssl = verify_ssl + self.trust_env = trust_env + self.requests_per_second = requests_per_second + self.last_request_time = None + self.continue_on_failure = continue_on_failure + self.timeout = timeout + + def lazy_load(self) -> Iterator[Document]: + valid_urls = [] + for url in self.web_paths: + try: + self._safe_process_url_sync(url) + valid_urls.append(url) + except Exception as e: + log.warning(f'SSL verification failed for {url}: {str(e)}') + if not self.continue_on_failure: + raise e + if not valid_urls: + if self.continue_on_failure: + log.warning('No valid URLs to process after SSL verification') + return + raise ValueError('No valid URLs to process after SSL verification') + + loader = MicrosoftWebIQLoader( + urls=valid_urls, + api_base_url=self.api_base_url, + api_key=self.api_key, + language=self.language, + verify_ssl=self.verify_ssl, + timeout=self.timeout, + continue_on_failure=self.continue_on_failure, + ) + yield from loader.lazy_load() + + async def alazy_load(self) -> AsyncIterator[Document]: + try: + docs = await run_in_threadpool(lambda: list(self.lazy_load())) + for doc in docs: + yield doc + except Exception as e: + if self.continue_on_failure: + log.warning(f'Error browsing URLs with Microsoft Web IQ: {e}') + else: + raise e + + class SafePlaywrightURLLoader(PlaywrightURLLoader, RateLimitMixin, URLProcessingMixin): """Load HTML pages safely with Playwright, supporting SSL verification, rate limiting, and remote browser connection. @@ -757,13 +854,13 @@ def get_web_loader( 'trust_env': trust_env, } - if WEB_LOADER_ENGINE.value == '' or WEB_LOADER_ENGINE.value == 'safe_web': + if WEB_LOADER_ENGINE == '' or WEB_LOADER_ENGINE == 'safe_web': WebLoaderClass = SafeWebBaseLoader request_kwargs = {} - if WEB_LOADER_TIMEOUT.value: + if WEB_LOADER_TIMEOUT: try: - timeout_value = float(WEB_LOADER_TIMEOUT.value) + timeout_value = float(WEB_LOADER_TIMEOUT) except ValueError: timeout_value = None @@ -773,31 +870,42 @@ def get_web_loader( if request_kwargs: web_loader_args['requests_kwargs'] = request_kwargs - if WEB_LOADER_ENGINE.value == 'playwright': + if WEB_LOADER_ENGINE == 'playwright': WebLoaderClass = SafePlaywrightURLLoader - web_loader_args['playwright_timeout'] = PLAYWRIGHT_TIMEOUT.value - if PLAYWRIGHT_WS_URL.value: - web_loader_args['playwright_ws_url'] = PLAYWRIGHT_WS_URL.value + web_loader_args['playwright_timeout'] = PLAYWRIGHT_TIMEOUT + if PLAYWRIGHT_WS_URL: + web_loader_args['playwright_ws_url'] = PLAYWRIGHT_WS_URL - if WEB_LOADER_ENGINE.value == 'firecrawl': + if WEB_LOADER_ENGINE == 'firecrawl': WebLoaderClass = SafeFireCrawlLoader - web_loader_args['api_key'] = FIRECRAWL_API_KEY.value - web_loader_args['api_url'] = FIRECRAWL_API_BASE_URL.value - if FIRECRAWL_TIMEOUT.value: + web_loader_args['api_key'] = FIRECRAWL_API_KEY + web_loader_args['api_url'] = FIRECRAWL_API_BASE_URL + if FIRECRAWL_TIMEOUT: try: - web_loader_args['timeout'] = int(FIRECRAWL_TIMEOUT.value) + web_loader_args['timeout'] = int(FIRECRAWL_TIMEOUT) except ValueError: pass - if WEB_LOADER_ENGINE.value == 'tavily': + if WEB_LOADER_ENGINE == 'tavily': WebLoaderClass = SafeTavilyLoader - web_loader_args['api_key'] = TAVILY_API_KEY.value - web_loader_args['extract_depth'] = TAVILY_EXTRACT_DEPTH.value + web_loader_args['api_key'] = TAVILY_API_KEY + web_loader_args['extract_depth'] = TAVILY_EXTRACT_DEPTH - if WEB_LOADER_ENGINE.value == 'external': + if WEB_LOADER_ENGINE == 'microsoft_web_iq': + WebLoaderClass = SafeMicrosoftWebIQLoader + web_loader_args['api_base_url'] = MICROSOFT_WEB_IQ_API_BASE_URL + web_loader_args['api_key'] = MICROSOFT_WEB_IQ_API_KEY + web_loader_args['language'] = MICROSOFT_WEB_IQ_LANGUAGE + if WEB_LOADER_TIMEOUT: + try: + web_loader_args['timeout'] = int(WEB_LOADER_TIMEOUT) + except ValueError: + pass + + if WEB_LOADER_ENGINE == 'external': WebLoaderClass = ExternalWebLoader - web_loader_args['external_url'] = EXTERNAL_WEB_LOADER_URL.value - web_loader_args['external_api_key'] = EXTERNAL_WEB_LOADER_API_KEY.value + web_loader_args['external_url'] = EXTERNAL_WEB_LOADER_URL + web_loader_args['external_api_key'] = EXTERNAL_WEB_LOADER_API_KEY if WebLoaderClass: web_loader = WebLoaderClass(**web_loader_args) @@ -811,6 +919,6 @@ def get_web_loader( return web_loader else: raise ValueError( - f'Invalid WEB_LOADER_ENGINE: {WEB_LOADER_ENGINE.value}. ' - "Please set it to 'safe_web', 'playwright', 'firecrawl', or 'tavily'." + f'Invalid WEB_LOADER_ENGINE: {WEB_LOADER_ENGINE}. ' + "Please set it to 'safe_web', 'playwright', 'firecrawl', 'tavily', 'external', or 'microsoft_web_iq'." ) diff --git a/backend/open_webui/routers/analytics.py b/backend/open_webui/routers/analytics.py index fcef30342c..d9cf8e0a61 100644 --- a/backend/open_webui/routers/analytics.py +++ b/backend/open_webui/routers/analytics.py @@ -28,6 +28,8 @@ router = APIRouter() class ModelAnalyticsEntry(BaseModel): model_id: str count: int + unique_users: int = 0 + unique_chats: int = 0 class ModelAnalyticsResponse(BaseModel): @@ -65,8 +67,16 @@ async def get_model_analytics( counts = await ChatMessages.get_message_count_by_model( start_date=start_date, end_date=end_date, group_id=group_id, db=db ) + unique_counts = await ChatMessages.get_unique_counts_by_model( + start_date=start_date, end_date=end_date, group_id=group_id, db=db + ) models = [ - ModelAnalyticsEntry(model_id=model_id, count=count) + ModelAnalyticsEntry( + model_id=model_id, + count=count, + unique_users=unique_counts.get(model_id, {}).get('unique_users', 0), + unique_chats=unique_counts.get(model_id, {}).get('unique_chats', 0), + ) for model_id, count in sorted(counts.items(), key=lambda x: -x[1]) ] return ModelAnalyticsResponse(models=models) @@ -269,6 +279,9 @@ class ModelChatsResponse(BaseModel): total: int +MODEL_CHAT_ORDER_FIELDS = {'title', 'updated_at', 'user_name'} + + @router.get('/models/{model_id:path}/chats', response_model=ModelChatsResponse) async def get_model_chats( model_id: str, @@ -276,65 +289,34 @@ async def get_model_chats( end_date: Optional[int] = Query(None), skip: int = Query(0), limit: int = Query(50, le=100), + order_by: str = Query('updated_at'), + direction: str = Query('desc'), user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session), ): """Get chats that used a specific model, with preview and feedback info.""" + filter = {} + if start_date: + filter['start_date'] = start_date + if end_date: + filter['end_date'] = end_date + if order_by in MODEL_CHAT_ORDER_FIELDS: + filter['order_by'] = order_by + if direction in {'asc', 'desc'}: + filter['direction'] = direction - # Get chat IDs that used this model - chat_ids = await ChatMessages.get_chat_ids_by_model_id( + result = await Chats.get_chats_by_model_id( model_id=model_id, - start_date=start_date, - end_date=end_date, + filter=filter, skip=skip, limit=limit, db=db, ) - if not chat_ids: - return ModelChatsResponse(chats=[], total=0) - - # Get chat details from messages only - chats_data = [] - for chat_id in chat_ids: - messages = await ChatMessages.get_messages_by_chat_id(chat_id, db=db) - if not messages: - continue - - # Get user_id from first user message - first_user_msg = next((m for m in messages if m.role == 'user'), None) - user_id = first_user_msg.user_id if first_user_msg else None - - # Extract first message content as preview - first_message = None - if first_user_msg and first_user_msg.content: - content = first_user_msg.content - if isinstance(content, str): - first_message = content[:200] - elif isinstance(content, list): - text_parts = [b.get('text', '') for b in content if isinstance(b, dict)] - first_message = ' '.join(text_parts)[:200] - - # Get user info - user_name = None - if user_id: - user_info = await Users.get_user_by_id(user_id, db=db) - user_name = user_info.name if user_info else None - - # Timestamps from messages - updated_at = max(m.created_at for m in messages) if messages else 0 - - chats_data.append( - ModelChatEntry( - chat_id=chat_id, - user_id=user_id, - user_name=user_name, - first_message=first_message, - updated_at=updated_at, - ) - ) - - return ModelChatsResponse(chats=chats_data, total=len(chats_data)) + return ModelChatsResponse( + chats=[ModelChatEntry.model_validate(chat) for chat in result['items']], + total=result['total'] or 0, + ) #################### @@ -367,6 +349,12 @@ async def get_model_overview( ): """Get model overview with feedback history and chat tags.""" + # Calculate start date for history + now = datetime.now() + start_dt = None + if days > 0: + start_dt = now - timedelta(days=days) + # Get chat IDs that used this model chat_ids = await ChatMessages.get_chat_ids_by_model_id( model_id=model_id, @@ -377,31 +365,18 @@ async def get_model_overview( db=db, ) - # Get feedback history per day - history_counts: dict[str, dict] = defaultdict(lambda: {'won': 0, 'lost': 0}) - - # Calculate start date for history - now = datetime.now() - start_dt = None - if days > 0: - start_dt = now - timedelta(days=days) - - for chat_id in chat_ids: - feedbacks = await Feedbacks.get_feedbacks_by_chat_id(chat_id, db=db) - for fb in feedbacks: - if fb.data and 'rating' in fb.data: - rating = fb.data['rating'] - fb_date = datetime.fromtimestamp(fb.created_at) - - # Filter by date range - if start_dt and fb_date < start_dt: - continue - - date_str = fb_date.strftime('%Y-%m-%d') - if rating == 1: - history_counts[date_str]['won'] += 1 - elif rating == -1: - history_counts[date_str]['lost'] += 1 + history_rows = await Feedbacks.get_model_feedback_counts_by_day( + model_id=model_id, + start_date=int(start_dt.timestamp()) if start_dt else None, + db=db, + ) + history_counts = { + entry.date: { + 'won': entry.won, + 'lost': entry.lost, + } + for entry in history_rows + } # Fill in missing days history = [] @@ -430,10 +405,14 @@ async def get_model_overview( # Get chat tags tag_counts: dict[str, int] = defaultdict(int) - for chat_id in chat_ids: - chat = await Chats.get_chat_by_id(chat_id, db=db) - if chat and chat.meta: - for tag in chat.meta.get('tags', []): + if chat_ids: + chat_metas = await Chats.get_chat_metas_by_chat_ids( + chat_ids, + include_archived=True, + db=db, + ) + for meta in chat_metas: + for tag in meta.get('tags', []): tag_counts[tag] += 1 # Sort by count and take top 10 diff --git a/backend/open_webui/routers/audio.py b/backend/open_webui/routers/audio.py index 441915972d..8310f49a2c 100644 --- a/backend/open_webui/routers/audio.py +++ b/backend/open_webui/routers/audio.py @@ -28,6 +28,8 @@ from fastapi import ( ) from fastapi.responses import FileResponse from pydantic import BaseModel + +# pydub needs stdlib audioop (gone in 3.13); keep requires-python capped < 3.13 from pydub import AudioSegment from pydub.silence import split_on_silence from pydub.utils import mediainfo @@ -52,6 +54,8 @@ from open_webui.env import ( ENABLE_FORWARD_USER_INFO_HEADERS, ENV, ) +from open_webui.events import EVENTS, publish_event +from open_webui.models.config import Config from open_webui.utils.access_control import has_permission from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.headers import include_user_info_headers @@ -71,6 +75,50 @@ AZURE_MAX_FILE_SIZE: int = AZURE_MAX_FILE_SIZE_MB * 1024 * 1024 SPEECH_CACHE_DIR = CACHE_DIR / 'audio' / 'speech' SPEECH_CACHE_DIR.mkdir(parents=True, exist_ok=True) +TTS_CONFIG_KEYS = { + 'OPENAI_API_BASE_URL': 'audio.tts.openai.api_base_url', + 'OPENAI_API_KEY': 'audio.tts.openai.api_key', + 'OPENAI_PARAMS': 'audio.tts.openai.params', + 'API_KEY': 'audio.tts.api_key', + 'ENGINE': 'audio.tts.engine', + 'MODEL': 'audio.tts.model', + 'VOICE': 'audio.tts.voice', + 'SPLIT_ON': 'audio.tts.split_on', + 'AZURE_SPEECH_REGION': 'audio.tts.azure.speech_region', + 'AZURE_SPEECH_BASE_URL': 'audio.tts.azure.speech_base_url', + 'AZURE_SPEECH_OUTPUT_FORMAT': 'audio.tts.azure.speech_output_format', + 'MISTRAL_API_KEY': 'audio.tts.mistral.api_key', + 'MISTRAL_API_BASE_URL': 'audio.tts.mistral.api_base_url', +} + +STT_CONFIG_KEYS = { + 'OPENAI_API_BASE_URL': 'audio.stt.openai.api_base_url', + 'OPENAI_API_KEY': 'audio.stt.openai.api_key', + 'ENGINE': 'audio.stt.engine', + 'MODEL': 'audio.stt.model', + 'SUPPORTED_CONTENT_TYPES': 'audio.stt.supported_content_types', + 'ALLOWED_EXTENSIONS': 'audio.stt.allowed_extensions', + 'WHISPER_MODEL': 'audio.stt.whisper_model', + 'DEEPGRAM_API_KEY': 'audio.stt.deepgram.api_key', + 'AZURE_API_KEY': 'audio.stt.azure.api_key', + 'AZURE_REGION': 'audio.stt.azure.region', + 'AZURE_LOCALES': 'audio.stt.azure.locales', + 'AZURE_BASE_URL': 'audio.stt.azure.base_url', + 'AZURE_MAX_SPEAKERS': 'audio.stt.azure.max_speakers', + 'MISTRAL_API_KEY': 'audio.stt.mistral.api_key', + 'MISTRAL_API_BASE_URL': 'audio.stt.mistral.api_base_url', + 'MISTRAL_USE_CHAT_COMPLETIONS': 'audio.stt.mistral.use_chat_completions', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +def config_updates(data: dict, key_map: dict[str, str]) -> dict: + return {key_map[field]: value for field, value in data.items() if field in key_map} + def is_audio_conversion_required(file_path): """ @@ -228,119 +276,39 @@ class AudioConfigUpdateForm(BaseModel): @router.get('/config') async def get_audio_config(request: Request, user=Depends(get_admin_user)): return { - 'tts': { - 'OPENAI_API_BASE_URL': request.app.state.config.TTS_OPENAI_API_BASE_URL, - 'OPENAI_API_KEY': request.app.state.config.TTS_OPENAI_API_KEY, - 'OPENAI_PARAMS': request.app.state.config.TTS_OPENAI_PARAMS, - 'API_KEY': request.app.state.config.TTS_API_KEY, - 'ENGINE': request.app.state.config.TTS_ENGINE, - 'MODEL': request.app.state.config.TTS_MODEL, - 'VOICE': request.app.state.config.TTS_VOICE, - 'SPLIT_ON': request.app.state.config.TTS_SPLIT_ON, - 'AZURE_SPEECH_REGION': request.app.state.config.TTS_AZURE_SPEECH_REGION, - 'AZURE_SPEECH_BASE_URL': request.app.state.config.TTS_AZURE_SPEECH_BASE_URL, - 'AZURE_SPEECH_OUTPUT_FORMAT': request.app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT, - 'MISTRAL_API_KEY': request.app.state.config.TTS_MISTRAL_API_KEY, - 'MISTRAL_API_BASE_URL': request.app.state.config.TTS_MISTRAL_API_BASE_URL, - }, - 'stt': { - 'OPENAI_API_BASE_URL': request.app.state.config.STT_OPENAI_API_BASE_URL, - 'OPENAI_API_KEY': request.app.state.config.STT_OPENAI_API_KEY, - 'ENGINE': request.app.state.config.STT_ENGINE, - 'MODEL': request.app.state.config.STT_MODEL, - 'SUPPORTED_CONTENT_TYPES': request.app.state.config.STT_SUPPORTED_CONTENT_TYPES, - 'ALLOWED_EXTENSIONS': request.app.state.config.STT_ALLOWED_EXTENSIONS, - 'WHISPER_MODEL': request.app.state.config.WHISPER_MODEL, - 'DEEPGRAM_API_KEY': request.app.state.config.DEEPGRAM_API_KEY, - 'AZURE_API_KEY': request.app.state.config.AUDIO_STT_AZURE_API_KEY, - 'AZURE_REGION': request.app.state.config.AUDIO_STT_AZURE_REGION, - 'AZURE_LOCALES': request.app.state.config.AUDIO_STT_AZURE_LOCALES, - 'AZURE_BASE_URL': request.app.state.config.AUDIO_STT_AZURE_BASE_URL, - 'AZURE_MAX_SPEAKERS': request.app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS, - 'MISTRAL_API_KEY': request.app.state.config.AUDIO_STT_MISTRAL_API_KEY, - 'MISTRAL_API_BASE_URL': request.app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL, - 'MISTRAL_USE_CHAT_COMPLETIONS': request.app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS, - }, + 'tts': await get_config_values(TTS_CONFIG_KEYS), + 'stt': await get_config_values(STT_CONFIG_KEYS), } @router.post('/config/update') async def update_audio_config(request: Request, form_data: AudioConfigUpdateForm, user=Depends(get_admin_user)): - # TTS settings - request.app.state.config.TTS_OPENAI_API_BASE_URL = form_data.tts.OPENAI_API_BASE_URL - request.app.state.config.TTS_OPENAI_API_KEY = form_data.tts.OPENAI_API_KEY - request.app.state.config.TTS_OPENAI_PARAMS = form_data.tts.OPENAI_PARAMS - request.app.state.config.TTS_API_KEY = form_data.tts.API_KEY - request.app.state.config.TTS_ENGINE = form_data.tts.ENGINE - request.app.state.config.TTS_MODEL = form_data.tts.MODEL - request.app.state.config.TTS_VOICE = form_data.tts.VOICE - request.app.state.config.TTS_SPLIT_ON = form_data.tts.SPLIT_ON - request.app.state.config.TTS_AZURE_SPEECH_REGION = form_data.tts.AZURE_SPEECH_REGION - request.app.state.config.TTS_AZURE_SPEECH_BASE_URL = form_data.tts.AZURE_SPEECH_BASE_URL - request.app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT = form_data.tts.AZURE_SPEECH_OUTPUT_FORMAT - request.app.state.config.TTS_MISTRAL_API_KEY = form_data.tts.MISTRAL_API_KEY - request.app.state.config.TTS_MISTRAL_API_BASE_URL = form_data.tts.MISTRAL_API_BASE_URL + await Config.upsert( + { + **config_updates(form_data.tts.model_dump(), TTS_CONFIG_KEYS), + **config_updates(form_data.stt.model_dump(), STT_CONFIG_KEYS), + } + ) - # STT settings - request.app.state.config.STT_OPENAI_API_BASE_URL = form_data.stt.OPENAI_API_BASE_URL - request.app.state.config.STT_OPENAI_API_KEY = form_data.stt.OPENAI_API_KEY - request.app.state.config.STT_ENGINE = form_data.stt.ENGINE - request.app.state.config.STT_MODEL = form_data.stt.MODEL - request.app.state.config.STT_SUPPORTED_CONTENT_TYPES = form_data.stt.SUPPORTED_CONTENT_TYPES - request.app.state.config.STT_ALLOWED_EXTENSIONS = form_data.stt.ALLOWED_EXTENSIONS - request.app.state.config.WHISPER_MODEL = form_data.stt.WHISPER_MODEL - request.app.state.config.DEEPGRAM_API_KEY = form_data.stt.DEEPGRAM_API_KEY - request.app.state.config.AUDIO_STT_AZURE_API_KEY = form_data.stt.AZURE_API_KEY - request.app.state.config.AUDIO_STT_AZURE_REGION = form_data.stt.AZURE_REGION - request.app.state.config.AUDIO_STT_AZURE_LOCALES = form_data.stt.AZURE_LOCALES - request.app.state.config.AUDIO_STT_AZURE_BASE_URL = form_data.stt.AZURE_BASE_URL - request.app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS = form_data.stt.AZURE_MAX_SPEAKERS - request.app.state.config.AUDIO_STT_MISTRAL_API_KEY = form_data.stt.MISTRAL_API_KEY - request.app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL = form_data.stt.MISTRAL_API_BASE_URL - request.app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS = form_data.stt.MISTRAL_USE_CHAT_COMPLETIONS - - if request.app.state.config.STT_ENGINE == '': - request.app.state.faster_whisper_model = set_faster_whisper_model( - form_data.stt.WHISPER_MODEL, WHISPER_MODEL_AUTO_UPDATE + if form_data.stt.ENGINE == '': + request.app.state.faster_whisper_model = await asyncio.to_thread( + set_faster_whisper_model, form_data.stt.WHISPER_MODEL, WHISPER_MODEL_AUTO_UPDATE ) else: request.app.state.faster_whisper_model = None - return { - 'tts': { - 'ENGINE': request.app.state.config.TTS_ENGINE, - 'MODEL': request.app.state.config.TTS_MODEL, - 'VOICE': request.app.state.config.TTS_VOICE, - 'OPENAI_API_BASE_URL': request.app.state.config.TTS_OPENAI_API_BASE_URL, - 'OPENAI_API_KEY': request.app.state.config.TTS_OPENAI_API_KEY, - 'OPENAI_PARAMS': request.app.state.config.TTS_OPENAI_PARAMS, - 'API_KEY': request.app.state.config.TTS_API_KEY, - 'SPLIT_ON': request.app.state.config.TTS_SPLIT_ON, - 'AZURE_SPEECH_REGION': request.app.state.config.TTS_AZURE_SPEECH_REGION, - 'AZURE_SPEECH_BASE_URL': request.app.state.config.TTS_AZURE_SPEECH_BASE_URL, - 'AZURE_SPEECH_OUTPUT_FORMAT': request.app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT, - 'MISTRAL_API_KEY': request.app.state.config.TTS_MISTRAL_API_KEY, - 'MISTRAL_API_BASE_URL': request.app.state.config.TTS_MISTRAL_API_BASE_URL, + config = await get_audio_config(request, user) + await publish_event( + request, + EVENTS.CONFIG_UPDATED, + actor=user, + subject_id='audio', + data={ + 'tts_engine': config.get('tts', {}).get('ENGINE'), + 'stt_engine': config.get('stt', {}).get('ENGINE'), }, - 'stt': { - 'OPENAI_API_BASE_URL': request.app.state.config.STT_OPENAI_API_BASE_URL, - 'OPENAI_API_KEY': request.app.state.config.STT_OPENAI_API_KEY, - 'ENGINE': request.app.state.config.STT_ENGINE, - 'MODEL': request.app.state.config.STT_MODEL, - 'SUPPORTED_CONTENT_TYPES': request.app.state.config.STT_SUPPORTED_CONTENT_TYPES, - 'ALLOWED_EXTENSIONS': request.app.state.config.STT_ALLOWED_EXTENSIONS, - 'WHISPER_MODEL': request.app.state.config.WHISPER_MODEL, - 'DEEPGRAM_API_KEY': request.app.state.config.DEEPGRAM_API_KEY, - 'AZURE_API_KEY': request.app.state.config.AUDIO_STT_AZURE_API_KEY, - 'AZURE_REGION': request.app.state.config.AUDIO_STT_AZURE_REGION, - 'AZURE_LOCALES': request.app.state.config.AUDIO_STT_AZURE_LOCALES, - 'AZURE_BASE_URL': request.app.state.config.AUDIO_STT_AZURE_BASE_URL, - 'AZURE_MAX_SPEAKERS': request.app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS, - 'MISTRAL_API_KEY': request.app.state.config.AUDIO_STT_MISTRAL_API_KEY, - 'MISTRAL_API_BASE_URL': request.app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL, - 'MISTRAL_USE_CHAT_COMPLETIONS': request.app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS, - }, - } + ) + return config def load_speech_pipeline(request): @@ -388,14 +356,16 @@ async def _write_tts_cache( async def _tts_openai(request, payload, file_path, file_body_path, user): """Generate speech via an OpenAI-compatible TTS endpoint.""" - payload['model'] = request.app.state.config.TTS_MODEL + payload['model'] = await Config.get('audio.tts.model') if not payload.get('voice'): - payload['voice'] = request.app.state.config.TTS_VOICE - payload = {**payload, **(request.app.state.config.TTS_OPENAI_PARAMS or {})} + payload['voice'] = await Config.get('audio.tts.voice') + payload = {**payload, **(await Config.get('audio.tts.openai.params') or {})} + api_key = await Config.get('audio.tts.openai.api_key') + api_base_url = await Config.get('audio.tts.openai.api_base_url') headers = { 'Content-Type': 'application/json', - 'Authorization': f'Bearer {request.app.state.config.TTS_OPENAI_API_KEY}', + 'Authorization': f'Bearer {api_key}', } if ENABLE_FORWARD_USER_INFO_HEADERS: headers = include_user_info_headers(headers, user) @@ -404,7 +374,7 @@ async def _tts_openai(request, payload, file_path, file_body_path, user): try: session = await get_session() r = await session.post( - url=f'{request.app.state.config.TTS_OPENAI_API_BASE_URL}/audio/speech', + url=f'{api_base_url}/audio/speech', json=payload, headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -429,8 +399,12 @@ async def _tts_openai(request, payload, file_path, file_body_path, user): async def _tts_elevenlabs(request, payload, file_path, file_body_path, user): """Generate speech via the ElevenLabs TTS API.""" - voice_id = payload.get('voice', '') - if voice_id not in await get_available_voices(request): + voice_id = (payload.get('voice') or '').strip() + if not voice_id: + raise HTTPException(status_code=400, detail='Invalid voice id') + + available_voices = await get_available_voices(request) + if available_voices and voice_id not in available_voices: raise HTTPException(status_code=400, detail='Invalid voice id') r = None @@ -440,13 +414,13 @@ async def _tts_elevenlabs(request, payload, file_path, file_body_path, user): f'{ELEVENLABS_API_BASE_URL}/v1/text-to-speech/{voice_id}', json={ 'text': payload['input'], - 'model_id': request.app.state.config.TTS_MODEL, + 'model_id': await Config.get('audio.tts.model'), 'voice_settings': {'stability': 0.5, 'similarity_boost': 0.5}, }, headers={ 'Accept': 'audio/mpeg', 'Content-Type': 'application/json', - 'xi-api-key': request.app.state.config.TTS_API_KEY, + 'xi-api-key': await Config.get('audio.tts.api_key'), }, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: @@ -460,15 +434,15 @@ async def _tts_elevenlabs(request, payload, file_path, file_body_path, user): async def _tts_azure(request, payload, file_path, file_body_path, user): """Generate speech via Azure Cognitive Services TTS.""" - az_region = request.app.state.config.TTS_AZURE_SPEECH_REGION or 'eastus' - az_base = request.app.state.config.TTS_AZURE_SPEECH_BASE_URL - language = payload.get('voice') or request.app.state.config.TTS_VOICE + az_region = await Config.get('audio.tts.azure.speech_region') or 'eastus' + az_base = await Config.get('audio.tts.azure.speech_base_url') + language = payload.get('voice') or await Config.get('audio.tts.voice') locale = '-'.join(language.split('-')[:2]) - output_format = request.app.state.config.TTS_AZURE_SPEECH_OUTPUT_FORMAT + output_format = await Config.get('audio.tts.azure.speech_output_format') ssml = ( - f'' - f'{html.escape(payload["input"])}' + f'' + f'{html.escape(payload["input"])}' f'' ) @@ -478,7 +452,7 @@ async def _tts_azure(request, payload, file_path, file_body_path, user): async with session.post( (az_base or f'https://{az_region}.tts.speech.microsoft.com') + '/cognitiveservices/v1', headers={ - 'Ocp-Apim-Subscription-Key': request.app.state.config.TTS_API_KEY, + 'Ocp-Apim-Subscription-Key': await Config.get('audio.tts.api_key'), 'Content-Type': 'application/ssml+xml', 'X-Microsoft-OutputFormat': output_format, }, @@ -498,10 +472,10 @@ async def _tts_transformers(request, payload, file_path, file_body_path, user): import soundfile as sf import torch - load_speech_pipeline(request) + await asyncio.to_thread(load_speech_pipeline, request) embeddings = request.app.state.speech_speaker_embeddings_dataset - model_name = request.app.state.config.TTS_MODEL + model_name = await Config.get('audio.tts.model') idx = 6799 try: @@ -529,8 +503,8 @@ async def _tts_transformers(request, payload, file_path, file_body_path, user): async def _tts_mistral(request, payload, file_path, file_body_path, user): """Generate speech via the Mistral TTS API.""" - api_key = request.app.state.config.TTS_MISTRAL_API_KEY - api_base_url = request.app.state.config.TTS_MISTRAL_API_BASE_URL or 'https://api.mistral.ai/v1' + api_key = await Config.get('audio.tts.mistral.api_key') + api_base_url = await Config.get('audio.tts.mistral.api_base_url') or 'https://api.mistral.ai/v1' if not api_key: raise HTTPException(status_code=400, detail='Mistral API key is required for Mistral TTS') @@ -542,7 +516,7 @@ async def _tts_mistral(request, payload, file_path, file_body_path, user): url=f'{api_base_url}/audio/speech', json={ 'input': payload.get('input', ''), # text to synthesize - 'model': request.app.state.config.TTS_MODEL or 'voxtral-mini-tts-2603', + 'model': await Config.get('audio.tts.model') or 'voxtral-mini-tts-2603', 'voice_id': payload.get('voice', ''), 'response_format': 'mp3', }, @@ -578,16 +552,14 @@ _TTS_ENGINES = { @router.post('/speech') async def speech(request: Request, user=Depends(get_verified_user)): - engine = request.app.state.config.TTS_ENGINE + engine = await Config.get('audio.tts.engine') if engine == '': raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND, ) - if user.role != 'admin' and not await has_permission( - user.id, 'chat.tts', request.app.state.config.USER_PERMISSIONS - ): + if user.role != 'admin' and not await has_permission(user.id, 'chat.tts', await Config.get('user.permissions')): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, @@ -595,7 +567,7 @@ async def speech(request: Request, user=Depends(get_verified_user)): body = await request.body() name = hashlib.sha256( - body + str(engine).encode('utf-8') + str(request.app.state.config.TTS_MODEL).encode('utf-8') + body + str(engine).encode('utf-8') + str(await Config.get('audio.tts.model')).encode('utf-8') ).hexdigest() file_path = SPEECH_CACHE_DIR.joinpath(f'{name}.mp3') @@ -603,6 +575,13 @@ async def speech(request: Request, user=Depends(get_verified_user)): # Return cached result if available if file_path.is_file(): + await publish_event( + request, + EVENTS.AUDIO_SPEECH_REQUESTED, + actor=user, + subject_id=name, + data={'engine': engine, 'cached': True}, + ) return FileResponse(file_path) try: @@ -615,12 +594,27 @@ async def speech(request: Request, user=Depends(get_verified_user)): if handler is None: raise HTTPException(status_code=400, detail=f'Unsupported TTS engine: {engine}') - return await handler(request, payload, file_path, file_body_path, user) + response = await handler(request, payload, file_path, file_body_path, user) + await publish_event( + request, + EVENTS.AUDIO_SPEECH_REQUESTED, + actor=user, + subject_id=name, + data={ + 'engine': engine, + 'model': payload.get('model'), + 'input_preview': str(payload.get('input', ''))[:300], + 'cached': False, + }, + ) + return response async def _transcribe_whisper(request, file_path, languages, file_dir, id): if request.app.state.faster_whisper_model is None: - request.app.state.faster_whisper_model = set_faster_whisper_model(request.app.state.config.WHISPER_MODEL) + request.app.state.faster_whisper_model = await asyncio.to_thread( + set_faster_whisper_model, await Config.get('audio.stt.whisper_model') + ) model = request.app.state.faster_whisper_model @@ -651,11 +645,13 @@ async def _transcribe_openai(request, file_path, filename, languages, file_dir, try: session = await get_session() for language in languages: - payload = {'model': request.app.state.config.STT_MODEL} + payload = {'model': await Config.get('audio.stt.model')} if language: payload['language'] = language + api_key = await Config.get('audio.stt.openai.api_key') + api_base_url = await Config.get('audio.stt.openai.api_base_url') - headers = {'Authorization': f'Bearer {request.app.state.config.STT_OPENAI_API_KEY}'} + headers = {'Authorization': f'Bearer {api_key}'} if user and ENABLE_FORWARD_USER_INFO_HEADERS: headers = include_user_info_headers(headers, user) @@ -665,7 +661,7 @@ async def _transcribe_openai(request, file_path, filename, languages, file_dir, form_data.add_field('file', open(file_path, 'rb'), filename=filename) r = await session.post( - url=f'{request.app.state.config.STT_OPENAI_API_BASE_URL}/audio/transcriptions', + url=f'{api_base_url}/audio/transcriptions', headers=headers, data=form_data, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -699,8 +695,8 @@ async def _transcribe_deepgram(request, file_path, languages, file_dir, id): async with aiofiles.open(file_path, 'rb') as f: audio_bytes = await f.read() - api_key = request.app.state.config.DEEPGRAM_API_KEY - stt_model = request.app.state.config.STT_MODEL + api_key = await Config.get('audio.stt.deepgram.api_key') + stt_model = await Config.get('audio.stt.model') r = None try: @@ -767,11 +763,11 @@ async def _transcribe_azure(request, file_path, filename, file_dir, id): detail=f'File size ({audio_size // (1024 * 1024)}MB) exceeds Azure limit of {AZURE_MAX_FILE_SIZE_MB}MB', ) - api_key = request.app.state.config.AUDIO_STT_AZURE_API_KEY - region = request.app.state.config.AUDIO_STT_AZURE_REGION or 'eastus' - locale_str = request.app.state.config.AUDIO_STT_AZURE_LOCALES - base_url = request.app.state.config.AUDIO_STT_AZURE_BASE_URL - max_speakers = request.app.state.config.AUDIO_STT_AZURE_MAX_SPEAKERS or 3 + api_key = await Config.get('audio.stt.azure.api_key') + region = await Config.get('audio.stt.azure.region') or 'eastus' + locale_str = await Config.get('audio.stt.azure.locales') + base_url = await Config.get('audio.stt.azure.base_url') + max_speakers = await Config.get('audio.stt.azure.max_speakers') or 3 # Default to a broad set of locales when none are configured if len(locale_str) < 2: @@ -881,16 +877,16 @@ async def transcription_handler(request, file_path, metadata, user=None): None, # Always fallback to None in case transcription fails ] - if request.app.state.config.STT_ENGINE == '': + if await Config.get('audio.stt.engine') == '': return await _transcribe_whisper(request, file_path, languages, file_dir, id) - elif request.app.state.config.STT_ENGINE == 'openai': + elif await Config.get('audio.stt.engine') == 'openai': return await _transcribe_openai(request, file_path, filename, languages, file_dir, id, user) - elif request.app.state.config.STT_ENGINE == 'deepgram': + elif await Config.get('audio.stt.engine') == 'deepgram': return await _transcribe_deepgram(request, file_path, languages, file_dir, id) - elif request.app.state.config.STT_ENGINE == 'azure': + elif await Config.get('audio.stt.engine') == 'azure': return await _transcribe_azure(request, file_path, filename, file_dir, id) - elif request.app.state.config.STT_ENGINE == 'mistral': + elif await Config.get('audio.stt.engine') == 'mistral': return await _transcribe_mistral(request, file_path, filename, metadata, file_dir, id) @@ -903,16 +899,16 @@ async def _transcribe_mistral(request, file_path, filename, metadata, file_dir, if file_size > MAX_FILE_SIZE: raise HTTPException(status_code=400, detail=f'File size exceeds limit of {MAX_FILE_SIZE_MB}MB') - api_key = request.app.state.config.AUDIO_STT_MISTRAL_API_KEY - api_base_url = request.app.state.config.AUDIO_STT_MISTRAL_API_BASE_URL or 'https://api.mistral.ai/v1' - use_chat_completions = request.app.state.config.AUDIO_STT_MISTRAL_USE_CHAT_COMPLETIONS + api_key = await Config.get('audio.stt.mistral.api_key') + api_base_url = await Config.get('audio.stt.mistral.api_base_url') or 'https://api.mistral.ai/v1' + use_chat_completions = await Config.get('audio.stt.mistral.use_chat_completions') if not api_key: raise HTTPException(status_code=400, detail='Mistral API key is required for Mistral STT') r = None try: - model = request.app.state.config.STT_MODEL or 'voxtral-mini-latest' + model = await Config.get('audio.stt.model') or 'voxtral-mini-latest' log.info( f'Mistral STT - model: {model}, method: {"chat_completions" if use_chat_completions else "transcriptions"}' ) @@ -1056,7 +1052,7 @@ async def transcribe(request: Request, file_path: str, metadata: Optional[dict] log.exception(e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error processing audio file'), ) results = [] @@ -1153,15 +1149,13 @@ async def transcription( language: Optional[str] = Form(None), user=Depends(get_verified_user), ): - if user.role != 'admin' and not await has_permission( - user.id, 'chat.stt', request.app.state.config.USER_PERMISSIONS - ): + if user.role != 'admin' and not await has_permission(user.id, 'chat.stt', await Config.get('user.permissions')): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) log.info(f'file.content_type: {file.content_type}') - stt_supported_content_types = getattr(request.app.state.config, 'STT_SUPPORTED_CONTENT_TYPES', []) + stt_supported_content_types = await Config.get('audio.stt.supported_content_types', []) if not strict_match_mime_type(stt_supported_content_types, file.content_type): raise HTTPException( @@ -1173,7 +1167,7 @@ async def transcription( safe_name = os.path.basename(file.filename) if file.filename else '' ext = safe_name.rsplit('.', 1)[-1].lower() if '.' in safe_name else '' - allowed_extensions = getattr(request.app.state.config, 'STT_ALLOWED_EXTENSIONS', []) + allowed_extensions = await Config.get('audio.stt.allowed_extensions', []) if allowed_extensions and ext not in allowed_extensions: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -1193,8 +1187,12 @@ async def transcription( if not os.path.realpath(file_path).startswith(os.path.realpath(file_dir)): raise ValueError('Invalid file path detected') - with open(file_path, 'wb') as f: - f.write(contents) + def _write_upload(): + with open(file_path, 'wb') as f: + f.write(contents) + + # Audio uploads can be large; write to disk off the event loop. + await asyncio.to_thread(_write_upload) try: metadata = None @@ -1204,6 +1202,17 @@ async def transcription( result = await transcribe(request, file_path, metadata, user) + await publish_event( + request, + EVENTS.AUDIO_TRANSCRIPTION_REQUESTED, + actor=user, + subject_id=str(id), + data={ + 'filename': safe_name, + 'content_type': file.content_type, + 'language': language, + }, + ) return { **result, 'filename': os.path.basename(file_path), @@ -1233,11 +1242,11 @@ async def transcription( async def get_available_models(request: Request) -> list[dict]: """Return the list of available TTS models for the configured engine.""" available_models = [] - engine = request.app.state.config.TTS_ENGINE + engine = await Config.get('audio.tts.engine') _timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST) if engine == 'openai': - base_url = request.app.state.config.TTS_OPENAI_API_BASE_URL + base_url = await Config.get('audio.tts.openai.api_base_url') if not base_url.startswith('https://api.openai.com'): session = await get_session() try: @@ -1272,7 +1281,7 @@ async def get_available_models(request: Request) -> list[dict]: async with session.get( f'{ELEVENLABS_API_BASE_URL}/v1/models', headers={ - 'xi-api-key': request.app.state.config.TTS_API_KEY, + 'xi-api-key': await Config.get('audio.tts.api_key'), 'Content-Type': 'application/json', }, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -1307,11 +1316,11 @@ _OPENAI_DEFAULT_VOICES = { async def get_available_voices(request) -> dict: """Return ``{voice_id: voice_name}`` for the configured TTS engine.""" - engine = request.app.state.config.TTS_ENGINE + engine = await Config.get('audio.tts.engine') _timeout = aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT_MODEL_LIST) if engine == 'openai': - base_url = request.app.state.config.TTS_OPENAI_API_BASE_URL + base_url = await Config.get('audio.tts.openai.api_base_url') if not base_url.startswith('https://api.openai.com'): try: session = await get_session() @@ -1334,7 +1343,7 @@ async def get_available_voices(request) -> dict: async with session.get( f'{ELEVENLABS_API_BASE_URL}/v1/voices', headers={ - 'xi-api-key': request.app.state.config.TTS_API_KEY, + 'xi-api-key': await Config.get('audio.tts.api_key'), 'Content-Type': 'application/json', }, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -1344,19 +1353,19 @@ async def get_available_voices(request) -> dict: voices_data = await resp.json() return {v['voice_id']: v['name'] for v in voices_data.get('voices', [])} except Exception as e: - log.error(f'Error fetching ElevenLabs voices: {e}') + log.warning(f'Error fetching ElevenLabs voices: {e}') return {} if engine == 'azure': try: - region = request.app.state.config.TTS_AZURE_SPEECH_REGION - base_url = request.app.state.config.TTS_AZURE_SPEECH_BASE_URL + region = await Config.get('audio.tts.azure.speech_region') + base_url = await Config.get('audio.tts.azure.speech_base_url') url = (base_url or f'https://{region}.tts.speech.microsoft.com') + '/cognitiveservices/voices/list' session = await get_session() async with session.get( url, - headers={'Ocp-Apim-Subscription-Key': request.app.state.config.TTS_API_KEY}, + headers={'Ocp-Apim-Subscription-Key': await Config.get('audio.tts.api_key')}, ssl=AIOHTTP_CLIENT_SESSION_SSL, timeout=_timeout, ) as resp: @@ -1368,8 +1377,8 @@ async def get_available_voices(request) -> dict: return {} if engine == 'mistral': - api_key = request.app.state.config.TTS_MISTRAL_API_KEY - api_base_url = request.app.state.config.TTS_MISTRAL_API_BASE_URL or 'https://api.mistral.ai/v1' + api_key = await Config.get('audio.tts.mistral.api_key') + api_base_url = await Config.get('audio.tts.mistral.api_base_url') or 'https://api.mistral.ai/v1' if api_key: try: session = await get_session() diff --git a/backend/open_webui/routers/auths.py b/backend/open_webui/routers/auths.py index 434a6349de..9f71ecafb8 100644 --- a/backend/open_webui/routers/auths.py +++ b/backend/open_webui/routers/auths.py @@ -8,23 +8,18 @@ import time import urllib import uuid from ssl import CERT_NONE, CERT_REQUIRED, PROTOCOL_TLS -from typing import List, Optional from aiohttp import ClientSession from fastapi import APIRouter, Depends, HTTPException, Request, status -from fastapi.responses import JSONResponse, RedirectResponse, Response +from fastapi.responses import JSONResponse, Response from ldap3 import NONE, Connection, Server, Tls from ldap3.utils.conv import escape_filter_chars from open_webui.config import ( - ENABLE_LDAP, - ENABLE_OAUTH_SIGNUP, ENABLE_PASSWORD_AUTH, - OAUTH_MERGE_ACCOUNTS_BY_EMAIL, OAUTH_PROVIDERS, - OPENID_END_SESSION_ENDPOINT, - OPENID_PROVIDER_URL, ) -from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES +from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ( AIOHTTP_CLIENT_SESSION_SSL, ENABLE_INITIAL_ADMIN_SIGNUP, @@ -50,6 +45,7 @@ from open_webui.models.auths import ( Token, UpdatePasswordForm, ) +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.users import ( @@ -75,10 +71,8 @@ from open_webui.utils.auth import ( ) from open_webui.utils.groups import apply_default_group_assignment from open_webui.utils.misc import parse_duration, validate_email_format -from open_webui.utils.oauth import auth_manager_config from open_webui.utils.rate_limit import RateLimiter from open_webui.utils.redis import get_redis_client -from open_webui.utils.webhook import post_webhook from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession @@ -90,9 +84,68 @@ log = logging.getLogger(__name__) # who exceed their allotted rate against this gate. signin_rate_limiter = RateLimiter(redis_client=get_redis_client(), limit=5 * 3, window=60 * 3) +ADMIN_CONFIG_KEYS = { + 'SHOW_ADMIN_DETAILS': 'auth.admin.show', + 'ADMIN_EMAIL': 'auth.admin.email', + 'WEBUI_URL': 'webui.url', + 'ENABLE_SIGNUP': 'ui.enable_signup', + 'ENABLE_API_KEYS': 'auth.enable_api_keys', + 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS': 'auth.api_key.endpoint_restrictions', + 'API_KEYS_ALLOWED_ENDPOINTS': 'auth.api_key.allowed_endpoints', + 'DEFAULT_USER_ROLE': 'ui.default_user_role', + 'DEFAULT_GROUP_ID': 'ui.default_group_id', + 'JWT_EXPIRES_IN': 'auth.jwt_expiry', + 'ENABLE_COMMUNITY_SHARING': 'ui.enable_community_sharing', + 'ENABLE_MESSAGE_RATING': 'ui.enable_message_rating', + 'ENABLE_FOLDERS': 'folders.enable', + 'FOLDER_MAX_FILE_COUNT': 'folders.max_file_count', + 'AUTOMATION_MAX_COUNT': 'automations.max_count', + 'AUTOMATION_MIN_INTERVAL': 'automations.min_interval', + 'ENABLE_AUTOMATIONS': 'automations.enable', + 'ENABLE_CHANNELS': 'channels.enable', + 'ENABLE_CALENDAR': 'calendar.enable', + 'ENABLE_MEMORIES': 'memories.enable', + 'ENABLE_NOTES': 'notes.enable', + 'ENABLE_USER_WEBHOOKS': 'ui.enable_user_webhooks', + 'ENABLE_USER_STATUS': 'users.enable_status', + 'PENDING_USER_OVERLAY_TITLE': 'ui.pending_user_overlay_title', + 'PENDING_USER_OVERLAY_CONTENT': 'ui.pending_user_overlay_content', + 'RESPONSE_WATERMARK': 'ui.watermark', +} + +LDAP_SERVER_CONFIG_KEYS = { + 'label': 'ldap.server.label', + 'host': 'ldap.server.host', + 'port': 'ldap.server.port', + 'attribute_for_mail': 'ldap.server.attribute_for_mail', + 'attribute_for_username': 'ldap.server.attribute_for_username', + 'app_dn': 'ldap.server.app_dn', + 'app_dn_password': 'ldap.server.app_password', + 'search_base': 'ldap.server.users_dn', + 'search_filters': 'ldap.server.search_filter', + 'use_tls': 'ldap.server.use_tls', + 'certificate_path': 'ldap.server.ca_cert_file', + 'validate_cert': 'ldap.server.validate_cert', + 'ciphers': 'ldap.server.ciphers', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +def config_updates(data: dict, key_map: dict[str, str]) -> dict: + return {key_map[field]: value for field, value in data.items() if field in key_map} + async def create_session_response( - request: Request, user, db, response: Response = None, set_cookie: bool = False + request: Request, + user, + db, + response: Response = None, + set_cookie: bool = False, + source: str = 'api', ) -> dict: """ Create JWT token and build session response for a user. @@ -105,7 +158,7 @@ async def create_session_response( response: FastAPI response object (required if set_cookie is True) set_cookie: Whether to set the auth cookie on the response """ - expires_delta = parse_duration(request.app.state.config.JWT_EXPIRES_IN) + expires_delta = parse_duration(await Config.get('auth.jwt_expiry')) expires_at = None if expires_delta: expires_at = int(time.time()) + int(expires_delta.total_seconds()) @@ -128,7 +181,16 @@ async def create_session_response( **({'max_age': max_age} if max_age is not None else {}), ) - user_permissions = await get_permissions(user.id, request.app.state.config.USER_PERMISSIONS, db=db) + user_permissions = await get_permissions(user.id, await Config.get('user.permissions'), db=db) + await publish_event( + request, + EVENTS.AUTH_LOGIN, + actor=user, + subject_id=user.id, + subject_type='user', + source=source, + data={'auth_method': source}, + ) return { 'token': token, @@ -201,7 +263,7 @@ async def get_session_user( **({'max_age': max_age} if max_age is not None else {}), ) - user_permissions = await get_permissions(user.id, request.app.state.config.USER_PERMISSIONS, db=db) + user_permissions = await get_permissions(user.id, await Config.get('user.permissions'), db=db) response_data = { 'token': token, @@ -231,6 +293,7 @@ async def get_session_user( @router.post('/update/profile', response_model=UserProfileImageResponse) async def update_profile( + request: Request, form_data: UpdateProfileForm, session_user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), @@ -242,6 +305,13 @@ async def update_profile( db=db, ) if user: + await publish_event( + request, + EVENTS.USER_PROFILE_UPDATED, + actor=session_user, + subject_id=session_user.id, + data={'updated_fields': list(form_data.model_dump().keys())}, + ) return user else: raise HTTPException(400, detail=ERROR_MESSAGES.DEFAULT()) @@ -260,6 +330,7 @@ class UpdateTimezoneForm(BaseModel): @router.post('/update/timezone') async def update_timezone( + request: Request, form_data: UpdateTimezoneForm, session_user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session), @@ -270,6 +341,13 @@ async def update_timezone( {'timezone': form_data.timezone}, db=db, ) + await publish_event( + request, + EVENTS.USER_UPDATED, + actor=session_user, + subject_id=session_user.id, + data={'updated_fields': ['timezone']}, + ) return {'status': True} else: raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) @@ -282,6 +360,7 @@ async def update_timezone( @router.post('/update/password', response_model=bool) async def update_password( + request: Request, form_data: UpdatePasswordForm, session_user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session), @@ -301,8 +380,17 @@ async def update_password( validate_password(form_data.new_password) except Exception as e: raise HTTPException(400, detail=str(e)) - hashed = get_password_hash(form_data.new_password) - return await Auths.update_user_password_by_id(user.id, hashed, db=db) + hashed = await get_password_hash(form_data.new_password) + success = await Auths.update_user_password_by_id(user.id, hashed, db=db) + if success: + await publish_event( + request, + EVENTS.AUTH_PASSWORD_CHANGED, + actor=user, + subject_id=user.id, + subject_type='user', + ) + return success else: raise HTTPException(400, detail=ERROR_MESSAGES.INCORRECT_PASSWORD) else: @@ -320,7 +408,7 @@ async def ldap_auth( db: AsyncSession = Depends(get_async_session), ): # Security checks FIRST - before loading any config - if not request.app.state.config.ENABLE_LDAP: + if not await Config.get('ldap.enable'): raise HTTPException(400, detail='LDAP authentication is not enabled') if not ENABLE_PASSWORD_AUTH: @@ -338,19 +426,19 @@ async def ldap_auth( raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) # NOW load LDAP config variables - LDAP_SERVER_LABEL = request.app.state.config.LDAP_SERVER_LABEL - LDAP_SERVER_HOST = request.app.state.config.LDAP_SERVER_HOST - LDAP_SERVER_PORT = request.app.state.config.LDAP_SERVER_PORT - LDAP_ATTRIBUTE_FOR_MAIL = request.app.state.config.LDAP_ATTRIBUTE_FOR_MAIL - LDAP_ATTRIBUTE_FOR_USERNAME = request.app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME - LDAP_SEARCH_BASE = request.app.state.config.LDAP_SEARCH_BASE - LDAP_SEARCH_FILTERS = request.app.state.config.LDAP_SEARCH_FILTERS - LDAP_APP_DN = request.app.state.config.LDAP_APP_DN - LDAP_APP_PASSWORD = request.app.state.config.LDAP_APP_PASSWORD - LDAP_USE_TLS = request.app.state.config.LDAP_USE_TLS - LDAP_CA_CERT_FILE = request.app.state.config.LDAP_CA_CERT_FILE - LDAP_VALIDATE_CERT = CERT_REQUIRED if request.app.state.config.LDAP_VALIDATE_CERT else CERT_NONE - LDAP_CIPHERS = request.app.state.config.LDAP_CIPHERS if request.app.state.config.LDAP_CIPHERS else 'ALL' + LDAP_SERVER_LABEL = await Config.get('ldap.server.label') + LDAP_SERVER_HOST = await Config.get('ldap.server.host') + LDAP_SERVER_PORT = await Config.get('ldap.server.port') + LDAP_ATTRIBUTE_FOR_MAIL = await Config.get('ldap.server.attribute_for_mail') + LDAP_ATTRIBUTE_FOR_USERNAME = await Config.get('ldap.server.attribute_for_username') + LDAP_SEARCH_BASE = await Config.get('ldap.server.users_dn') + LDAP_SEARCH_FILTERS = await Config.get('ldap.server.search_filter') + LDAP_APP_DN = await Config.get('ldap.server.app_dn') + LDAP_APP_PASSWORD = await Config.get('ldap.server.app_password') + LDAP_USE_TLS = await Config.get('ldap.server.use_tls') + LDAP_CA_CERT_FILE = await Config.get('ldap.server.ca_cert_file') + LDAP_VALIDATE_CERT = CERT_REQUIRED if await Config.get('ldap.server.validate_cert') else CERT_NONE + LDAP_CIPHERS = await Config.get('ldap.server.ciphers') if await Config.get('ldap.server.ciphers') else 'ALL' try: tls = Tls( @@ -381,9 +469,9 @@ async def ldap_auth( if not await asyncio.to_thread(connection_app.bind): raise HTTPException(400, detail='Application account bind failed') - ENABLE_LDAP_GROUP_MANAGEMENT = request.app.state.config.ENABLE_LDAP_GROUP_MANAGEMENT - ENABLE_LDAP_GROUP_CREATION = request.app.state.config.ENABLE_LDAP_GROUP_CREATION - LDAP_ATTRIBUTE_FOR_GROUPS = request.app.state.config.LDAP_ATTRIBUTE_FOR_GROUPS + ENABLE_LDAP_GROUP_MANAGEMENT = await Config.get('ldap.group.enable_management') + ENABLE_LDAP_GROUP_CREATION = await Config.get('ldap.group.enable_creation') + LDAP_ATTRIBUTE_FOR_GROUPS = await Config.get('ldap.server.attribute_for_groups') search_attributes = [ f'{LDAP_ATTRIBUTE_FOR_USERNAME}', @@ -500,7 +588,7 @@ async def ldap_auth( email=email, password=str(uuid.uuid4()), name=cn, - role=request.app.state.config.DEFAULT_USER_ROLE, + role=await Config.get('ui.default_user_role'), db=db, ) @@ -514,22 +602,19 @@ async def ldap_auth( user = await Users.get_user_by_id(user.id, db=db) await apply_default_group_assignment( - request.app.state.config.DEFAULT_GROUP_ID, + await Config.get('ui.default_group_id'), user.id, db=db, ) - if request.app.state.config.WEBHOOK_URL: - await post_webhook( - request.app.state.WEBUI_NAME, - request.app.state.config.WEBHOOK_URL, - WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - { - 'action': 'signup', - 'message': WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - 'user': user.model_dump_json(exclude_none=True), - }, - ) + await publish_event( + request, + EVENTS.USER_CREATED, + actor=user, + subject_id=user.id, + source='ldap', + data={'role': user.role}, + ) except HTTPException: raise @@ -549,7 +634,7 @@ async def ldap_auth( except Exception as e: log.error(f'Failed to sync groups for user {user.id}: {e}') - return await create_session_response(request, user, db, response, set_cookie=True) + return await create_session_response(request, user, db, response, set_cookie=True, source='ldap') else: raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) else: @@ -577,7 +662,10 @@ async def signin( detail=ERROR_MESSAGES.ACTION_PROHIBITED, ) + auth_source = 'password' + if WEBUI_AUTH_TRUSTED_EMAIL_HEADER: + auth_source = 'trusted_header' if WEBUI_AUTH_TRUSTED_EMAIL_HEADER not in request.headers: raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.INVALID_TRUSTED_HEADER) @@ -598,6 +686,7 @@ async def signin( str(uuid.uuid4()), name, db=db, + source='trusted_header', ) user = await Auths.authenticate_user_by_email(email, db=db) @@ -618,6 +707,7 @@ async def signin( log.warning(f'Ignoring invalid trusted role header value: {trusted_role}') elif WEBUI_AUTH == False: + auth_source = 'system' admin_email = 'admin@localhost' admin_password = 'admin' @@ -637,6 +727,7 @@ async def signin( admin_password, 'User', db=db, + source='system', ) user = await Auths.authenticate_user( @@ -651,15 +742,6 @@ async def signin( detail=ERROR_MESSAGES.RATE_LIMIT_EXCEEDED, ) - password_bytes = form_data.password.encode('utf-8') - if len(password_bytes) > 72: - # TODO: Implement other hashing algorithms that support longer passwords - log.info('Password too long, truncating to 72 bytes for bcrypt') - password_bytes = password_bytes[:72] - - # decode safely — ignore incomplete UTF-8 sequences - form_data.password = password_bytes.decode('utf-8', errors='ignore') - user = await Auths.authenticate_user( form_data.email.lower(), lambda pw: verify_password(form_data.password, pw), @@ -667,7 +749,7 @@ async def signin( ) if user: - return await create_session_response(request, user, db, response, set_cookie=True) + return await create_session_response(request, user, db, response, set_cookie=True, source=auth_source) else: raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) @@ -685,6 +767,7 @@ async def signup_handler( profile_image_url: str = '/user.png', *, db: AsyncSession, + source: str = 'api', ) -> UserModel: """ Core user-creation logic shared by the signup endpoint and @@ -696,14 +779,14 @@ async def signup_handler( # Insert with default role first to avoid TOCTOU race on first signup. # If has_users() is checked before insert, concurrent requests during # first-user registration can all see an empty table and each get admin. - hashed = get_password_hash(password) + hashed = await get_password_hash(password) user = await Auths.insert_new_auth( email=email.lower(), password=hashed, name=name, profile_image_url=profile_image_url, - role=request.app.state.config.DEFAULT_USER_ROLE, + role=await Config.get('ui.default_user_role'), db=db, ) if not user: @@ -714,26 +797,23 @@ async def signup_handler( if await Users.get_num_users(db=db) == 1: await Users.update_user_role_by_id(user.id, 'admin', db=db) user = await Users.get_user_by_id(user.id, db=db) - request.app.state.config.ENABLE_SIGNUP = False - - if request.app.state.config.WEBHOOK_URL: - await post_webhook( - request.app.state.WEBUI_NAME, - request.app.state.config.WEBHOOK_URL, - WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - { - 'action': 'signup', - 'message': WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - 'user': user.model_dump_json(exclude_none=True), - }, - ) + await Config.upsert({'ui.enable_signup': False}) await apply_default_group_assignment( - request.app.state.config.DEFAULT_GROUP_ID, + await Config.get('ui.default_group_id'), user.id, db=db, ) + await publish_event( + request, + EVENTS.USER_CREATED, + actor=user, + subject_id=user.id, + source=source, + data={'role': user.role}, + ) + return user @@ -748,10 +828,10 @@ async def signup( if WEBUI_AUTH: if has_users: - if not request.app.state.config.ENABLE_SIGNUP or not request.app.state.config.ENABLE_LOGIN_FORM: + if not await Config.get('ui.enable_signup') or not await Config.get('ui.enable_login_form'): raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED) # Don't gate the first admin on ENABLE_SIGNUP: it auto-disables and can persist stale across a DB reset. - elif not request.app.state.config.ENABLE_LOGIN_FORM and not ENABLE_INITIAL_ADMIN_SIGNUP: + elif not await Config.get('ui.enable_login_form') and not ENABLE_INITIAL_ADMIN_SIGNUP: raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED) else: if has_users: @@ -777,6 +857,14 @@ async def signup( form_data.profile_image_url, db=db, ) + await publish_event( + request, + EVENTS.AUTH_SIGNUP, + actor=user, + subject_id=user.id, + subject_type='user', + data={'email': user.email}, + ) return await create_session_response(request, user, db, response, set_cookie=True) except HTTPException: raise @@ -798,7 +886,18 @@ async def signout(request: Request, response: Response, db: AsyncSession = Depen token = request.cookies.get('token') if token: + actor = None + data = decode_token(token) + if data and data.get('id'): + actor = await Users.get_user_by_id(data['id'], db=db) await invalidate_token(request, token) + await publish_event( + request, + EVENTS.AUTH_LOGOUT, + actor=actor, + subject_id=actor.id if actor else None, + subject_type='user' if actor else None, + ) response.delete_cookie('token') response.delete_cookie('oui-session') @@ -812,19 +911,21 @@ async def signout(request: Request, response: Response, db: AsyncSession = Depen # If a custom end_session_endpoint is configured (e.g. AWS Cognito), redirect # there directly instead of attempting OIDC discovery. - if OPENID_END_SESSION_ENDPOINT.value: + openid_end_session_endpoint = await Config.get('oauth.end_session_endpoint') + if openid_end_session_endpoint: return JSONResponse( status_code=200, content={ 'status': True, - 'redirect_url': OPENID_END_SESSION_ENDPOINT.value, + 'redirect_url': openid_end_session_endpoint, }, headers=response.headers, ) + openid_provider_url = await Config.get('oauth.provider_url') oauth_server_metadata_url = ( request.app.state.oauth_manager.get_server_metadata_url(session.provider) if session else None - ) or OPENID_PROVIDER_URL.value + ) or openid_provider_url if session and oauth_server_metadata_url: oauth_id_token = session.token.get('id_token') @@ -880,6 +981,7 @@ async def signout(request: Request, response: Response, db: AsyncSession = Depen @router.delete('/oauth/sessions/{provider:path}', response_model=bool) async def delete_oauth_session_by_provider( + request: Request, provider: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), @@ -895,6 +997,14 @@ async def delete_oauth_session_by_provider( status_code=status.HTTP_404_NOT_FOUND, detail='No OAuth session found for this provider', ) + await publish_event( + request, + EVENTS.AUTH_OAUTH_SESSION_DELETED, + actor=user, + subject_id=user.id, + subject_type='user', + data={'provider': provider}, + ) return True @@ -910,6 +1020,7 @@ async def add_user( user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session), ): + admin_user = user if not validate_email_format(form_data.email.lower()): raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.INVALID_EMAIL_FORMAT) @@ -922,7 +1033,7 @@ async def add_user( except Exception as e: raise HTTPException(400, detail=str(e)) - hashed = get_password_hash(form_data.password) + hashed = await get_password_hash(form_data.password) user = await Auths.insert_new_auth( form_data.email.lower(), hashed, @@ -934,12 +1045,20 @@ async def add_user( if user: await apply_default_group_assignment( - request.app.state.config.DEFAULT_GROUP_ID, + await Config.get('ui.default_group_id'), user.id, db=db, ) + await publish_event( + request, + EVENTS.USER_CREATED, + actor=admin_user, + subject_id=user.id, + source='admin', + data={'role': user.role}, + ) - expires_delta = parse_duration(request.app.state.config.JWT_EXPIRES_IN) + expires_delta = parse_duration(await Config.get('auth.jwt_expiry')) token = create_token(data={'id': user.id}, expires_delta=expires_delta) return { 'token': token, @@ -968,8 +1087,8 @@ async def add_user( async def get_admin_details( request: Request, user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session) ): - if request.app.state.config.SHOW_ADMIN_DETAILS: - admin_email = request.app.state.config.ADMIN_EMAIL + if await Config.get('auth.admin.show'): + admin_email = await Config.get('auth.admin.email') admin_name = None log.info(f'Admin details - Email: {admin_email}, Name: {admin_name}') @@ -999,34 +1118,7 @@ async def get_admin_details( @router.get('/admin/config') async def get_admin_config(request: Request, user=Depends(get_admin_user)): - return { - 'SHOW_ADMIN_DETAILS': request.app.state.config.SHOW_ADMIN_DETAILS, - 'ADMIN_EMAIL': request.app.state.config.ADMIN_EMAIL, - 'WEBUI_URL': request.app.state.config.WEBUI_URL, - 'ENABLE_SIGNUP': request.app.state.config.ENABLE_SIGNUP, - 'ENABLE_API_KEYS': request.app.state.config.ENABLE_API_KEYS, - 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS': request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, - 'API_KEYS_ALLOWED_ENDPOINTS': request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS, - 'DEFAULT_USER_ROLE': request.app.state.config.DEFAULT_USER_ROLE, - 'DEFAULT_GROUP_ID': request.app.state.config.DEFAULT_GROUP_ID, - 'JWT_EXPIRES_IN': request.app.state.config.JWT_EXPIRES_IN, - 'ENABLE_COMMUNITY_SHARING': request.app.state.config.ENABLE_COMMUNITY_SHARING, - 'ENABLE_MESSAGE_RATING': request.app.state.config.ENABLE_MESSAGE_RATING, - 'ENABLE_FOLDERS': request.app.state.config.ENABLE_FOLDERS, - 'FOLDER_MAX_FILE_COUNT': request.app.state.config.FOLDER_MAX_FILE_COUNT, - 'AUTOMATION_MAX_COUNT': request.app.state.config.AUTOMATION_MAX_COUNT, - 'AUTOMATION_MIN_INTERVAL': request.app.state.config.AUTOMATION_MIN_INTERVAL, - 'ENABLE_AUTOMATIONS': request.app.state.config.ENABLE_AUTOMATIONS, - 'ENABLE_CHANNELS': request.app.state.config.ENABLE_CHANNELS, - 'ENABLE_CALENDAR': request.app.state.config.ENABLE_CALENDAR, - 'ENABLE_MEMORIES': request.app.state.config.ENABLE_MEMORIES, - 'ENABLE_NOTES': request.app.state.config.ENABLE_NOTES, - 'ENABLE_USER_WEBHOOKS': request.app.state.config.ENABLE_USER_WEBHOOKS, - 'ENABLE_USER_STATUS': request.app.state.config.ENABLE_USER_STATUS, - 'PENDING_USER_OVERLAY_TITLE': request.app.state.config.PENDING_USER_OVERLAY_TITLE, - 'PENDING_USER_OVERLAY_CONTENT': request.app.state.config.PENDING_USER_OVERLAY_CONTENT, - 'RESPONSE_WATERMARK': request.app.state.config.RESPONSE_WATERMARK, - } + return await get_config_values(ADMIN_CONFIG_KEYS) class AdminConfig(BaseModel): @@ -1060,81 +1152,24 @@ class AdminConfig(BaseModel): @router.post('/admin/config') async def update_admin_config(request: Request, form_data: AdminConfig, user=Depends(get_admin_user)): - request.app.state.config.SHOW_ADMIN_DETAILS = form_data.SHOW_ADMIN_DETAILS - request.app.state.config.ADMIN_EMAIL = form_data.ADMIN_EMAIL - request.app.state.config.WEBUI_URL = form_data.WEBUI_URL - request.app.state.config.ENABLE_SIGNUP = form_data.ENABLE_SIGNUP - - request.app.state.config.ENABLE_API_KEYS = form_data.ENABLE_API_KEYS - request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS = form_data.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS - request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS = form_data.API_KEYS_ALLOWED_ENDPOINTS - - request.app.state.config.ENABLE_FOLDERS = form_data.ENABLE_FOLDERS - request.app.state.config.FOLDER_MAX_FILE_COUNT = ( - int(form_data.FOLDER_MAX_FILE_COUNT) if form_data.FOLDER_MAX_FILE_COUNT else '' - ) - request.app.state.config.AUTOMATION_MAX_COUNT = ( - int(form_data.AUTOMATION_MAX_COUNT) if form_data.AUTOMATION_MAX_COUNT else '' - ) - request.app.state.config.AUTOMATION_MIN_INTERVAL = ( + updates = config_updates(form_data.model_dump(), ADMIN_CONFIG_KEYS) + updates['folders.max_file_count'] = int(form_data.FOLDER_MAX_FILE_COUNT) if form_data.FOLDER_MAX_FILE_COUNT else '' + updates['automations.max_count'] = int(form_data.AUTOMATION_MAX_COUNT) if form_data.AUTOMATION_MAX_COUNT else '' + updates['automations.min_interval'] = ( int(form_data.AUTOMATION_MIN_INTERVAL) if form_data.AUTOMATION_MIN_INTERVAL else '' ) - request.app.state.config.ENABLE_AUTOMATIONS = form_data.ENABLE_AUTOMATIONS - request.app.state.config.ENABLE_CHANNELS = form_data.ENABLE_CHANNELS - request.app.state.config.ENABLE_CALENDAR = form_data.ENABLE_CALENDAR - request.app.state.config.ENABLE_MEMORIES = form_data.ENABLE_MEMORIES - request.app.state.config.ENABLE_NOTES = form_data.ENABLE_NOTES - if form_data.DEFAULT_USER_ROLE in ['pending', 'user', 'admin']: - request.app.state.config.DEFAULT_USER_ROLE = form_data.DEFAULT_USER_ROLE - - request.app.state.config.DEFAULT_GROUP_ID = form_data.DEFAULT_GROUP_ID + if form_data.DEFAULT_USER_ROLE not in ['pending', 'user', 'admin']: + updates.pop('ui.default_user_role', None) pattern = r'^(-1|0|(-?\d+(\.\d+)?)(ms|s|m|h|d|w))$' # Check if the input string matches the pattern - if re.match(pattern, form_data.JWT_EXPIRES_IN): - request.app.state.config.JWT_EXPIRES_IN = form_data.JWT_EXPIRES_IN + if not re.match(pattern, form_data.JWT_EXPIRES_IN): + updates.pop('auth.jwt_expiry', None) - request.app.state.config.ENABLE_COMMUNITY_SHARING = form_data.ENABLE_COMMUNITY_SHARING - request.app.state.config.ENABLE_MESSAGE_RATING = form_data.ENABLE_MESSAGE_RATING - - request.app.state.config.ENABLE_USER_WEBHOOKS = form_data.ENABLE_USER_WEBHOOKS - request.app.state.config.ENABLE_USER_STATUS = form_data.ENABLE_USER_STATUS - - request.app.state.config.PENDING_USER_OVERLAY_TITLE = form_data.PENDING_USER_OVERLAY_TITLE - request.app.state.config.PENDING_USER_OVERLAY_CONTENT = form_data.PENDING_USER_OVERLAY_CONTENT - - request.app.state.config.RESPONSE_WATERMARK = form_data.RESPONSE_WATERMARK - - return { - 'SHOW_ADMIN_DETAILS': request.app.state.config.SHOW_ADMIN_DETAILS, - 'ADMIN_EMAIL': request.app.state.config.ADMIN_EMAIL, - 'WEBUI_URL': request.app.state.config.WEBUI_URL, - 'ENABLE_SIGNUP': request.app.state.config.ENABLE_SIGNUP, - 'ENABLE_API_KEYS': request.app.state.config.ENABLE_API_KEYS, - 'ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS': request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS, - 'API_KEYS_ALLOWED_ENDPOINTS': request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS, - 'DEFAULT_USER_ROLE': request.app.state.config.DEFAULT_USER_ROLE, - 'DEFAULT_GROUP_ID': request.app.state.config.DEFAULT_GROUP_ID, - 'JWT_EXPIRES_IN': request.app.state.config.JWT_EXPIRES_IN, - 'ENABLE_COMMUNITY_SHARING': request.app.state.config.ENABLE_COMMUNITY_SHARING, - 'ENABLE_MESSAGE_RATING': request.app.state.config.ENABLE_MESSAGE_RATING, - 'ENABLE_FOLDERS': request.app.state.config.ENABLE_FOLDERS, - 'FOLDER_MAX_FILE_COUNT': request.app.state.config.FOLDER_MAX_FILE_COUNT, - 'AUTOMATION_MAX_COUNT': request.app.state.config.AUTOMATION_MAX_COUNT, - 'AUTOMATION_MIN_INTERVAL': request.app.state.config.AUTOMATION_MIN_INTERVAL, - 'ENABLE_AUTOMATIONS': request.app.state.config.ENABLE_AUTOMATIONS, - 'ENABLE_CHANNELS': request.app.state.config.ENABLE_CHANNELS, - 'ENABLE_CALENDAR': request.app.state.config.ENABLE_CALENDAR, - 'ENABLE_MEMORIES': request.app.state.config.ENABLE_MEMORIES, - 'ENABLE_NOTES': request.app.state.config.ENABLE_NOTES, - 'ENABLE_USER_WEBHOOKS': request.app.state.config.ENABLE_USER_WEBHOOKS, - 'ENABLE_USER_STATUS': request.app.state.config.ENABLE_USER_STATUS, - 'PENDING_USER_OVERLAY_TITLE': request.app.state.config.PENDING_USER_OVERLAY_TITLE, - 'PENDING_USER_OVERLAY_CONTENT': request.app.state.config.PENDING_USER_OVERLAY_CONTENT, - 'RESPONSE_WATERMARK': request.app.state.config.RESPONSE_WATERMARK, - } + await Config.upsert(updates) + return await get_config_values(ADMIN_CONFIG_KEYS) class LdapServerConfig(BaseModel): @@ -1155,21 +1190,7 @@ class LdapServerConfig(BaseModel): @router.get('/admin/config/ldap/server', response_model=LdapServerConfig) async def get_ldap_server(request: Request, user=Depends(get_admin_user)): - return { - 'label': request.app.state.config.LDAP_SERVER_LABEL, - 'host': request.app.state.config.LDAP_SERVER_HOST, - 'port': request.app.state.config.LDAP_SERVER_PORT, - 'attribute_for_mail': request.app.state.config.LDAP_ATTRIBUTE_FOR_MAIL, - 'attribute_for_username': request.app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME, - 'app_dn': request.app.state.config.LDAP_APP_DN, - 'app_dn_password': request.app.state.config.LDAP_APP_PASSWORD, - 'search_base': request.app.state.config.LDAP_SEARCH_BASE, - 'search_filters': request.app.state.config.LDAP_SEARCH_FILTERS, - 'use_tls': request.app.state.config.LDAP_USE_TLS, - 'certificate_path': request.app.state.config.LDAP_CA_CERT_FILE, - 'validate_cert': request.app.state.config.LDAP_VALIDATE_CERT, - 'ciphers': request.app.state.config.LDAP_CIPHERS, - } + return await get_config_values(LDAP_SERVER_CONFIG_KEYS) @router.post('/admin/config/ldap/server') @@ -1186,40 +1207,16 @@ async def update_ldap_server(request: Request, form_data: LdapServerConfig, user if not value: raise HTTPException(400, detail=ERROR_MESSAGES.REQUIRED_FIELD_EMPTY(key)) - request.app.state.config.LDAP_SERVER_LABEL = form_data.label - request.app.state.config.LDAP_SERVER_HOST = form_data.host - request.app.state.config.LDAP_SERVER_PORT = form_data.port - request.app.state.config.LDAP_ATTRIBUTE_FOR_MAIL = form_data.attribute_for_mail - request.app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME = form_data.attribute_for_username - request.app.state.config.LDAP_APP_DN = form_data.app_dn or '' - request.app.state.config.LDAP_APP_PASSWORD = form_data.app_dn_password or '' - request.app.state.config.LDAP_SEARCH_BASE = form_data.search_base - request.app.state.config.LDAP_SEARCH_FILTERS = form_data.search_filters - request.app.state.config.LDAP_USE_TLS = form_data.use_tls - request.app.state.config.LDAP_CA_CERT_FILE = form_data.certificate_path - request.app.state.config.LDAP_VALIDATE_CERT = form_data.validate_cert - request.app.state.config.LDAP_CIPHERS = form_data.ciphers - - return { - 'label': request.app.state.config.LDAP_SERVER_LABEL, - 'host': request.app.state.config.LDAP_SERVER_HOST, - 'port': request.app.state.config.LDAP_SERVER_PORT, - 'attribute_for_mail': request.app.state.config.LDAP_ATTRIBUTE_FOR_MAIL, - 'attribute_for_username': request.app.state.config.LDAP_ATTRIBUTE_FOR_USERNAME, - 'app_dn': request.app.state.config.LDAP_APP_DN, - 'app_dn_password': request.app.state.config.LDAP_APP_PASSWORD, - 'search_base': request.app.state.config.LDAP_SEARCH_BASE, - 'search_filters': request.app.state.config.LDAP_SEARCH_FILTERS, - 'use_tls': request.app.state.config.LDAP_USE_TLS, - 'certificate_path': request.app.state.config.LDAP_CA_CERT_FILE, - 'validate_cert': request.app.state.config.LDAP_VALIDATE_CERT, - 'ciphers': request.app.state.config.LDAP_CIPHERS, - } + updates = config_updates(form_data.model_dump(), LDAP_SERVER_CONFIG_KEYS) + updates['ldap.server.app_dn'] = form_data.app_dn or '' + updates['ldap.server.app_password'] = form_data.app_dn_password or '' + await Config.upsert(updates) + return await get_config_values(LDAP_SERVER_CONFIG_KEYS) @router.get('/admin/config/ldap') async def get_ldap_config(request: Request, user=Depends(get_admin_user)): - return {'ENABLE_LDAP': request.app.state.config.ENABLE_LDAP} + return {'ENABLE_LDAP': await Config.get('ldap.enable')} class LdapConfigForm(BaseModel): @@ -1228,8 +1225,8 @@ class LdapConfigForm(BaseModel): @router.post('/admin/config/ldap') async def update_ldap_config(request: Request, form_data: LdapConfigForm, user=Depends(get_admin_user)): - request.app.state.config.ENABLE_LDAP = form_data.enable_ldap - return {'ENABLE_LDAP': request.app.state.config.ENABLE_LDAP} + await Config.upsert({'ldap.enable': form_data.enable_ldap}) + return {'ENABLE_LDAP': await Config.get('ldap.enable')} ############################ @@ -1237,24 +1234,172 @@ async def update_ldap_config(request: Request, form_data: LdapConfigForm, user=D ############################ -# create api key -@router.post('/api_key', response_model=ApiKey) -async def generate_api_key( - request: Request, user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session) -): - if not request.app.state.config.ENABLE_API_KEYS or ( +class OAuthConfigForm(BaseModel): + """All OAuth/OIDC settings exposed to the admin panel.""" + + # General OAuth + ENABLE_OAUTH_SIGNUP: bool | None = None + OAUTH_MERGE_ACCOUNTS_BY_EMAIL: bool | None = None + OAUTH_AUTO_REDIRECT: bool | None = None + OAUTH_ALLOWED_DOMAINS: str | None = None + OAUTH_BLOCKED_GROUPS: str | None = None + + # Role management + ENABLE_OAUTH_ROLE_MANAGEMENT: bool | None = None + OAUTH_ROLES_CLAIM: str | None = None + OAUTH_ADMIN_ROLES: str | None = None + OAUTH_ALLOWED_ROLES: str | None = None + + # Group management + ENABLE_OAUTH_GROUP_MANAGEMENT: bool | None = None + ENABLE_OAUTH_GROUP_CREATION: bool | None = None + OAUTH_GROUP_CLAIM: str | None = None + OAUTH_GROUP_DEFAULT_SHARE: bool | str | None = None + + # OIDC provider settings + OAUTH_PROVIDER_NAME: str | None = None + OPENID_PROVIDER_URL: str | None = None + OAUTH_CLIENT_ID: str | None = None + OAUTH_CLIENT_SECRET: str | None = None + OPENID_REDIRECT_URI: str | None = None + OAUTH_SCOPES: str | None = None + OAUTH_CODE_CHALLENGE_METHOD: str | None = None + OAUTH_TOKEN_ENDPOINT_AUTH_METHOD: str | None = None + OPENID_END_SESSION_ENDPOINT: str | None = None + OAUTH_TIMEOUT: int | str | None = None + OAUTH_CLIENT_TIMEOUT: int | str | None = None + + # Claims + OAUTH_EMAIL_CLAIM: str | None = None + OAUTH_USERNAME_CLAIM: str | None = None + OAUTH_PICTURE_CLAIM: str | None = None + OAUTH_SUB_CLAIM: str | None = None + OAUTH_AUDIENCE: str | None = None + + # Profile update toggles + OAUTH_UPDATE_EMAIL_ON_LOGIN: bool | None = None + OAUTH_UPDATE_NAME_ON_LOGIN: bool | None = None + OAUTH_UPDATE_PICTURE_ON_LOGIN: bool | None = None + + # Token + OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE: bool | None = None + + +OAUTH_COMMA_LIST_FIELDS = { + 'OAUTH_ALLOWED_DOMAINS', + 'OAUTH_ADMIN_ROLES', + 'OAUTH_ALLOWED_ROLES', +} + + +OAUTH_CONFIG_KEYS = { + 'ENABLE_OAUTH_SIGNUP': 'oauth.enable_signup', + 'OAUTH_MERGE_ACCOUNTS_BY_EMAIL': 'oauth.merge_accounts_by_email', + 'OAUTH_AUTO_REDIRECT': 'oauth.auto_redirect', + 'OAUTH_ALLOWED_DOMAINS': 'oauth.allowed_domains', + 'OAUTH_BLOCKED_GROUPS': 'oauth.blocked_groups', + 'ENABLE_OAUTH_ROLE_MANAGEMENT': 'oauth.enable_role_mapping', + 'OAUTH_ROLES_CLAIM': 'oauth.roles_claim', + 'OAUTH_ADMIN_ROLES': 'oauth.admin_roles', + 'OAUTH_ALLOWED_ROLES': 'oauth.allowed_roles', + 'ENABLE_OAUTH_GROUP_MANAGEMENT': 'oauth.enable_group_mapping', + 'ENABLE_OAUTH_GROUP_CREATION': 'oauth.enable_group_creation', + 'OAUTH_GROUP_CLAIM': 'oauth.group_claim', + 'OAUTH_GROUP_DEFAULT_SHARE': 'oauth.group_default_share', + 'OAUTH_PROVIDER_NAME': 'oauth.provider_name', + 'OPENID_PROVIDER_URL': 'oauth.provider_url', + 'OAUTH_CLIENT_ID': 'oauth.client_id', + 'OAUTH_CLIENT_SECRET': 'oauth.client_secret', + 'OPENID_REDIRECT_URI': 'oauth.redirect_uri', + 'OAUTH_SCOPES': 'oauth.scopes', + 'OAUTH_CODE_CHALLENGE_METHOD': 'oauth.code_challenge_method', + 'OAUTH_TOKEN_ENDPOINT_AUTH_METHOD': 'oauth.token_endpoint_auth_method', + 'OPENID_END_SESSION_ENDPOINT': 'oauth.end_session_endpoint', + 'OAUTH_TIMEOUT': 'oauth.timeout', + 'OAUTH_CLIENT_TIMEOUT': 'oauth.client.timeout', + 'OAUTH_EMAIL_CLAIM': 'oauth.email_claim', + 'OAUTH_USERNAME_CLAIM': 'oauth.username_claim', + 'OAUTH_PICTURE_CLAIM': 'oauth.picture_claim', + 'OAUTH_SUB_CLAIM': 'oauth.sub_claim', + 'OAUTH_AUDIENCE': 'oauth.audience', + 'OAUTH_UPDATE_EMAIL_ON_LOGIN': 'oauth.update_email_on_login', + 'OAUTH_UPDATE_NAME_ON_LOGIN': 'oauth.update_name_on_login', + 'OAUTH_UPDATE_PICTURE_ON_LOGIN': 'oauth.update_picture_on_login', + 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE': 'oauth.refresh_token.include_scope', +} + + +def _format_oauth_form_value(field: str, value): + if field in OAUTH_COMMA_LIST_FIELDS and isinstance(value, list): + return ','.join(str(item) for item in value) + return value + + +def _parse_oauth_update_value(field: str, value): + if field in OAUTH_COMMA_LIST_FIELDS and isinstance(value, str): + return [item.strip() for item in value.split(',') if item.strip()] + if field in {'OAUTH_TIMEOUT', 'OAUTH_CLIENT_TIMEOUT'} and value == '': + return '' + return value + + +async def get_oauth_config_values() -> dict: + values = await Config.get_many(*OAUTH_CONFIG_KEYS.values()) + return { + field: _format_oauth_form_value(field, values[storage_key]) + for field, storage_key in OAUTH_CONFIG_KEYS.items() + if storage_key in values + } + + +def oauth_config_updates(data: dict) -> dict: + return { + OAUTH_CONFIG_KEYS[field]: _parse_oauth_update_value(field, value) + for field, value in data.items() + if field in OAUTH_CONFIG_KEYS + } + + +@router.get('/admin/config/oauth', response_model=OAuthConfigForm) +async def get_oauth_config(request: Request, user=Depends(get_admin_user)): + return await get_oauth_config_values() + + +@router.post('/admin/config/oauth', response_model=OAuthConfigForm) +async def update_oauth_config(request: Request, form_data: OAuthConfigForm, user=Depends(get_admin_user)): + await Config.upsert(oauth_config_updates(form_data.model_dump(exclude_none=True))) + return await get_oauth_config_values() + + +async def _check_api_key_permission(request: Request, user, db: AsyncSession): + if not await Config.get('auth.enable_api_keys') or ( user.role != 'admin' - and not await has_permission(user.id, 'features.api_keys', request.app.state.config.USER_PERMISSIONS) + and not await has_permission(user.id, 'features.api_keys', await Config.get('user.permissions'), db=db) ): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_CREATION_NOT_ALLOWED, ) + +# create api key +@router.post('/api_key', response_model=ApiKey) +async def generate_api_key( + request: Request, user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session) +): + await _check_api_key_permission(request, user, db) + api_key = create_api_key() success = await Users.update_user_api_key_by_id(user.id, api_key, db=db) if success: + await publish_event( + request, + EVENTS.AUTH_API_KEY_CREATED, + actor=user, + subject_id=user.id, + subject_type='user', + ) return { 'api_key': api_key, } @@ -1264,13 +1409,26 @@ async def generate_api_key( # delete api key @router.delete('/api_key', response_model=bool) -async def delete_api_key(user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session)): - return await Users.delete_user_api_key_by_id(user.id, db=db) +async def delete_api_key( + request: Request, user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session) +): + await _check_api_key_permission(request, user, db) + success = await Users.delete_user_api_key_by_id(user.id, db=db) + if success: + await publish_event( + request, + EVENTS.AUTH_API_KEY_DELETED, + actor=user, + subject_id=user.id, + subject_type='user', + ) + return success # get api key @router.get('/api_key', response_model=ApiKey) -async def get_api_key(user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session)): +async def get_api_key(request: Request, user=Depends(get_current_user), db: AsyncSession = Depends(get_async_session)): + await _check_api_key_permission(request, user, db) api_key = await Users.get_user_api_key_by_id(user.id, db=db) if api_key: return { @@ -1342,11 +1500,11 @@ async def token_exchange( ) # Extract user information from the token claims - email_claim = request.app.state.config.OAUTH_EMAIL_CLAIM - username_claim = request.app.state.config.OAUTH_USERNAME_CLAIM + email_claim = await Config.get('oauth.email_claim', 'email') # Get sub claim - sub = user_data.get(request.app.state.config.OAUTH_SUB_CLAIM or OAUTH_PROVIDERS[provider].get('sub_claim', 'sub')) + sub_claim = await Config.get('oauth.sub_claim') + sub = user_data.get(sub_claim or OAUTH_PROVIDERS[provider].get('sub_claim', 'sub')) if not sub: log.warning(f'Token exchange failed: sub claim missing from user data') raise HTTPException( @@ -1364,10 +1522,10 @@ async def token_exchange( email = email.lower() # Enforce domain allowlist — same check as the normal OAuth callback - if ( - '*' not in auth_manager_config.OAUTH_ALLOWED_DOMAINS - and email.split('@')[-1] not in auth_manager_config.OAUTH_ALLOWED_DOMAINS - ): + oauth_allowed_domains = await Config.get('oauth.allowed_domains', []) + if isinstance(oauth_allowed_domains, str): + oauth_allowed_domains = [domain.strip() for domain in oauth_allowed_domains.split(',') if domain.strip()] + if '*' not in oauth_allowed_domains and email.split('@')[-1] not in oauth_allowed_domains: log.warning(f'Token exchange denied: email domain not in allowed domains list') raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, @@ -1377,7 +1535,7 @@ async def token_exchange( # Try to find the user by OAuth sub user = await Users.get_user_by_oauth_sub(provider, sub, db=db) - if not user and OAUTH_MERGE_ACCOUNTS_BY_EMAIL.value: + if not user and await Config.get('oauth.merge_accounts_by_email'): # Try to find by email if merge is enabled user = await Users.get_user_by_email(email, db=db) if user: @@ -1390,4 +1548,4 @@ async def token_exchange( detail='User not found. Please sign in via the web interface first.', ) - return await create_session_response(request, user, db) + return await create_session_response(request, user, db, source='oauth') diff --git a/backend/open_webui/routers/automations.py b/backend/open_webui/routers/automations.py index fced12978a..f7d027bad9 100644 --- a/backend/open_webui/routers/automations.py +++ b/backend/open_webui/routers/automations.py @@ -4,6 +4,7 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.automations import ( AutomationForm, @@ -14,6 +15,7 @@ from open_webui.models.automations import ( AutomationRuns, Automations, ) +from open_webui.models.config import Config from open_webui.utils.access_control import has_permission from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.automations import ( @@ -38,13 +40,14 @@ PAGE_ITEM_COUNT = 30 async def check_automations_permission(request, user): - if not request.app.state.config.ENABLE_AUTOMATIONS: + config = await Config.get_many('automations.enable', 'user.permissions') + if not config.get('automations.enable'): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.UNAUTHORIZED, ) if user.role != 'admin' and not await has_permission( - user.id, 'features.automations', request.app.state.config.USER_PERMISSIONS + user.id, 'features.automations', config.get('user.permissions') ): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, @@ -72,7 +75,7 @@ async def check_automation_limits(request, user, rrule_str: str, db, is_create: # Max count (create only) if is_create: - max_count = request.app.state.config.AUTOMATION_MAX_COUNT + max_count = await Config.get('automations.max_count') if max_count: max_count = int(max_count) if max_count > 0 and await Automations.count_by_user(user.id, db=db) >= max_count: @@ -82,7 +85,7 @@ async def check_automation_limits(request, user, rrule_str: str, db, is_create: ) # Min interval (create + update) - min_interval = request.app.state.config.AUTOMATION_MIN_INTERVAL + min_interval = await Config.get('automations.min_interval') if min_interval: min_interval = int(min_interval) if min_interval > 0: @@ -173,7 +176,15 @@ async def create_new_automation( tz = user.timezone automation = await Automations.insert(user.id, form_data, next_run_ns(form_data.data.rrule, tz=tz), db=db) - return await enrich_automation(automation, db, tz=tz) + response = await enrich_automation(automation, db, tz=tz) + await publish_event( + request, + EVENTS.AUTOMATION_CREATED, + actor=user, + subject_id=automation.id, + data={'name': automation.name, 'is_active': automation.is_active}, + ) + return response ############################ @@ -223,7 +234,15 @@ async def update_automation_by_id( tz = user.timezone updated = await Automations.update_by_id(id, form_data, next_run_ns(form_data.data.rrule, tz=tz), db=db) - return await enrich_automation(updated, db, tz=tz) + response = await enrich_automation(updated, db, tz=tz) + await publish_event( + request, + EVENTS.AUTOMATION_UPDATED, + actor=user, + subject_id=updated.id, + data={'name': updated.name, 'is_active': updated.is_active}, + ) + return response ############################ @@ -242,7 +261,16 @@ async def toggle_automation_by_id( automation = await Automations.get_by_id(id, db=db) check_automation_access(automation, user) toggled = await Automations.toggle(id, next_run_ns(automation.data['rrule'], tz=user.timezone), db=db) - return await enrich_automation(toggled, db, tz=user.timezone) + response = await enrich_automation(toggled, db, tz=user.timezone) + await publish_event( + request, + EVENTS.AUTOMATION_ENABLED if toggled.is_active else EVENTS.AUTOMATION_DISABLED, + actor=user, + subject_id=toggled.id, + subject_type='automation', + data={'name': toggled.name}, + ) + return response ############################ @@ -261,6 +289,13 @@ async def run_automation_by_id( automation = await Automations.get_by_id(id, db=db) check_automation_access(automation, user) asyncio.create_task(execute_automation(request.app, automation)) + await publish_event( + request, + EVENTS.AUTOMATION_RUN_STARTED, + actor=user, + subject_id=automation.id, + data={'name': automation.name}, + ) return await enrich_automation(automation, db, tz=user.timezone) @@ -280,7 +315,16 @@ async def delete_automation_by_id( automation = await Automations.get_by_id(id, db=db) check_automation_access(automation, user) await AutomationRuns.delete_by_automation(id, db=db) - return await Automations.delete(id, db=db) + result = await Automations.delete(id, db=db) + if result: + await publish_event( + request, + EVENTS.AUTOMATION_DELETED, + actor=user, + subject_id=id, + data={'name': automation.name}, + ) + return result ############################ diff --git a/backend/open_webui/routers/calendar.py b/backend/open_webui/routers/calendar.py index 5d397ea868..f95be48e84 100644 --- a/backend/open_webui/routers/calendar.py +++ b/backend/open_webui/routers/calendar.py @@ -4,6 +4,7 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.models.access_grants import AccessGrants from open_webui.models.calendar import ( CalendarEventAttendees, @@ -19,6 +20,7 @@ from open_webui.models.calendar import ( CalendarUpdateForm, RSVPForm, ) +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.users import UserModel from open_webui.utils.access_control import filter_allowed_access_grants, has_permission @@ -34,14 +36,13 @@ SCHEDULED_TASKS_CALENDAR_ID = '__scheduled_tasks__' async def check_calendar_permission(request: Request, user): """Check global feature flag AND per-user permission for calendar access.""" - if not request.app.state.config.ENABLE_CALENDAR: + config = await Config.get_many('calendar.enable', 'user.permissions') + if not config.get('calendar.enable'): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.UNAUTHORIZED, ) - if user.role != 'admin' and not await has_permission( - user.id, 'features.calendar', request.app.state.config.USER_PERMISSIONS - ): + if user.role != 'admin' and not await has_permission(user.id, 'features.calendar', config.get('user.permissions')): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.UNAUTHORIZED, @@ -50,11 +51,12 @@ async def check_calendar_permission(request: Request, user): async def _user_has_automations(request: Request, user) -> bool: """Check if automations feature is available to this user.""" - if not getattr(request.app.state.config, 'ENABLE_AUTOMATIONS', False): + config = await Config.get_many('automations.enable', 'user.permissions') + if not config.get('automations.enable', False): return False if user.role == 'admin': return True - return await has_permission(user.id, 'features.automations', request.app.state.config.USER_PERMISSIONS) + return await has_permission(user.id, 'features.automations', config.get('user.permissions')) async def _check_calendar_access(calendar_id: str, user: UserModel, permission: str = 'write') -> CalendarModel: @@ -116,13 +118,21 @@ async def create_calendar(request: Request, form_data: CalendarForm, user: UserM # could create a calendar with `principal_id='*' permission='read'|'write'`, # making their events readable or writable by any other verified user. form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, 'sharing.public_calendars', ) - return await Calendars.insert_new_calendar(user.id, form_data) + calendar = await Calendars.insert_new_calendar(user.id, form_data) + await publish_event( + request, + EVENTS.CALENDAR_CREATED, + actor=user, + subject_id=calendar.id, + data={'name': calendar.name}, + ) + return calendar #################### @@ -263,7 +273,15 @@ async def get_events( async def create_event(request: Request, form_data: CalendarEventForm, user: UserModel = Depends(get_verified_user)): await check_calendar_permission(request, user) await _check_calendar_access(form_data.calendar_id, user, 'write') - return await CalendarEvents.insert_new_event(user.id, form_data) + event = await CalendarEvents.insert_new_event(user.id, form_data) + await publish_event( + request, + EVENTS.CALENDAR_EVENT_CREATED, + actor=user, + subject_id=event.id, + data={'calendar_id': event.calendar_id, 'title': event.title}, + ) + return event @router.get('/events/search', response_model=CalendarEventListResponse) @@ -310,6 +328,13 @@ async def update_event( updated = await CalendarEvents.update_event_by_id(event_id, form_data) if not updated: raise HTTPException(status_code=500, detail='Failed to update') + await publish_event( + request, + EVENTS.CALENDAR_EVENT_UPDATED, + actor=user, + subject_id=updated.id, + data={'calendar_id': updated.calendar_id, 'title': updated.title}, + ) return updated @@ -325,6 +350,13 @@ async def delete_event(request: Request, event_id: str, user: UserModel = Depend result = await CalendarEvents.delete_event_by_id(event_id) if not result: raise HTTPException(status_code=500, detail='Failed to delete') + await publish_event( + request, + EVENTS.CALENDAR_EVENT_DELETED, + actor=user, + subject_id=event_id, + data={'calendar_id': event.calendar_id, 'title': event.title}, + ) return {'status': True} @@ -340,6 +372,13 @@ async def rsvp_event( result = await CalendarEventAttendees.update_rsvp(event_id, user.id, form_data.status) if not result: raise HTTPException(status_code=404, detail='Not an attendee of this event') + await publish_event( + request, + EVENTS.CALENDAR_EVENT_RSVP_UPDATED, + actor=user, + subject_id=event_id, + data={'status': result.status}, + ) return {'status': True, 'rsvp': result.status} @@ -373,7 +412,7 @@ async def update_calendar( # publicly readable/writable without the corresponding sharing permission. if form_data.access_grants is not None: form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -383,6 +422,13 @@ async def update_calendar( updated = await Calendars.update_calendar_by_id(calendar_id, form_data) if not updated: raise HTTPException(status_code=500, detail='Failed to update') + await publish_event( + request, + EVENTS.CALENDAR_UPDATED, + actor=user, + subject_id=updated.id, + data={'name': updated.name}, + ) return updated @@ -407,6 +453,13 @@ async def delete_calendar(request: Request, calendar_id: str, user: UserModel = result = await Calendars.delete_calendar_by_id(calendar_id) if not result: raise HTTPException(status_code=500, detail='Failed to delete') + await publish_event( + request, + EVENTS.CALENDAR_DELETED, + actor=user, + subject_id=calendar_id, + data={'name': cal.name}, + ) return {'status': True} @@ -416,4 +469,11 @@ async def set_default_calendar(request: Request, calendar_id: str, user: UserMod cal = await Calendars.set_default_calendar(user.id, calendar_id) if not cal: raise HTTPException(status_code=404, detail='Calendar not found') + await publish_event( + request, + EVENTS.CALENDAR_DEFAULT_UPDATED, + actor=user, + subject_id=cal.id, + data={'name': cal.name}, + ) return cal diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index 11d3a4a871..459a238ba1 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -8,9 +8,11 @@ from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request, from fastapi.responses import FileResponse, Response, StreamingResponse from open_webui.config import ENABLE_ADMIN_CHAT_ACCESS, ENABLE_ADMIN_EXPORT from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import STATIC_DIR from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants, has_public_read_access_grant, has_public_write_access_grant +from open_webui.models.config import Config from open_webui.models.channels import ( ChannelForm, ChannelModel, @@ -31,9 +33,7 @@ from open_webui.models.messages import ( from open_webui.models.users import ( UserIdNameResponse, UserIdNameStatusResponse, - UserListResponse, UserModel, - UserModelResponse, UserNameResponse, Users, ) @@ -125,7 +125,7 @@ def get_channel_permitted_group_and_user_ids( async def check_channels_access(request: Request, user: Optional[UserModel] = None): """Dependency to ensure channels are globally enabled.""" - if not request.app.state.config.ENABLE_CHANNELS: + if not await Config.get('channels.enable'): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.FEATURE_DISABLED('Channels'), @@ -133,7 +133,7 @@ async def check_channels_access(request: Request, user: Optional[UserModel] = No if user: if user.role != 'admin' and not await has_permission( - user.id, 'features.channels', request.app.state.config.USER_PERMISSIONS + user.id, 'features.channels', await Config.get('user.permissions') ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -294,7 +294,7 @@ async def create_new_channel( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -316,6 +316,13 @@ async def create_new_channel( await enter_room_for_users(f'channel:{existing_channel.id}', participant_ids) await Channels.update_member_active_status(existing_channel.id, user.id, True, db=db) + await publish_event( + request, + EVENTS.CHANNEL_MEMBER_ACTIVE_UPDATED, + actor=user, + subject_id=existing_channel.id, + data={'is_active': True}, + ) return ChannelModel(**existing_channel.model_dump()) channel = await Channels.insert_new_channel(form_data, user.id, db=db) @@ -330,6 +337,13 @@ async def create_new_channel( ) await enter_room_for_users(f'channel:{channel.id}', participant_ids) + await publish_event( + request, + EVENTS.CHANNEL_CREATED, + actor=user, + subject_id=channel.id, + data={'type': channel.type, 'name': channel.name}, + ) return ChannelModel(**channel.model_dump()) else: raise Exception('Error creating channel') @@ -440,7 +454,40 @@ async def get_channel_by_id( PAGE_ITEM_COUNT = 30 -@router.get('/{id}/members', response_model=UserListResponse) +class ChannelMemberResponse(BaseModel): + id: str + email: str + name: str + role: str + profile_image_url: str | None = None + presence_state: str | None = None + status_emoji: str | None = None + status_message: str | None = None + status_expires_at: int | None = None + is_active: bool = False + + +class ChannelMemberListResponse(BaseModel): + users: list[ChannelMemberResponse] + total: int + + +def serialize_channel_member(user: UserModel) -> ChannelMemberResponse: + return ChannelMemberResponse( + id=user.id, + email=user.email, + name=user.name, + role=user.role, + profile_image_url=user.profile_image_url, + presence_state=user.presence_state, + status_emoji=user.status_emoji, + status_message=user.status_message, + status_expires_at=user.status_expires_at, + is_active=Users.is_active(user), + ) + + +@router.get('/{id}/members', response_model=ChannelMemberListResponse) async def get_channel_members_by_id( request: Request, id: str, @@ -475,7 +522,7 @@ async def get_channel_members_by_id( total = len(fetched_users) return { - 'users': [UserModelResponse(**u.model_dump(), is_active=Users.is_active(u)) for u in fetched_users], + 'users': [serialize_channel_member(u) for u in fetched_users], 'total': total, } else: @@ -503,7 +550,7 @@ async def get_channel_members_by_id( total = result['total'] return { - 'users': [UserModelResponse(**u.model_dump(), is_active=Users.is_active(u)) for u in fetched_users], + 'users': [serialize_channel_member(u) for u in fetched_users], 'total': total, } @@ -534,6 +581,13 @@ async def update_is_active_member_by_id_and_user_id( raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) await Channels.update_member_active_status(channel.id, user.id, form_data.is_active, db=db) + await publish_event( + request, + EVENTS.CHANNEL_MEMBER_ACTIVE_UPDATED, + actor=user, + subject_id=channel.id, + data={'is_active': form_data.is_active}, + ) return True @@ -568,6 +622,13 @@ async def add_members_by_id( channel.id, user.id, form_data.user_ids, form_data.group_ids, db=db ) + await publish_event( + request, + EVENTS.CHANNEL_MEMBER_ADDED, + actor=user, + subject_id=channel.id, + data={'user_ids': form_data.user_ids, 'group_ids': form_data.group_ids}, + ) return memberships except Exception as e: log.exception(e) @@ -603,6 +664,13 @@ async def remove_members_by_id( try: deleted = await Channels.remove_members_from_channel(channel.id, form_data.user_ids, db=db) + await publish_event( + request, + EVENTS.CHANNEL_MEMBER_REMOVED, + actor=user, + subject_id=channel.id, + data={'user_ids': form_data.user_ids}, + ) return deleted except Exception as e: log.exception(e) @@ -632,7 +700,7 @@ async def update_channel_by_id( raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -641,6 +709,13 @@ async def update_channel_by_id( try: channel = await Channels.update_channel_by_id(id, form_data, db=db) + await publish_event( + request, + EVENTS.CHANNEL_UPDATED, + actor=user, + subject_id=id, + data={'name': channel.name, 'type': channel.type}, + ) return ChannelModel(**channel.model_dump()) except Exception as e: log.exception(e) @@ -670,6 +745,13 @@ async def delete_channel_by_id( try: await Channels.delete_channel_by_id(id, db=db) + await publish_event( + request, + EVENTS.CHANNEL_DELETED, + actor=user, + subject_id=id, + data={'name': channel.name, 'type': channel.type}, + ) return True except Exception as e: log.exception(e) @@ -726,10 +808,14 @@ async def get_channel_messages( user_ids = list(set(m.user_id for m in message_list)) fetched_users = {u.id: u for u in await Users.get_users_by_user_ids(user_ids, db=db)} + # Batch fetch reactions and reply counts in 2 queries (fixes N+1) + message_ids = [m.id for m in message_list] + all_reactions = await Messages.get_reactions_by_message_ids(message_ids, db=db) + all_reply_counts = await Messages.get_thread_reply_counts_by_message_ids(message_ids, db=db) + messages = [] for message in message_list: - thread_replies = await Messages.get_thread_replies_by_message_id(message.id, db=db) - latest_thread_reply_at = thread_replies[0].created_at if thread_replies else None + reply_count, latest_reply_at = all_reply_counts.get(message.id, (0, None)) # Use message.user if present (for webhooks), otherwise look up by user_id user_info = message.user @@ -740,9 +826,9 @@ async def get_channel_messages( MessageUserResponse( **{ **message.model_dump(), - 'reply_count': len(thread_replies), - 'latest_reply_at': latest_thread_reply_at, - 'reactions': await Messages.get_reactions_by_message_id(message.id, db=db), + 'reply_count': reply_count, + 'latest_reply_at': latest_reply_at, + 'reactions': all_reactions.get(message.id, []), 'user': user_info, } ) @@ -791,6 +877,10 @@ async def get_pinned_channel_messages( user_ids = list(set(m.user_id for m in message_list)) fetched_users = {u.id: u for u in await Users.get_users_by_user_ids(user_ids, db=db)} + # Batch fetch reactions in 1 query (fixes N+1) + message_ids = [m.id for m in message_list] + all_reactions = await Messages.get_reactions_by_message_ids(message_ids, db=db) + messages = [] for message in message_list: # Check for webhook identity in meta @@ -810,7 +900,7 @@ async def get_pinned_channel_messages( MessageWithReactionsResponse( **{ **message.model_dump(), - 'reactions': await Messages.get_reactions_by_message_id(message.id, db=db), + 'reactions': all_reactions.get(message.id, []), 'user': user_info, } ) @@ -826,13 +916,16 @@ async def get_pinned_channel_messages( async def send_notification(request, channel, message, active_user_ids, db=None): name = request.app.state.WEBUI_NAME - webui_url = request.app.state.config.WEBUI_URL - enable_user_webhooks = request.app.state.config.ENABLE_USER_WEBHOOKS + webui_url = await Config.get('webui.url') + enable_user_webhooks = await Config.get('ui.enable_user_webhooks') users = await get_channel_users_with_access(channel, 'read', db=db) + # Batch fetch channel members in 1 query (fixes N+1) + member_ids = {m.user_id for m in await Channels.get_members_by_channel_id(channel.id, db=db)} + for u in users: - if (u.id not in active_user_ids) and await Channels.is_user_channel_member(channel.id, u.id, db=db): + if (u.id not in active_user_ids) and u.id in member_ids: if enable_user_webhooks and u.settings: webhook_url = u.settings.ui.get('notifications', {}).get('webhook_url', None) if webhook_url: @@ -978,7 +1071,7 @@ async def model_response_handler(request, channel, message, user, db=None): ) tool_ids = _resolve_model_tool_ids(request.app, model_id) - features = _resolve_model_features(request.app, model_id) + features = await _resolve_model_features(request.app, model_id) filter_ids = _resolve_model_filter_ids(request.app, model_id) # Build full form_data — same shape as frontend POST. @@ -1036,6 +1129,13 @@ async def new_message_handler(request: Request, id: str, form_data: MessageForm, ): raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) + # Thread parent / reply target must belong to this channel (no cross-channel binding). + for ref_id in (form_data.parent_id, form_data.reply_to_id): + if ref_id: + ref = await Messages.get_message_by_id(ref_id, include_thread_replies=False, db=db) + if not ref or ref.channel_id != channel.id: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + try: message = await Messages.insert_new_message(form_data, channel.id, user.id, db=db) if message: @@ -1128,6 +1228,16 @@ async def post_new_message( background_tasks.add_task(background_handler) + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor=user, + subject_id=message.id, + data={ + 'channel_id': channel.id, + 'content_preview': message.content[:300], + }, + ) return message except HTTPException as e: @@ -1255,12 +1365,37 @@ async def pin_channel_message( await Messages.update_is_pinned_by_id(message_id, form_data.is_pinned, user.id, db=db) message = await Messages.get_message_by_id(message_id, db=db) message_user = await Users.get_user_by_id(message.user_id, db=db) - return MessageUserResponse( + message_data = MessageUserResponse( **{ **message.model_dump(), 'user': UserNameResponse(**message_user.model_dump()) if message_user else None, } ) + + await sio.emit( + 'events:channel', + { + 'channel_id': channel.id, + 'message_id': message.id, + 'data': { + 'type': 'message:update', + 'data': message_data.model_dump(), + }, + 'user': UserNameResponse(**user.model_dump()).model_dump(), + 'channel': channel.model_dump(), + }, + to=f'channel:{channel.id}', + ) + + await publish_event( + request, + EVENTS.MESSAGE_PINNED if form_data.is_pinned else EVENTS.MESSAGE_UNPINNED, + actor=user, + subject_id=message_id, + subject_type='message', + data={'channel_id': id}, + ) + return message_data except Exception as e: log.exception(e) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) @@ -1302,6 +1437,10 @@ async def get_channel_thread_messages( user_ids = list(set(m.user_id for m in message_list)) fetched_users = {u.id: u for u in await Users.get_users_by_user_ids(user_ids, db=db)} + # Batch fetch reactions in 1 query (fixes N+1) + message_ids = [m.id for m in message_list] + all_reactions = await Messages.get_reactions_by_message_ids(message_ids, db=db) + messages = [] for message in message_list: # Use message.user if present (for webhooks), otherwise look up by user_id @@ -1315,7 +1454,7 @@ async def get_channel_thread_messages( **message.model_dump(), 'reply_count': 0, 'latest_reply_at': None, - 'reactions': await Messages.get_reactions_by_message_id(message.id, db=db), + 'reactions': all_reactions.get(message.id, []), 'user': user_info, } ) @@ -1384,6 +1523,13 @@ async def update_message_by_id( to=f'channel:{channel.id}', ) + await publish_event( + request, + EVENTS.MESSAGE_UPDATED, + actor=user, + subject_id=message_id, + data={'channel_id': id, 'content_preview': form_data.content[:300]}, + ) return MessageModel(**message.model_dump()) except Exception as e: log.exception(e) @@ -1455,6 +1601,13 @@ async def add_reaction_to_message( to=f'channel:{channel.id}', ) + await publish_event( + request, + EVENTS.MESSAGE_REACTION_ADDED, + actor=user, + subject_id=message_id, + data={'channel_id': id, 'reaction': form_data.name}, + ) return True except Exception as e: log.exception(e) @@ -1523,6 +1676,13 @@ async def remove_reaction_by_id_and_user_id_and_name( to=f'channel:{channel.id}', ) + await publish_event( + request, + EVENTS.MESSAGE_REACTION_REMOVED, + actor=user, + subject_id=message_id, + data={'channel_id': id, 'reaction': form_data.name}, + ) return True except Exception as e: log.exception(e) @@ -1614,6 +1774,13 @@ async def delete_message_by_id( to=f'channel:{channel.id}', ) + await publish_event( + request, + EVENTS.MESSAGE_DELETED, + actor=user, + subject_id=message_id, + data={'channel_id': id}, + ) return True except Exception as e: log.exception(e) @@ -1699,6 +1866,13 @@ async def create_channel_webhook( if not webhook: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + await publish_event( + request, + EVENTS.CHANNEL_WEBHOOK_CREATED, + actor=user, + subject_id=webhook.id, + data={'channel_id': id, 'name': webhook.name}, + ) return webhook @@ -1728,6 +1902,13 @@ async def update_channel_webhook( if not updated: raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + await publish_event( + request, + EVENTS.CHANNEL_WEBHOOK_UPDATED, + actor=user, + subject_id=webhook_id, + data={'channel_id': id, 'name': updated.name}, + ) return updated @@ -1752,7 +1933,16 @@ async def delete_channel_webhook( if not webhook or webhook.channel_id != id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) - return await Channels.delete_webhook_by_id(webhook_id, db=db) + deleted = await Channels.delete_webhook_by_id(webhook_id, db=db) + if deleted: + await publish_event( + request, + EVENTS.CHANNEL_WEBHOOK_DELETED, + actor=user, + subject_id=webhook_id, + data={'channel_id': id}, + ) + return deleted ############################ @@ -1835,4 +2025,12 @@ async def post_webhook_message( to=f'channel:{channel.id}', ) + await publish_event( + request, + EVENTS.MESSAGE_CREATED, + actor={'id': webhook.id, 'name': webhook.name, 'role': 'webhook', 'type': 'webhook'}, + subject_id=message.id, + source='channel_webhook', + data={'channel_id': channel.id, 'content_preview': form_data.content[:300]}, + ) return {'success': True, 'message_id': message.id} diff --git a/backend/open_webui/routers/chats.py b/backend/open_webui/routers/chats.py index 2689aa6d2f..98621ff80e 100644 --- a/backend/open_webui/routers/chats.py +++ b/backend/open_webui/routers/chats.py @@ -10,8 +10,10 @@ from fastapi import APIRouter, Depends, HTTPException, Request, status from fastapi.responses import StreamingResponse from open_webui.config import ENABLE_ADMIN_CHAT_ACCESS, ENABLE_ADMIN_EXPORT from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.chats import ( AggregateChatStats, ChatBody, @@ -30,11 +32,13 @@ from open_webui.models.folders import Folders from open_webui.models.shared_chats import SharedChatResponse, SharedChats from open_webui.models.tags import TagModel, Tags from open_webui.socket.main import get_event_emitter -from open_webui.tasks import stop_item_tasks +from open_webui.tasks import has_active_tasks, stop_item_tasks from open_webui.utils.access_control import filter_allowed_access_grants, has_permission +from open_webui.utils.access_control.folders import has_folder_access from open_webui.utils.auth import get_admin_user, get_verified_user -from open_webui.utils.middleware import serialize_output +from open_webui.utils.context_compaction import compact_chat_branch from open_webui.utils.misc import get_message_list +from open_webui.utils.models import get_all_models from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession @@ -42,6 +46,81 @@ log = logging.getLogger(__name__) router = APIRouter() +SEARCH_FILTER_PREFIXES = ('tag:', 'folder:', 'pinned:', 'archived:', 'shared:') + +CHAT_CONFIG_KEYS = { + 'ENABLE_CONTEXT_COMPACTION': 'chat.context_compaction.enable', + 'CONTEXT_COMPACTION_TOKEN_THRESHOLD': 'chat.context_compaction.token_threshold', + 'CONTEXT_COMPACTION_PROMPT_TEMPLATE': 'chat.context_compaction.prompt_template', +} + + +class ChatConfigForm(BaseModel): + ENABLE_CONTEXT_COMPACTION: bool + CONTEXT_COMPACTION_TOKEN_THRESHOLD: int + CONTEXT_COMPACTION_PROMPT_TEMPLATE: str + + +class CompactChatForm(BaseModel): + model: str | None = None + + +def chat_search_content_text(text: str) -> str: + words = text.lower().strip().split(' ') + return ' '.join(word for word in words if not word.startswith(SEARCH_FILTER_PREFIXES)).strip() + + +def chat_search_snippet(chat: dict, search_text: str, max_length: int = 200) -> str | None: + if not search_text: + return None + + messages = chat.get('messages', []) + if isinstance(messages, dict): + messages = messages.values() + + for message in messages: + if not isinstance(message, dict): + continue + + content = message.get('content') + if not isinstance(content, str): + continue + + index = content.lower().find(search_text) + if index == -1: + continue + + start = max(index - max_length // 2, 0) + end = min(start + max_length, len(content)) + if index + len(search_text) > end: + end = min(index + len(search_text), len(content)) + start = max(end - max_length, 0) + + snippet = ' '.join(content[start:end].split()) + return f'{"..." if start else ""}{snippet}{"..." if end < len(content) else ""}' + + return None + + +async def get_chat_config_values() -> dict: + values = await Config.get_many(*CHAT_CONFIG_KEYS.values()) + return {field: values[storage_key] for field, storage_key in CHAT_CONFIG_KEYS.items() if storage_key in values} + + +def chat_config_updates(data: dict) -> dict: + return {CHAT_CONFIG_KEYS[field]: value for field, value in data.items() if field in CHAT_CONFIG_KEYS} + + +async def require_chat_import_permission(request: Request, user, db: AsyncSession): + if user.role != 'admin' and not await has_permission( + user.id, 'chat.import', await Config.get('user.permissions'), db=db + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + ############################ # GetChatList # Let the record outlive the session, so that what was @@ -400,7 +479,7 @@ async def export_chat_stats( user=Depends(get_verified_user), ): # Check if the user has permission to share/export chats - if (user.role != 'admin') and (not request.app.state.config.ENABLE_COMMUNITY_SHARING): + if (user.role != 'admin') and (not await Config.get('ui.enable_community_sharing')): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, @@ -449,7 +528,7 @@ async def export_single_chat_stats( Returns ChatStatsExport for the specified chat. """ # Check if the user has permission to share/export chats - if (user.role != 'admin') and (not request.app.state.config.ENABLE_COMMUNITY_SHARING): + if (user.role != 'admin') and (not await Config.get('ui.enable_community_sharing')): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, @@ -495,15 +574,21 @@ async def delete_all_user_chats( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if user.role == 'user' and not await has_permission( - user.id, 'chat.delete', request.app.state.config.USER_PERMISSIONS - ): + if user.role == 'user' and not await has_permission(user.id, 'chat.delete', await Config.get('user.permissions')): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) result = await Chats.delete_chats_by_user_id(user.id, db=db) + if result: + await publish_event( + request, + EVENTS.CHAT_DELETED_ALL, + actor=user, + subject_id=user.id, + subject_type='user', + ) return result @@ -550,6 +635,7 @@ async def get_user_chat_list_by_user_id( @router.post('/new', response_model=ChatResponse | None) async def create_new_chat( + request: Request, form_data: ChatForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), @@ -561,13 +647,23 @@ async def create_new_chat( # to assume the column is clean. Also catches non-UUID / nonexistent IDs. if form_data.folder_id is not None: if not await Folders.get_folder_by_id_and_user_id(form_data.folder_id, user.id, db=db): - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) + # Check shared folder write access + shared_folder = await Folders.get_folder_by_id(form_data.folder_id, db=db) + if not shared_folder or not await has_folder_access(user.id, shared_folder, 'write', db): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) try: chat = await Chats.insert_new_chat(str(uuid4()), user.id, form_data, db=db) + await publish_event( + request, + EVENTS.CHAT_CREATED, + actor=user, + subject_id=chat.id, + data={'title': chat.title, 'folder_id': chat.folder_id}, + ) return ChatResponse(**chat.model_dump()) except Exception as e: log.exception(e) @@ -581,18 +677,52 @@ async def create_new_chat( @router.post('/import', response_model=list[ChatResponse]) async def import_chats( + request: Request, form_data: ChatsImportForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await require_chat_import_permission(request, user, db) + try: chats = await Chats.import_chats(user.id, form_data.chats, db=db) + await publish_event( + request, + EVENTS.CHAT_IMPORTED, + actor=user, + subject_type='chat.import', + data={'count': len(chats), 'chat_ids': [chat.id for chat in chats]}, + ) return chats except Exception as e: log.exception(e) raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) +############################ +# ChatConfig +############################ + + +@router.get('/config', response_model=ChatConfigForm) +async def get_chat_config(user=Depends(get_admin_user)): + return await get_chat_config_values() + + +@router.post('/config', response_model=ChatConfigForm) +async def set_chat_config(form_data: ChatConfigForm, user=Depends(get_admin_user)): + threshold = max(1, int(form_data.CONTEXT_COMPACTION_TOKEN_THRESHOLD)) + await Config.upsert( + chat_config_updates( + { + **form_data.model_dump(), + 'CONTEXT_COMPACTION_TOKEN_THRESHOLD': threshold, + } + ) + ) + return await get_chat_config_values() + + ############################ # GetChats ############################ @@ -611,10 +741,10 @@ async def search_user_chats( limit = 60 skip = (page - 1) * limit - chat_list = [ - ChatTitleIdResponse(**chat.model_dump()) - for chat in await Chats.get_chats_by_user_id_and_search_text(user.id, text, skip=skip, limit=limit, db=db) - ] + search_text = chat_search_content_text(text) + chat_list = [] + for chat in await Chats.get_chats_by_user_id_and_search_text(user.id, text, skip=skip, limit=limit, db=db): + chat_list.append(ChatTitleIdResponse(**chat.model_dump(), snippet=chat_search_snippet(chat.chat, search_text))) # Delete tag if no chat is found words = text.strip().split(' ') @@ -800,14 +930,32 @@ async def get_archived_session_user_chat_list( ) +############################ +# GetArchivedChatsCount +############################ + + +@router.get('/archived/count', response_model=int) +async def get_archived_session_user_chat_count( + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + return await Chats.count_archived_chats_by_user_id(user.id, db=db) + + ############################ # ArchiveAllChats ############################ @router.post('/archive/all', response_model=bool) -async def archive_all_chats(user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): - return await Chats.archive_all_chats_by_user_id(user.id, db=db) +async def archive_all_chats( + request: Request, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): + result = await Chats.archive_all_chats_by_user_id(user.id, db=db) + if result: + await publish_event(request, EVENTS.CHAT_ARCHIVED, actor=user, subject_id=user.id, subject_type='user') + return result ############################ @@ -816,15 +964,48 @@ async def archive_all_chats(user=Depends(get_verified_user), db: AsyncSession = @router.post('/unarchive/all', response_model=bool) -async def unarchive_all_chats(user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): - return await Chats.unarchive_all_chats_by_user_id(user.id, db=db) +async def unarchive_all_chats( + request: Request, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): + result = await Chats.unarchive_all_chats_by_user_id(user.id, db=db) + if result: + await publish_event(request, EVENTS.CHAT_UNARCHIVED, actor=user, subject_id=user.id, subject_type='user') + return result ############################ -# GetSharedChats +# UnshareAllChats ############################ +@router.delete('/share/all', response_model=bool) +async def unshare_all_chats( + request: Request, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): + # Collect chat_ids that have shares so we can clear share_id and access grants + shared_list = await SharedChats.get_by_user_id(user.id, db=db) + chat_ids = [s.chat_id for s in shared_list] + + # Delete all shared_chat rows for this user + result = await SharedChats.delete_all_by_user_id(user.id, db=db) + + # Clear share_id on the original chats and remove access grants + for chat_id in chat_ids: + await Chats.update_chat_share_id_by_id(chat_id, None, db=db) + await AccessGrants.set_access_grants('shared_chat', chat_id, [], db=db) + + if result: + await publish_event( + request, + EVENTS.CHAT_UNSHARED, + actor=user, + subject_id=user.id, + subject_type='user', + data={'count': len(chat_ids), 'chat_ids': chat_ids}, + ) + return result + + @router.get('/shared', response_model=list[SharedChatResponse]) async def get_shared_session_user_chat_list( page: int | None = None, @@ -927,6 +1108,58 @@ async def get_user_chat_list_by_tag_name( return chats +############################ +# CompactChat +############################ + + +@router.post('/{id}/compact') +async def compact_chat_by_id( + request: Request, + id: str, + form_data: CompactChatForm | None = None, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) + if not chat: + raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND) + + if await has_active_tasks(request.app.state.redis, id): + raise HTTPException( + status_code=status.HTTP_409_CONFLICT, + detail='Wait for the current response to finish before compacting.', + ) + + if not request.app.state.MODELS: + await get_all_models(request, user=user) + + history = (chat.chat or {}).get('history') or {} + messages_map = await Chats.get_messages_map_by_chat_id(id) + message_list = get_message_list(messages_map or history.get('messages') or {}, history.get('currentId')) + model_id = (form_data.model if form_data else None) or next( + (message.get('model') for message in reversed(message_list) if message.get('model')), + None, + ) + + if not model_id: + chat_models = (chat.chat or {}).get('models') or [] + model_id = chat_models[0] if chat_models else None + if not model_id: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='No model found for context compaction.') + + result = await compact_chat_branch(request, user, chat, model_id, request.app.state.MODELS) + if result.get('compacted'): + await publish_event( + request, + EVENTS.CHAT_COMPACTED, + actor=user, + subject_id=id, + data={'dropped_messages': result.get('dropped_messages')}, + ) + return result + + ############################ # GetChatById ############################ @@ -951,6 +1184,14 @@ async def get_chat_by_id(id: str, user=Depends(get_verified_user), db: AsyncSess if has_grant: chat = await Chats.get_chat_by_id(id, db=db) + # Check folder-based access (shared folders) + if not chat: + candidate = await Chats.get_chat_by_id(id, db=db) + if candidate and candidate.folder_id: + folder = await Folders.get_folder_by_id(candidate.folder_id, db=db) + if folder and await has_folder_access(user.id, folder, 'read', db): + chat = candidate + if chat: return ChatResponse(**chat.model_dump()) @@ -964,6 +1205,7 @@ async def get_chat_by_id(id: str, user=Depends(get_verified_user), db: AsyncSess @router.post('/{id}', response_model=ChatResponse | None) async def update_chat_by_id( + request: Request, id: str, form_data: ChatForm, user=Depends(get_verified_user), @@ -972,26 +1214,27 @@ async def update_chat_by_id( chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) if chat: updated_chat = {**chat.chat, **form_data.chat} - - # Re-derive content from output for assistant messages so that frontend - # edits to output items are reflected in content. Only when output - # actually changed — otherwise content set independently of output - # (e.g. a `replace` event or an outlet filter footer) would be reverted. - existing_messages = (chat.chat.get('history') or {}).get('messages') or {} - for msg_id, msg in updated_chat.get('history', {}).get('messages', {}).items(): - if msg.get('role') == 'assistant' and msg.get('output'): - if msg.get('output') != existing_messages.get(msg_id, {}).get('output'): - msg['content'] = serialize_output(msg['output']) + if 'history' in form_data.chat: + updated_chat['history'] = Chats.merge_history( + chat.chat.get('history'), + form_data.chat.get('history'), + ) chat = await Chats.update_chat_by_id(id, updated_chat, db=db) - # Reconcile chat_message rows with the committed blob. - # This is the only caller where the frontend pushes a full - # history with potential edits, deletions, or new branches. + # Reconcile chat_message rows without inferring deletes from missing IDs. + # Message deletion has its own endpoint below. messages = (updated_chat.get('history') or {}).get('messages') or {} if messages: await Chats.reconcile_messages_by_chat_id(id, user.id, messages) + await publish_event( + request, + EVENTS.CHAT_UPDATED, + actor=user, + subject_id=id, + data={'title': chat.title}, + ) return ChatResponse(**chat.model_dump()) else: raise HTTPException( @@ -1009,6 +1252,7 @@ class MessageForm(BaseModel): @router.post('/{id}/messages/{message_id}', response_model=ChatResponse | None) async def update_chat_message_by_id( + request: Request, id: str, message_id: str, form_data: MessageForm, @@ -1058,6 +1302,52 @@ async def update_chat_message_by_id( } ) + await publish_event( + request, + EVENTS.MESSAGE_UPDATED, + actor=user, + subject_id=message_id, + data={'chat_id': id, 'content_preview': form_data.content[:300]}, + ) + return ChatResponse(**chat.model_dump()) + + +@router.delete('/{id}/messages/{message_id}', response_model=ChatResponse | None) +async def delete_chat_message_by_id( + request: Request, + id: str, + message_id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + chat = await Chats.get_chat_by_id(id, db=db) + + if not chat: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if chat.user_id != user.id and user.role != 'admin': + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + chat = await Chats.delete_message_from_chat_by_id_and_message_id(id, message_id) + if not chat: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + await publish_event( + request, + EVENTS.MESSAGE_DELETED, + actor=user, + subject_id=message_id, + data={'chat_id': id}, + ) return ChatResponse(**chat.model_dump()) @@ -1071,6 +1361,7 @@ class EventForm(BaseModel): @router.post('/{id}/messages/{message_id}/event', response_model=bool | None) async def send_chat_message_event_by_id( + request: Request, id: str, message_id: str, form_data: EventForm, @@ -1104,6 +1395,13 @@ async def send_chat_message_event_by_id( await event_emitter(form_data.model_dump()) else: return False + await publish_event( + request, + EVENTS.MESSAGE_EVENT_RECEIVED, + actor=user, + subject_id=message_id, + data={'chat_id': id, 'event_type': form_data.type}, + ) return True except Exception: return False @@ -1136,9 +1434,17 @@ async def delete_chat_by_id( result = await Chats.delete_chat_by_id(id, db=db) + if result: + await publish_event( + request, + EVENTS.CHAT_DELETED, + actor=user, + subject_id=id, + data={'owner_id': chat.user_id}, + ) return result else: - if not await has_permission(user.id, 'chat.delete', request.app.state.config.USER_PERMISSIONS): + if not await has_permission(user.id, 'chat.delete', await Config.get('user.permissions')): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, @@ -1153,6 +1459,14 @@ async def delete_chat_by_id( await Chats.delete_orphan_tags_for_user(chat.meta.get('tags', []), user.id, threshold=1, db=db) result = await Chats.delete_chat_by_id_and_user_id(id, user.id, db=db) + if result: + await publish_event( + request, + EVENTS.CHAT_DELETED, + actor=user, + subject_id=id, + data={'owner_id': user.id}, + ) return result @@ -1178,10 +1492,19 @@ async def get_pinned_status_by_id( @router.post('/{id}/pin', response_model=ChatResponse | None) -async def pin_chat_by_id(id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +async def pin_chat_by_id( + request: Request, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) if chat: chat = await Chats.toggle_chat_pinned_by_id(id, db=db) + await publish_event( + request, + EVENTS.CHAT_PINNED if chat.pinned else EVENTS.CHAT_UNPINNED, + actor=user, + subject_id=id, + subject_type='chat', + ) return chat else: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()) @@ -1198,11 +1521,14 @@ class CloneForm(BaseModel): @router.post('/{id}/clone', response_model=ChatResponse | None) async def clone_chat_by_id( + request: Request, form_data: CloneForm, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await require_chat_import_permission(request, user, db) + chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) if chat: updated_chat = { @@ -1229,6 +1555,13 @@ async def clone_chat_by_id( if chats: chat = chats[0] + await publish_event( + request, + EVENTS.CHAT_CLONED, + actor=user, + subject_id=chat.id, + data={'original_chat_id': id}, + ) return ChatResponse(**chat.model_dump()) else: raise HTTPException( @@ -1246,8 +1579,13 @@ async def clone_chat_by_id( @router.post('/{id}/clone/shared', response_model=ChatResponse | None) async def clone_shared_chat_by_id( - id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, + id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), ): + await require_chat_import_permission(request, user, db) + chat = await Chats.get_chat_by_share_id(id, db=db) # Fallback: admins can also access any chat directly by chat ID @@ -1334,6 +1672,13 @@ async def archive_chat_by_id( # Unarchived — ensure tag rows exist await Tags.ensure_tags_exist(tag_ids, user.id, db=db) + await publish_event( + request, + EVENTS.CHAT_ARCHIVED if chat.archived else EVENTS.CHAT_UNARCHIVED, + actor=user, + subject_id=id, + subject_type='chat', + ) return ChatResponse(**chat.model_dump()) else: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()) @@ -1349,9 +1694,7 @@ async def share_chat_by_id( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if user.role != 'admin' and not await has_permission( - user.id, 'chat.share', request.app.state.config.USER_PERMISSIONS - ): + if user.role != 'admin' and not await has_permission(user.id, 'chat.share', await Config.get('user.permissions')): raise HTTPException(status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED) chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) @@ -1363,6 +1706,13 @@ async def share_chat_by_id( shared = await SharedChats.update(chat.share_id, db=db) if shared: chat = await Chats.get_chat_by_id(id, db=db) + await publish_event( + request, + EVENTS.CHAT_SHARED, + actor=user, + subject_id=id, + data={'share_id': chat.share_id, 'updated': True}, + ) return ChatResponse(**chat.model_dump()) # Create a new share @@ -1374,6 +1724,13 @@ async def share_chat_by_id( if not chat: raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, detail=ERROR_MESSAGES.DEFAULT()) + await publish_event( + request, + EVENTS.CHAT_SHARED, + actor=user, + subject_id=id, + data={'share_id': shared.id}, + ) return ChatResponse(**chat.model_dump()) @@ -1382,19 +1739,26 @@ async def share_chat_by_id( @router.delete('/{id}/share', response_model=bool | None) async def delete_shared_chat_by_id( - id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) ): chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) if not chat: raise HTTPException(status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.ACCESS_PROHIBITED) - if not chat.share_id: - return False - await SharedChats.delete_by_chat_id(id, db=db) - await Chats.update_chat_share_id_by_id(id, None, db=db) + + if chat.share_id: + await Chats.update_chat_share_id_by_id(id, None, db=db) + await AccessGrants.set_access_grants('shared_chat', id, [], db=db) + await publish_event( + request, + EVENTS.CHAT_UNSHARED, + actor=user, + subject_id=id, + data={'share_id': chat.share_id}, + ) return True @@ -1426,7 +1790,7 @@ async def update_shared_chat_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -1482,6 +1846,7 @@ class ChatFolderIdForm(BaseModel): @router.post('/{id}/folder', response_model=ChatResponse | None) async def update_chat_folder_id_by_id( + request: Request, id: str, form_data: ChatFolderIdForm, user=Depends(get_verified_user), @@ -1493,12 +1858,22 @@ async def update_chat_folder_id_by_id( # folder_id values. None is allowed (moves the chat out of any folder). if form_data.folder_id is not None: if not await Folders.get_folder_by_id_and_user_id(form_data.folder_id, user.id, db=db): - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) + # Check shared folder write access + shared_folder = await Folders.get_folder_by_id(form_data.folder_id, db=db) + if not shared_folder or not await has_folder_access(user.id, shared_folder, 'write', db): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) chat = await Chats.update_chat_folder_id_by_id_and_user_id(id, user.id, form_data.folder_id, db=db) + await publish_event( + request, + EVENTS.CHAT_FOLDER_UPDATED, + actor=user, + subject_id=id, + data={'folder_id': form_data.folder_id}, + ) return ChatResponse(**chat.model_dump()) else: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.DEFAULT()) @@ -1526,6 +1901,7 @@ async def get_chat_tags_by_id(id: str, user=Depends(get_verified_user), db: Asyn @router.post('/{id}/tags', response_model=list[TagModel]) async def add_tag_by_id_and_tag_name( + request: Request, id: str, form_data: TagForm, user=Depends(get_verified_user), @@ -1544,6 +1920,13 @@ async def add_tag_by_id_and_tag_name( if tag_id not in tags: await Chats.add_chat_tag_by_id_and_user_id_and_tag_name(id, user.id, form_data.name, db=db) + await publish_event( + request, + EVENTS.CHAT_TAG_ADDED, + actor=user, + subject_id=id, + data={'tag': form_data.name}, + ) chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) tags = chat.meta.get('tags', []) @@ -1559,6 +1942,7 @@ async def add_tag_by_id_and_tag_name( @router.delete('/{id}/tags', response_model=list[TagModel]) async def delete_tag_by_id_and_tag_name( + request: Request, id: str, form_data: TagForm, user=Depends(get_verified_user), @@ -1567,6 +1951,13 @@ async def delete_tag_by_id_and_tag_name( chat = await Chats.get_chat_by_id_and_user_id(id, user.id, db=db) if chat: await Chats.delete_tag_by_id_and_user_id_and_tag_name(id, user.id, form_data.name, db=db) + await publish_event( + request, + EVENTS.CHAT_TAG_REMOVED, + actor=user, + subject_id=id, + data={'tag': form_data.name}, + ) if await Chats.count_chats_by_tag_name_and_user_id(form_data.name, user.id, db=db) == 0: await Tags.delete_tag_by_name_and_user_id(form_data.name, user.id, db=db) diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py index c40131f41f..533c1bd27f 100644 --- a/backend/open_webui/routers/configs.py +++ b/backend/open_webui/routers/configs.py @@ -7,22 +7,27 @@ from typing import Optional import aiohttp from fastapi import APIRouter, Depends, HTTPException, Request from mcp.shared.auth import OAuthMetadata -from open_webui.config import BannerModel, async_save_config, get_config, save_config +from open_webui.config import BannerModel from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT +from open_webui.events import EVENTS, publish_event +from open_webui.models.config import Config from open_webui.models.oauth_sessions import OAuthSessions from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.headers import get_custom_headers from open_webui.utils.mcp.client import MCPClient from open_webui.utils.oauth import ( OAuthClientInformationFull, + apply_connection_oauth_options, decrypt_data, encrypt_data, get_discovery_urls, get_oauth_client_info_with_dynamic_client_registration, get_oauth_client_info_with_static_credentials, + recover_static_oauth_client_metadata, resolve_oauth_client_info, ) from open_webui.utils.tools import ( + bearer_auth_header, get_tool_server_data, get_tool_server_url, set_terminal_servers, @@ -34,6 +39,44 @@ router = APIRouter() log = logging.getLogger(__name__) +CONNECTIONS_CONFIG_KEYS = { + 'ENABLE_DIRECT_CONNECTIONS': 'direct.enable', + 'ENABLE_BASE_MODELS_CACHE': 'models.base_models_cache', +} +CODE_EXECUTION_CONFIG_KEYS = { + 'ENABLE_CODE_EXECUTION': 'code_execution.enable', + 'CODE_EXECUTION_ENGINE': 'code_execution.engine', + 'CODE_EXECUTION_JUPYTER_URL': 'code_execution.jupyter.url', + 'CODE_EXECUTION_JUPYTER_AUTH': 'code_execution.jupyter.auth', + 'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': 'code_execution.jupyter.auth_token', + 'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': 'code_execution.jupyter.auth_password', + 'CODE_EXECUTION_JUPYTER_TIMEOUT': 'code_execution.jupyter.timeout', + 'ENABLE_CODE_INTERPRETER': 'code_interpreter.enable', + 'CODE_INTERPRETER_ENGINE': 'code_interpreter.engine', + 'CODE_INTERPRETER_PROMPT_TEMPLATE': 'code_interpreter.prompt_template', + 'CODE_INTERPRETER_JUPYTER_URL': 'code_interpreter.jupyter.url', + 'CODE_INTERPRETER_JUPYTER_AUTH': 'code_interpreter.jupyter.auth', + 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': 'code_interpreter.jupyter.auth_token', + 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': 'code_interpreter.jupyter.auth_password', + 'CODE_INTERPRETER_JUPYTER_TIMEOUT': 'code_interpreter.jupyter.timeout', +} +MODELS_CONFIG_KEYS = { + 'DEFAULT_MODELS': 'ui.default_models', + 'DEFAULT_PINNED_MODELS': 'ui.default_pinned_models', + 'MODEL_ORDER_LIST': 'ui.model_order_list', + 'DEFAULT_MODEL_METADATA': 'models.default_metadata', + 'DEFAULT_MODEL_PARAMS': 'models.default_params', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +def config_updates(data: dict, key_map: dict[str, str]) -> dict: + return {key_map[field]: value for field, value in data.items() if field in key_map} + ############################ # ImportConfig @@ -48,9 +91,15 @@ class ImportConfigForm(BaseModel): @router.post('/import', response_model=dict) async def import_config(request: Request, form_data: ImportConfigForm, user=Depends(get_admin_user)): - await async_save_config(form_data.config) - request.app.state.config._sync_to_redis() - return get_config() + await Config.upsert(form_data.config) + await publish_event( + request, + EVENTS.CONFIG_IMPORTED, + actor=user, + subject_id='import', + data={'keys': list(form_data.config.keys())}, + ) + return await Config.get_all() ############################ @@ -60,7 +109,12 @@ async def import_config(request: Request, form_data: ImportConfigForm, user=Depe @router.get('/export', response_model=dict) async def export_config(user=Depends(get_admin_user)): - return get_config() + return await Config.get_all() + + +@router.get('/namespace/{namespace}', response_model=dict) +async def get_config_namespace(namespace: str, user=Depends(get_admin_user)): + return await Config.get_namespace(namespace) ############################ @@ -75,10 +129,7 @@ class ConnectionsConfigForm(BaseModel): @router.get('/connections', response_model=ConnectionsConfigForm) async def get_connections_config(request: Request, user=Depends(get_admin_user)): - return { - 'ENABLE_DIRECT_CONNECTIONS': request.app.state.config.ENABLE_DIRECT_CONNECTIONS, - 'ENABLE_BASE_MODELS_CACHE': request.app.state.config.ENABLE_BASE_MODELS_CACHE, - } + return await get_config_values(CONNECTIONS_CONFIG_KEYS) @router.post('/connections', response_model=ConnectionsConfigForm) @@ -87,13 +138,17 @@ async def set_connections_config( form_data: ConnectionsConfigForm, user=Depends(get_admin_user), ): - request.app.state.config.ENABLE_DIRECT_CONNECTIONS = form_data.ENABLE_DIRECT_CONNECTIONS - request.app.state.config.ENABLE_BASE_MODELS_CACHE = form_data.ENABLE_BASE_MODELS_CACHE - - return { - 'ENABLE_DIRECT_CONNECTIONS': request.app.state.config.ENABLE_DIRECT_CONNECTIONS, - 'ENABLE_BASE_MODELS_CACHE': request.app.state.config.ENABLE_BASE_MODELS_CACHE, - } + await Config.upsert(config_updates(form_data.model_dump(), CONNECTIONS_CONFIG_KEYS)) + values = await get_config_values(CONNECTIONS_CONFIG_KEYS) + await publish_event( + request, + EVENTS.CONFIG_CONNECTIONS_UPDATED, + actor=user, + subject_id='connections', + subject_type='config', + data=values, + ) + return values class OAuthClientRegistrationForm(BaseModel): @@ -102,6 +157,7 @@ class OAuthClientRegistrationForm(BaseModel): client_name: str | None = None client_secret: str | None = None oauth_server_url: str | None = None + oauth_scope: str | None = None @router.post('/oauth/clients/register') @@ -126,10 +182,11 @@ async def register_oauth_client( oauth_server_url, oauth_client_id=form_data.client_id, oauth_client_secret=form_data.client_secret, + oauth_scope=form_data.oauth_scope, ) else: oauth_client_info = await get_oauth_client_info_with_dynamic_client_registration( - request, oauth_client_id, oauth_server_url + request, oauth_client_id, oauth_server_url, oauth_scope=form_data.oauth_scope ) return { 'status': True, @@ -167,9 +224,7 @@ class ToolServersConfigForm(BaseModel): @router.get('/tool_servers', response_model=ToolServersConfigForm) async def get_tool_servers_config(request: Request, user=Depends(get_admin_user)): - return { - 'TOOL_SERVER_CONNECTIONS': request.app.state.config.TOOL_SERVER_CONNECTIONS, - } + return {'TOOL_SERVER_CONNECTIONS': await Config.get('tool_server.connections')} @router.post('/tool_servers', response_model=ToolServersConfigForm) @@ -178,13 +233,14 @@ async def set_tool_servers_config( form_data: ToolServersConfigForm, user=Depends(get_admin_user), ): - for connection in request.app.state.config.TOOL_SERVER_CONNECTIONS: + existing_connections = await Config.get('tool_server.connections', []) or [] + for connection in existing_connections: server_type = connection.get('type', 'openapi') auth_type = connection.get('auth_type', 'none') if auth_type in ('oauth_2.1', 'oauth_2.1_static'): # Remove existing OAuth clients for tool servers - server_id = connection.get('info', {}).get('id') + server_id = (connection.get('info') or {}).get('id') client_key = f'{server_type}:{server_id}' try: @@ -193,21 +249,22 @@ async def set_tool_servers_config( pass # Set new tool server connections - request.app.state.config.TOOL_SERVER_CONNECTIONS = [ - connection.model_dump() for connection in form_data.TOOL_SERVER_CONNECTIONS - ] + connections = [connection.model_dump() for connection in form_data.TOOL_SERVER_CONNECTIONS] + await Config.upsert({'tool_server.connections': connections}) await set_tool_servers(request) - for connection in request.app.state.config.TOOL_SERVER_CONNECTIONS: + for connection in connections: server_type = connection.get('type', 'openapi') if server_type == 'mcp': - server_id = connection.get('info', {}).get('id') + server_id = (connection.get('info') or {}).get('id') auth_type = connection.get('auth_type', 'none') if auth_type in ('oauth_2.1', 'oauth_2.1_static') and server_id: try: oauth_client_info = resolve_oauth_client_info(connection) + oauth_client_info = await recover_static_oauth_client_metadata(connection, oauth_client_info) + oauth_client_info = apply_connection_oauth_options(connection, oauth_client_info) request.app.state.oauth_client_manager.add_client( f'{server_type}:{server_id}', OAuthClientInformationFull(**oauth_client_info), @@ -216,9 +273,15 @@ async def set_tool_servers_config( log.debug(f'Failed to add OAuth client for MCP tool server: {e}') continue - return { - 'TOOL_SERVER_CONNECTIONS': request.app.state.config.TOOL_SERVER_CONNECTIONS, - } + await publish_event( + request, + EVENTS.CONFIG_TOOL_SERVERS_UPDATED, + actor=user, + subject_id='tool_server.connections', + subject_type='config', + data={'count': len(connections), 'types': [connection.get('type', 'openapi') for connection in connections]}, + ) + return {'TOOL_SERVER_CONNECTIONS': connections} class TerminalServerConnection(BaseModel): @@ -249,9 +312,7 @@ class TerminalServersConfigForm(BaseModel): @router.get('/terminal_servers') async def get_terminal_servers_config(request: Request, user=Depends(get_admin_user)): - return { - 'TERMINAL_SERVER_CONNECTIONS': request.app.state.config.TERMINAL_SERVER_CONNECTIONS, - } + return {'TERMINAL_SERVER_CONNECTIONS': await Config.get('terminal_server.connections')} @router.post('/terminal_servers') @@ -260,15 +321,20 @@ async def set_terminal_servers_config( form_data: TerminalServersConfigForm, user=Depends(get_admin_user), ): - request.app.state.config.TERMINAL_SERVER_CONNECTIONS = [ - connection.model_dump() for connection in form_data.TERMINAL_SERVER_CONNECTIONS - ] + connections = [connection.model_dump() for connection in form_data.TERMINAL_SERVER_CONNECTIONS] + await Config.upsert({'terminal_server.connections': connections}) await set_terminal_servers(request) - return { - 'TERMINAL_SERVER_CONNECTIONS': request.app.state.config.TERMINAL_SERVER_CONNECTIONS, - } + await publish_event( + request, + EVENTS.CONFIG_TERMINAL_SERVERS_UPDATED, + actor=user, + subject_id='terminal_server.connections', + subject_type='config', + data={'count': len(connections)}, + ) + return {'TERMINAL_SERVER_CONNECTIONS': connections} @router.post('/terminal_servers/verify') @@ -287,7 +353,7 @@ async def verify_terminal_server_connection( headers = {} if form_data.auth_type == 'bearer' and form_data.key: - headers['Authorization'] = f'Bearer {form_data.key}' + headers.update(bearer_auth_header(form_data.key)) try: async with aiohttp.ClientSession( @@ -328,6 +394,24 @@ class TerminalServerPolicyForm(BaseModel): policy_data: dict +class TerminalServerLifecycleForm(BaseModel): + url: str + key: str | None = '' + auth_type: str | None = 'bearer' + policy_id: str + lifecycle_data: dict + + +class TerminalServerRefreshForm(BaseModel): + url: str + key: str | None = '' + auth_type: str | None = 'bearer' + user_id: str | None = None + policy_id: str | None = None + only_idle: bool = True + reset: bool = False + + @router.post('/terminal_servers/policy') async def put_terminal_server_policy( request: Request, form_data: TerminalServerPolicyForm, user=Depends(get_admin_user) @@ -341,7 +425,7 @@ async def put_terminal_server_policy( headers = {'Content-Type': 'application/json'} if form_data.auth_type == 'bearer' and form_data.key: - headers['Authorization'] = f'Bearer {form_data.key}' + headers.update(bearer_auth_header(form_data.key)) try: async with aiohttp.ClientSession( @@ -363,6 +447,91 @@ async def put_terminal_server_policy( raise HTTPException(status_code=400, detail='Failed to save policy to terminal server') +@router.post('/terminal_servers/lifecycle') +async def put_terminal_server_lifecycle( + request: Request, form_data: TerminalServerLifecycleForm, user=Depends(get_admin_user) +): + """ + Proxy a policy lifecycle PUT to an orchestrator terminal server. + """ + base_url = (form_data.url or '').rstrip('/') + if not base_url: + raise HTTPException(status_code=400, detail='Terminal server URL is required') + + headers = {'Content-Type': 'application/json'} + if form_data.auth_type == 'bearer' and form_data.key: + headers.update(bearer_auth_header(form_data.key)) + + try: + async with aiohttp.ClientSession( + trust_env=True, + timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT), + ) as session: + lifecycle_url = f'{base_url}/api/v1/policies/{form_data.policy_id}/lifecycle' + async with session.put( + lifecycle_url, + headers=headers, + json=form_data.lifecycle_data, + ssl=AIOHTTP_CLIENT_SESSION_SSL, + ) as resp: + if resp.ok: + return await resp.json() + detail = await resp.text() + raise HTTPException(status_code=resp.status, detail=detail) + except HTTPException: + raise + except Exception as e: + log.debug(f'Failed to save lifecycle to terminal server: {e}') + raise HTTPException(status_code=400, detail='Failed to save lifecycle to terminal server') + + +@router.post('/terminal_servers/refresh') +async def refresh_terminal_server_terminals( + request: Request, form_data: TerminalServerRefreshForm, user=Depends(get_admin_user) +): + """ + Proxy a terminal refresh request to an orchestrator terminal server. + """ + base_url = (form_data.url or '').rstrip('/') + if not base_url: + raise HTTPException(status_code=400, detail='Terminal server URL is required') + + headers = {'Content-Type': 'application/json'} + if form_data.auth_type == 'bearer' and form_data.key: + headers.update(bearer_auth_header(form_data.key)) + + body = { + 'only_idle': form_data.only_idle, + 'reset': form_data.reset, + } + if form_data.user_id: + body['user_id'] = form_data.user_id + if form_data.policy_id: + body['policy_id'] = form_data.policy_id + + try: + async with aiohttp.ClientSession( + trust_env=True, + timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT), + ) as session: + refresh_url = f'{base_url}/api/v1/terminals/refresh' + async with session.post( + refresh_url, + headers=headers, + json=body, + ssl=AIOHTTP_CLIENT_SESSION_SSL, + ) as resp: + if resp.ok: + return await resp.json() + detail = await resp.text() + raise HTTPException(status_code=resp.status, detail=detail) + except HTTPException: + raise + except Exception as e: + log.debug(f'Failed to refresh terminals: {e}') + raise HTTPException(status_code=400, detail='Failed to refresh terminals') + + @router.post('/tool_servers/verify') async def verify_tool_servers_config(request: Request, form_data: ToolServerConnection, user=Depends(get_admin_user)): """ @@ -518,67 +687,29 @@ class CodeInterpreterConfigForm(BaseModel): @router.get('/code_execution', response_model=CodeInterpreterConfigForm) async def get_code_execution_config(request: Request, user=Depends(get_admin_user)): - return { - 'ENABLE_CODE_EXECUTION': request.app.state.config.ENABLE_CODE_EXECUTION, - 'CODE_EXECUTION_ENGINE': request.app.state.config.CODE_EXECUTION_ENGINE, - 'CODE_EXECUTION_JUPYTER_URL': request.app.state.config.CODE_EXECUTION_JUPYTER_URL, - 'CODE_EXECUTION_JUPYTER_AUTH': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH, - 'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN, - 'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD, - 'CODE_EXECUTION_JUPYTER_TIMEOUT': request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT, - 'ENABLE_CODE_INTERPRETER': request.app.state.config.ENABLE_CODE_INTERPRETER, - 'CODE_INTERPRETER_ENGINE': request.app.state.config.CODE_INTERPRETER_ENGINE, - 'CODE_INTERPRETER_PROMPT_TEMPLATE': request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE, - 'CODE_INTERPRETER_JUPYTER_URL': request.app.state.config.CODE_INTERPRETER_JUPYTER_URL, - 'CODE_INTERPRETER_JUPYTER_AUTH': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH, - 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN, - 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD, - 'CODE_INTERPRETER_JUPYTER_TIMEOUT': request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT, - } + return await get_config_values(CODE_EXECUTION_CONFIG_KEYS) @router.post('/code_execution', response_model=CodeInterpreterConfigForm) async def set_code_execution_config( request: Request, form_data: CodeInterpreterConfigForm, user=Depends(get_admin_user) ): - request.app.state.config.ENABLE_CODE_EXECUTION = form_data.ENABLE_CODE_EXECUTION - - request.app.state.config.CODE_EXECUTION_ENGINE = form_data.CODE_EXECUTION_ENGINE - request.app.state.config.CODE_EXECUTION_JUPYTER_URL = form_data.CODE_EXECUTION_JUPYTER_URL - request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH = form_data.CODE_EXECUTION_JUPYTER_AUTH - request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN = form_data.CODE_EXECUTION_JUPYTER_AUTH_TOKEN - request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD = form_data.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD - request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT = form_data.CODE_EXECUTION_JUPYTER_TIMEOUT - - request.app.state.config.ENABLE_CODE_INTERPRETER = form_data.ENABLE_CODE_INTERPRETER - request.app.state.config.CODE_INTERPRETER_ENGINE = form_data.CODE_INTERPRETER_ENGINE - request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE = form_data.CODE_INTERPRETER_PROMPT_TEMPLATE - - request.app.state.config.CODE_INTERPRETER_JUPYTER_URL = form_data.CODE_INTERPRETER_JUPYTER_URL - - request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH = form_data.CODE_INTERPRETER_JUPYTER_AUTH - - request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN = form_data.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN - request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD = form_data.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD - request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT = form_data.CODE_INTERPRETER_JUPYTER_TIMEOUT - - return { - 'ENABLE_CODE_EXECUTION': request.app.state.config.ENABLE_CODE_EXECUTION, - 'CODE_EXECUTION_ENGINE': request.app.state.config.CODE_EXECUTION_ENGINE, - 'CODE_EXECUTION_JUPYTER_URL': request.app.state.config.CODE_EXECUTION_JUPYTER_URL, - 'CODE_EXECUTION_JUPYTER_AUTH': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH, - 'CODE_EXECUTION_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN, - 'CODE_EXECUTION_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD, - 'CODE_EXECUTION_JUPYTER_TIMEOUT': request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT, - 'ENABLE_CODE_INTERPRETER': request.app.state.config.ENABLE_CODE_INTERPRETER, - 'CODE_INTERPRETER_ENGINE': request.app.state.config.CODE_INTERPRETER_ENGINE, - 'CODE_INTERPRETER_PROMPT_TEMPLATE': request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE, - 'CODE_INTERPRETER_JUPYTER_URL': request.app.state.config.CODE_INTERPRETER_JUPYTER_URL, - 'CODE_INTERPRETER_JUPYTER_AUTH': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH, - 'CODE_INTERPRETER_JUPYTER_AUTH_TOKEN': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN, - 'CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD': request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD, - 'CODE_INTERPRETER_JUPYTER_TIMEOUT': request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT, - } + await Config.upsert(config_updates(form_data.model_dump(), CODE_EXECUTION_CONFIG_KEYS)) + values = await get_config_values(CODE_EXECUTION_CONFIG_KEYS) + await publish_event( + request, + EVENTS.CONFIG_CODE_EXECUTION_UPDATED, + actor=user, + subject_id='code_execution', + subject_type='config', + data={ + 'code_execution_enabled': values.get('ENABLE_CODE_EXECUTION'), + 'code_execution_engine': values.get('CODE_EXECUTION_ENGINE'), + 'code_interpreter_enabled': values.get('ENABLE_CODE_INTERPRETER'), + 'code_interpreter_engine': values.get('CODE_INTERPRETER_ENGINE'), + }, + ) + return values ############################ @@ -595,35 +726,32 @@ class ModelsConfigForm(BaseModel): @router.get('/models/defaults') async def get_models_defaults(request: Request, user=Depends(get_verified_user)): return { - 'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA, + 'DEFAULT_MODEL_METADATA': await Config.get('models.default_metadata'), } @router.get('/models', response_model=ModelsConfigForm) async def get_models_config(request: Request, user=Depends(get_admin_user)): - return { - 'DEFAULT_MODELS': request.app.state.config.DEFAULT_MODELS, - 'DEFAULT_PINNED_MODELS': request.app.state.config.DEFAULT_PINNED_MODELS, - 'MODEL_ORDER_LIST': request.app.state.config.MODEL_ORDER_LIST, - 'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA, - 'DEFAULT_MODEL_PARAMS': request.app.state.config.DEFAULT_MODEL_PARAMS, - } + return await get_config_values(MODELS_CONFIG_KEYS) @router.post('/models', response_model=ModelsConfigForm) async def set_models_config(request: Request, form_data: ModelsConfigForm, user=Depends(get_admin_user)): - request.app.state.config.DEFAULT_MODELS = form_data.DEFAULT_MODELS - request.app.state.config.DEFAULT_PINNED_MODELS = form_data.DEFAULT_PINNED_MODELS - request.app.state.config.MODEL_ORDER_LIST = form_data.MODEL_ORDER_LIST - request.app.state.config.DEFAULT_MODEL_METADATA = form_data.DEFAULT_MODEL_METADATA - request.app.state.config.DEFAULT_MODEL_PARAMS = form_data.DEFAULT_MODEL_PARAMS - return { - 'DEFAULT_MODELS': request.app.state.config.DEFAULT_MODELS, - 'DEFAULT_PINNED_MODELS': request.app.state.config.DEFAULT_PINNED_MODELS, - 'MODEL_ORDER_LIST': request.app.state.config.MODEL_ORDER_LIST, - 'DEFAULT_MODEL_METADATA': request.app.state.config.DEFAULT_MODEL_METADATA, - 'DEFAULT_MODEL_PARAMS': request.app.state.config.DEFAULT_MODEL_PARAMS, - } + await Config.upsert(config_updates(form_data.model_dump(), MODELS_CONFIG_KEYS)) + values = await get_config_values(MODELS_CONFIG_KEYS) + await publish_event( + request, + EVENTS.CONFIG_MODELS_UPDATED, + actor=user, + subject_id='models', + subject_type='config', + data={ + 'default_models': values.get('DEFAULT_MODELS'), + 'default_pinned_models': values.get('DEFAULT_PINNED_MODELS'), + 'model_order_count': len(values.get('MODEL_ORDER_LIST') or []), + }, + ) + return values class PromptSuggestion(BaseModel): @@ -642,8 +770,17 @@ async def set_default_suggestions( user=Depends(get_admin_user), ): data = form_data.model_dump() - request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS = data['suggestions'] - return request.app.state.config.DEFAULT_PROMPT_SUGGESTIONS + await Config.upsert({'ui.prompt_suggestions': data['suggestions']}) + suggestions = await Config.get('ui.prompt_suggestions') + await publish_event( + request, + EVENTS.CONFIG_SUGGESTIONS_UPDATED, + actor=user, + subject_id='ui.prompt_suggestions', + subject_type='config', + data={'count': len(suggestions or [])}, + ) + return suggestions ############################ @@ -662,8 +799,17 @@ async def set_banners( user=Depends(get_admin_user), ): data = form_data.model_dump() - request.app.state.config.BANNERS = data['banners'] - return request.app.state.config.BANNERS + await Config.upsert({'ui.banners': data['banners']}) + banners = await Config.get('ui.banners') + await publish_event( + request, + EVENTS.CONFIG_BANNERS_UPDATED, + actor=user, + subject_id='ui.banners', + subject_type='config', + data={'count': len(banners or [])}, + ) + return banners @router.get('/banners', response_model=list[BannerModel]) @@ -671,4 +817,4 @@ async def get_banners( request: Request, user=Depends(get_verified_user), ): - return request.app.state.config.BANNERS + return await Config.get('ui.banners') diff --git a/backend/open_webui/routers/evaluations.py b/backend/open_webui/routers/evaluations.py index d1c914f4ee..fd18843435 100644 --- a/backend/open_webui/routers/evaluations.py +++ b/backend/open_webui/routers/evaluations.py @@ -4,7 +4,9 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from fastapi.concurrency import run_in_threadpool from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session +from open_webui.models.config import Config from open_webui.models.feedbacks import ( FeedbackForm, FeedbackIdResponse, @@ -25,6 +27,16 @@ log = logging.getLogger(__name__) router = APIRouter() +EVALUATION_CONFIG_KEYS = { + 'ENABLE_EVALUATION_ARENA_MODELS': 'evaluation.arena.enable', + 'EVALUATION_ARENA_MODELS': 'evaluation.arena.models', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + # Leaderboard Elo Rating Computation # The judgment has already been rendered with grace; @@ -255,10 +267,7 @@ async def get_model_history( @router.get('/config') async def get_config(request: Request, user=Depends(get_admin_user)): - return { - 'ENABLE_EVALUATION_ARENA_MODELS': request.app.state.config.ENABLE_EVALUATION_ARENA_MODELS, - 'EVALUATION_ARENA_MODELS': request.app.state.config.EVALUATION_ARENA_MODELS, - } + return await get_config_values(EVALUATION_CONFIG_KEYS) ############################ @@ -277,15 +286,25 @@ async def update_config( form_data: UpdateConfigForm, user=Depends(get_admin_user), ): - config = request.app.state.config + updates = {} if form_data.ENABLE_EVALUATION_ARENA_MODELS is not None: - config.ENABLE_EVALUATION_ARENA_MODELS = form_data.ENABLE_EVALUATION_ARENA_MODELS + updates['evaluation.arena.enable'] = form_data.ENABLE_EVALUATION_ARENA_MODELS if form_data.EVALUATION_ARENA_MODELS is not None: - config.EVALUATION_ARENA_MODELS = form_data.EVALUATION_ARENA_MODELS - return { - 'ENABLE_EVALUATION_ARENA_MODELS': config.ENABLE_EVALUATION_ARENA_MODELS, - 'EVALUATION_ARENA_MODELS': config.EVALUATION_ARENA_MODELS, - } + updates['evaluation.arena.models'] = form_data.EVALUATION_ARENA_MODELS + await Config.upsert(updates) + values = await get_config_values(EVALUATION_CONFIG_KEYS) + await publish_event( + request, + EVENTS.CONFIG_UPDATED, + actor=user, + subject_id='evaluation', + data={ + 'keys': list(updates.keys()), + 'arena_enabled': values.get('ENABLE_EVALUATION_ARENA_MODELS'), + 'arena_model_count': len(values.get('EVALUATION_ARENA_MODELS') or []), + }, + ) + return values @router.get('/feedbacks/models', response_model=list[str]) @@ -299,8 +318,19 @@ async def get_all_feedback_ids(user=Depends(get_admin_user), db: AsyncSession = @router.delete('/feedbacks/all') -async def delete_all_feedbacks(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def delete_all_feedbacks( + request: Request, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): success = await Feedbacks.delete_all_feedbacks(db=db) + if success: + await publish_event( + request, + EVENTS.FEEDBACK_DELETED_ALL, + actor=user, + subject_id='all', + ) return success @@ -332,8 +362,20 @@ async def get_user_feedbacks( @router.delete('/feedbacks', response_model=bool) -async def delete_feedbacks(user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +async def delete_feedbacks( + request: Request, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): success = await Feedbacks.delete_feedbacks_by_user_id(user.id, db=db) + if success: + await publish_event( + request, + EVENTS.FEEDBACK_DELETED_ALL, + actor=user, + subject_id=user.id, + subject_type='user', + ) return success @@ -377,6 +419,13 @@ async def create_feedback( detail=ERROR_MESSAGES.DEFAULT(), ) + await publish_event( + request, + EVENTS.FEEDBACK_CREATED, + actor=user, + subject_id=feedback.id, + data={'rating': getattr(feedback, 'rating', None)}, + ) return feedback @@ -395,6 +444,7 @@ async def get_feedback_by_id(id: str, user=Depends(get_verified_user), db: Async @router.post('/feedback/{id}', response_model=FeedbackModel) async def update_feedback_by_id( + request: Request, id: str, form_data: FeedbackForm, user=Depends(get_verified_user), @@ -408,12 +458,22 @@ async def update_feedback_by_id( if not feedback: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + await publish_event( + request, + EVENTS.FEEDBACK_UPDATED, + actor=user, + subject_id=feedback.id, + data={'rating': getattr(feedback, 'rating', None)}, + ) return feedback @router.delete('/feedback/{id}') async def delete_feedback_by_id( - id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, + id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), ): if user.role == 'admin': success = await Feedbacks.delete_feedback_by_id(id=id, db=db) @@ -423,4 +483,10 @@ async def delete_feedback_by_id( if not success: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + await publish_event( + request, + EVENTS.FEEDBACK_DELETED, + actor=user, + subject_id=id, + ) return success diff --git a/backend/open_webui/routers/files.py b/backend/open_webui/routers/files.py index dbf1ccb885..33e7dc1220 100644 --- a/backend/open_webui/routers/files.py +++ b/backend/open_webui/routers/files.py @@ -1,4 +1,5 @@ import asyncio +import errno import hashlib import json import logging @@ -23,9 +24,11 @@ from fastapi import ( from fastapi.responses import FileResponse, StreamingResponse from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL, STORAGE_LOCAL_CACHE, STORAGE_PROVIDER, UPLOAD_DIR from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_db_context, get_async_session from open_webui.models.access_grants import AccessGrants from open_webui.models.channels import Channels +from open_webui.models.config import Config from open_webui.models.chats import Chats from open_webui.models.files import ( FileForm, @@ -123,7 +126,7 @@ async def process_uploaded_file( if _is_text_file(file_path): content_type = 'text/plain' - stt_supported = getattr(request.app.state.config, 'STT_SUPPORTED_CONTENT_TYPES', []) + stt_supported = await Config.get('audio.stt.supported_content_types', []) if content_type and strict_match_mime_type(stt_supported, content_type): # Audio / STT-supported files → transcribe then index @@ -144,7 +147,7 @@ async def process_uploaded_file( elif ( content_type and content_type.startswith(('image/', 'video/')) - and request.app.state.config.CONTENT_EXTRACTION_ENGINE != 'external' + and await Config.get('rag.content_extraction_engine') != 'external' ): # Media files without an external extraction engine if content_type.startswith('video/'): @@ -178,19 +181,39 @@ async def process_uploaded_file( knowledge_id = file_metadata.get('knowledge_id') if knowledge_id: try: - await Knowledges.add_file_to_knowledge_by_id( - knowledge_id=knowledge_id, - file_id=file_item.id, - user_id=user.id, - directory_id=file_metadata.get('directory_id'), + # Gate like POST /knowledge/{id}/file/add: a client-supplied + # metadata.knowledge_id must not let a non-writer attach files (CWE-862/863). + knowledge = await Knowledges.get_knowledge_by_id(id=knowledge_id, db=db_session) + can_write = bool(knowledge) and ( + knowledge.user_id == user.id + or user.role == 'admin' + or await AccessGrants.has_access( + user_id=user.id, + resource_type='knowledge', + resource_id=knowledge.id, + permission='write', + db=db_session, + ) ) - await process_file( - request, - ProcessFileForm(file_id=file_item.id, collection_name=knowledge_id), - user=user, - db=db_session, - ) - log.info(f'Linked file {file_item.id} to knowledge {knowledge_id}') + if not can_write: + log.warning( + f'Refusing to auto-link file {file_item.id} to knowledge ' + f'{knowledge_id}: user {user.id} lacks write access' + ) + else: + await Knowledges.add_file_to_knowledge_by_id( + knowledge_id=knowledge_id, + file_id=file_item.id, + user_id=user.id, + directory_id=file_metadata.get('directory_id'), + ) + await process_file( + request, + ProcessFileForm(file_id=file_item.id, collection_name=knowledge_id), + user=user, + db=db_session, + ) + log.info(f'Linked file {file_item.id} to knowledge {knowledge_id}') except Exception as e: log.warning(f'Failed to link file {file_item.id} to knowledge {knowledge_id}: {e}') @@ -226,7 +249,7 @@ async def upload_file( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - return await upload_file_handler( + result = await upload_file_handler( request, file=file, metadata=metadata, @@ -237,6 +260,27 @@ async def upload_file( db=db, ) + if isinstance(result, dict): + result_id = result.get('id') + result_filename = result.get('filename') + result_meta = result.get('meta') or {} + else: + result_id = result.id + result_filename = result.filename + result_meta = result.meta or {} + + result_content_type = ( + result_meta.get('content_type') if isinstance(result_meta, dict) else getattr(result_meta, 'content_type', None) + ) + await publish_event( + request, + EVENTS.FILE_UPLOADED, + actor=user, + subject_id=result_id, + data={'filename': result_filename, 'content_type': result_content_type}, + ) + return result + async def upload_file_handler( request: Request, @@ -268,36 +312,59 @@ async def upload_file_handler( # Remove the leading dot from the file extension and lowercase it file_extension = file_extension[1:].lower() if file_extension else '' - if process and request.app.state.config.ALLOWED_FILE_EXTENSIONS: - request.app.state.config.ALLOWED_FILE_EXTENSIONS = [ - ext for ext in request.app.state.config.ALLOWED_FILE_EXTENSIONS if ext - ] + allowed_file_extensions = await Config.get('rag.file.allowed_extensions') + if process and allowed_file_extensions: + allowed_file_extensions = [ext for ext in allowed_file_extensions if ext] - if file_extension not in request.app.state.config.ALLOWED_FILE_EXTENSIONS: + if file_extension not in allowed_file_extensions: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT(f'File type {file_extension} is not allowed'), ) - # replace filename with uuid + # Prefer readable storage names for admins, but fall back if the filesystem rejects it. id = str(uuid.uuid4()) name = filename filename = f'{id}_{filename}' - contents, file_path = await asyncio.to_thread( - Storage.upload_file, - file.file, - filename, - { - 'OpenWebUI-User-Email': user.email, - 'OpenWebUI-User-Id': user.id, - 'OpenWebUI-User-Name': user.name, - 'OpenWebUI-File-Id': id, - }, - ) + tags = { + 'OpenWebUI-User-Email': user.email, + 'OpenWebUI-User-Id': user.id, + 'OpenWebUI-User-Name': user.name, + 'OpenWebUI-File-Id': id, + } + try: + contents, file_path = await asyncio.to_thread(Storage.upload_file, file.file, filename, tags) + except OSError as e: + if e.errno != errno.ENAMETOOLONG: + log.exception(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e.strerror or 'Error uploading file'), + ) + + file.file.seek(0) + filename = f'{id}.{file_extension}' if file_extension else id + try: + contents, file_path = await asyncio.to_thread(Storage.upload_file, file.file, filename, tags) + except OSError as e: + log.exception(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e.strerror or 'Error uploading file'), + ) + max_size = await Config.get('rag.file.max_size') + if max_size and len(contents) > int(max_size) * 1024 * 1024: + await asyncio.to_thread(Storage.delete_file, file_path) + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail=ERROR_MESSAGES.FILE_TOO_LARGE(size=f'{max_size} MB'), + ) # SHA-256 of raw uploaded bytes for incremental sync diffing. # If the client pre-computed and sent file_hash, use that. - file_hash = file_metadata.get('file_hash') or hashlib.sha256(contents).hexdigest() + file_hash = file_metadata.get('file_hash') or await asyncio.to_thread( + lambda: hashlib.sha256(contents).hexdigest() + ) file_item = await Files.insert_new_file( user.id, @@ -443,13 +510,29 @@ async def search_files( return files +############################ +# Count Files +############################ + + +@router.get('/count', response_model=int) +async def count_files( + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + user_id = None if (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL) else user.id + return await Files.count_files_by_user_id(user_id=user_id, db=db) + + ############################ # Delete All Files ############################ @router.delete('/all') -async def delete_all_files(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def delete_all_files( + request: Request, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session) +): result = await Files.delete_all_files(db=db) if result: try: @@ -462,6 +545,7 @@ async def delete_all_files(user=Depends(get_admin_user), db: AsyncSession = Depe status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error deleting files'), ) + await publish_event(request, EVENTS.FILE_DELETED_ALL, actor=user, subject_type='file') return {'message': 'All files deleted successfully'} else: raise HTTPException( @@ -605,6 +689,12 @@ async def update_file_data_content_by_id( ) if file.user_id == user.id or user.role == 'admin' or await has_access_to_file(id, 'write', user, db=db): + max_size = await Config.get('rag.file.max_size') + if max_size and len(form_data.content.encode('utf-8')) > int(max_size) * 1024 * 1024: + raise HTTPException( + status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, + detail=ERROR_MESSAGES.FILE_TOO_LARGE(size=f'{max_size} MB'), + ) try: await process_file( request, @@ -623,18 +713,29 @@ async def update_file_data_content_by_id( knowledges = await Knowledges.get_knowledges_by_file_id(id, db=db) for knowledge in knowledges: try: - # Remove old embeddings for this file from the KB collection - await ASYNC_VECTOR_DB_CLIENT.delete(collection_name=knowledge.id, filter={'file_id': id}) - # Re-add from the now-updated file-{file_id} collection + old_vectors = await ASYNC_VECTOR_DB_CLIENT.query(collection_name=knowledge.id, filter={'file_id': id}) + old_vector_ids = old_vectors.ids[0] if old_vectors and old_vectors.ids else [] + + # Re-add from the now-updated file-{file_id} collection before + # removing old vectors, so a failed reindex keeps the KB usable. await process_file( request, ProcessFileForm(file_id=id, collection_name=knowledge.id), user=user, db=db, ) + if old_vector_ids: + await ASYNC_VECTOR_DB_CLIENT.delete(collection_name=knowledge.id, ids=old_vector_ids) except Exception as e: log.warning(f'Failed to update knowledge {knowledge.id} after content change for file {id}: {e}') + await publish_event( + request, + EVENTS.FILE_CONTENT_UPDATED, + actor=user, + subject_id=id, + data={'content_preview': form_data.content[:300]}, + ) return {'content': file.data.get('content', '')} else: raise HTTPException( @@ -824,6 +925,7 @@ class FileRenameForm(BaseModel): @router.post('/{id}/rename') async def rename_file_by_id( + request: Request, id: str, form_data: FileRenameForm, user=Depends(get_verified_user), @@ -840,6 +942,13 @@ async def rename_file_by_id( if file.user_id == user.id or user.role == 'admin' or await has_access_to_file(id, 'write', user, db=db): result = await Files.update_file_name_by_id(id, form_data.filename, db=db) if result: + await publish_event( + request, + EVENTS.FILE_RENAMED, + actor=user, + subject_id=id, + data={'filename': form_data.filename}, + ) return result else: raise HTTPException( @@ -859,7 +968,9 @@ async def rename_file_by_id( @router.delete('/{id}') -async def delete_file_by_id(id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +async def delete_file_by_id( + request: Request, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): file = await Files.get_file_by_id(id, db=db) if not file: @@ -894,6 +1005,13 @@ async def delete_file_by_id(id: str, user=Depends(get_verified_user), db: AsyncS status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error deleting files'), ) + await publish_event( + request, + EVENTS.FILE_DELETED, + actor=user, + subject_id=id, + data={'filename': file.filename}, + ) return {'message': 'File deleted successfully'} else: raise HTTPException( diff --git a/backend/open_webui/routers/folders.py b/backend/open_webui/routers/folders.py index 8d77de4894..f048bbbf75 100644 --- a/backend/open_webui/routers/folders.py +++ b/backend/open_webui/routers/folders.py @@ -10,7 +10,9 @@ from fastapi import APIRouter, Depends, File, HTTPException, Request, UploadFile from fastapi.responses import FileResponse, StreamingResponse from open_webui.config import UPLOAD_DIR from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session +from open_webui.models.config import Config from open_webui.models.chats import Chats from open_webui.models.folders import ( FolderForm, @@ -19,7 +21,13 @@ from open_webui.models.folders import ( Folders, FolderUpdateForm, ) +from open_webui.models.access_grants import AccessGrants +from open_webui.models.groups import Groups +from open_webui.models.users import Users from open_webui.utils.access_control import has_permission +from open_webui.utils.access_control import ( + filter_allowed_access_grants, +) from open_webui.utils.access_control.files import get_accessible_folder_files from open_webui.utils.auth import get_admin_user, get_verified_user from pydantic import BaseModel @@ -31,6 +39,29 @@ log = logging.getLogger(__name__) router = APIRouter() +from open_webui.utils.access_control.folders import has_folder_access as _has_folder_access + + +async def check_folders_permission(request: Request, user, db=None): + """Verify the folders feature is enabled and the user has permission.""" + config = await Config.get_many('folders.enable', 'user.permissions') + if config.get('folders.enable') is False: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + if user.role != 'admin' and not await has_permission( + user.id, + 'features.folders', + config.get('user.permissions'), + db=db, + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + ############################ # Get Folders ############################ @@ -42,22 +73,7 @@ async def get_folders( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if request.app.state.config.ENABLE_FOLDERS is False: - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) - - if user.role != 'admin' and not await has_permission( - user.id, - 'features.folders', - request.app.state.config.USER_PERMISSIONS, - db=db, - ): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_folders_permission(request, user, db=db) folders = await Folders.get_folders_by_user_id(user.id, db=db) @@ -87,10 +103,12 @@ async def get_folders( @router.post('/') async def create_folder( + request: Request, form_data: FolderForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await check_folders_permission(request, user, db=db) folder = await Folders.get_folder_by_parent_id_and_user_id_and_name( form_data.parent_id, user.id, form_data.name, db=db ) @@ -101,8 +119,43 @@ async def create_folder( detail=ERROR_MESSAGES.DEFAULT('Folder already exists'), ) + # Check if creating a subfolder in a shared folder + if form_data.parent_id: + parent = await Folders.get_folder_by_id(form_data.parent_id, db=db) + if parent and parent.user_id != user.id: + # Creating subfolder in someone else's shared folder + if user.role != 'admin' and not await _has_folder_access(user.id, parent, 'write', db): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + # Create as the folder owner's subfolder (keep tree consistent) + try: + folder = await Folders.insert_new_folder(parent.user_id, form_data, form_data.parent_id, db=db) + await publish_event( + request, + EVENTS.FOLDER_CREATED, + actor=user, + subject_id=folder.id, + data={'name': folder.name, 'parent_id': folder.parent_id, 'owner_id': folder.user_id}, + ) + return folder + except Exception as e: + log.exception(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT('Error creating folder'), + ) + try: folder = await Folders.insert_new_folder(user.id, form_data, form_data.parent_id, db=db) + await publish_event( + request, + EVENTS.FOLDER_CREATED, + actor=user, + subject_id=folder.id, + data={'name': folder.name, 'parent_id': folder.parent_id, 'owner_id': folder.user_id}, + ) return folder except Exception as e: log.exception(e) @@ -113,21 +166,90 @@ async def create_folder( ) +############################ +# Get Shared Folders +############################ + + +@router.get('/shared') +async def get_shared_folders( + request: Request, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + """Get all folders shared with the current user (not owned by them).""" + await check_folders_permission(request, user, db=db) + groups = await Groups.get_groups_by_member_id(user.id, db=db) + group_ids = {g.id for g in groups} + + folder_perms = await Folders.get_shared_folder_ids_for_user(user.id, group_ids, db=db) + + # Filter out folders owned by the user + results = [] + owner_cache = {} + for folder_id, permission in folder_perms.items(): + folder = await Folders.get_folder_by_id(folder_id, db=db) + if not folder or folder.user_id == user.id: + continue + + # Get owner name (cached) + if folder.user_id not in owner_cache: + owner = await Users.get_user_by_id(folder.user_id, db=db) + owner_cache[folder.user_id] = owner.name if owner else 'Unknown' + + results.append( + { + **folder.model_dump(), + 'owner_name': owner_cache[folder.user_id], + 'permission': permission, + } + ) + + # Also include child folders of shared folders (inheritance) + shared_root_ids = {r['id'] for r in results} + for root_id in list(shared_root_ids): + root_folder = await Folders.get_folder_by_id(root_id, db=db) + if root_folder: + children = await Folders.get_children_folders_by_id_and_user_id(root_id, root_folder.user_id, db=db) + if children: + for child in children: + if child.id not in {r['id'] for r in results}: + results.append( + { + **child.model_dump(), + 'owner_name': owner_cache.get(child.user_id, 'Unknown'), + 'permission': folder_perms.get(root_id, 'read'), + } + ) + + return results + + ############################ # Get Folders By Id ############################ -@router.get('/{id}', response_model=Optional[FolderModel]) -async def get_folder_by_id(id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +@router.get('/{id}', response_model=None) +async def get_folder_by_id( + request: Request, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): + await check_folders_permission(request, user, db=db) folder = await Folders.get_folder_by_id_and_user_id(id, user.id, db=db) if folder: - return folder - else: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) + grants = await AccessGrants.get_grants_by_resource('folder', id, db=db) + return {**folder.model_dump(), 'access_grants': [g.model_dump() for g in grants]} + + # Check shared access + folder = await Folders.get_folder_by_id(id, db=db) + if folder and (user.role == 'admin' or await _has_folder_access(user.id, folder, 'read', db)): + grants = await AccessGrants.get_grants_by_resource('folder', id, db=db) + return {**folder.model_dump(), 'access_grants': [g.model_dump() for g in grants]} + + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) ############################ @@ -137,17 +259,28 @@ async def get_folder_by_id(id: str, user=Depends(get_verified_user), db: AsyncSe @router.post('/{id}/update') async def update_folder_name_by_id( + request: Request, id: str, form_data: FolderUpdateForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await check_folders_permission(request, user, db=db) folder = await Folders.get_folder_by_id_and_user_id(id, user.id, db=db) + if not folder: + # Check shared write access + folder = await Folders.get_folder_by_id(id, db=db) + if not folder or (user.role != 'admin' and not await _has_folder_access(user.id, folder, 'write', db)): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + if folder: if form_data.name is not None: # Check if folder with same name exists existing_folder = await Folders.get_folder_by_parent_id_and_user_id_and_name( - folder.parent_id, user.id, form_data.name, db=db + folder.parent_id, folder.user_id, form_data.name, db=db ) if existing_folder and existing_folder.id != id: raise HTTPException( @@ -166,7 +299,14 @@ async def update_folder_name_by_id( ) try: - folder = await Folders.update_folder_by_id_and_user_id(id, user.id, form_data, db=db) + folder = await Folders.update_folder_by_id_and_user_id(id, folder.user_id, form_data, db=db) + await publish_event( + request, + EVENTS.FOLDER_UPDATED, + actor=user, + subject_id=id, + data={'name': folder.name}, + ) return folder except Exception as e: log.exception(e) @@ -175,11 +315,6 @@ async def update_folder_name_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error updating folder'), ) - else: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) ############################ @@ -193,11 +328,13 @@ class FolderParentIdForm(BaseModel): @router.post('/{id}/update/parent') async def update_folder_parent_id_by_id( + request: Request, id: str, form_data: FolderParentIdForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await check_folders_permission(request, user, db=db) folder = await Folders.get_folder_by_id_and_user_id(id, user.id, db=db) if folder: existing_folder = await Folders.get_folder_by_parent_id_and_user_id_and_name( @@ -212,6 +349,13 @@ async def update_folder_parent_id_by_id( try: folder = await Folders.update_folder_parent_id_by_id_and_user_id(id, user.id, form_data.parent_id, db=db) + await publish_event( + request, + EVENTS.FOLDER_PARENT_UPDATED, + actor=user, + subject_id=id, + data={'parent_id': form_data.parent_id}, + ) return folder except Exception as e: log.exception(e) @@ -238,11 +382,13 @@ class FolderIsExpandedForm(BaseModel): @router.post('/{id}/update/expanded') async def update_folder_is_expanded_by_id( + request: Request, id: str, form_data: FolderIsExpandedForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + await check_folders_permission(request, user, db=db) folder = await Folders.get_folder_by_id_and_user_id(id, user.id, db=db) if folder: try: @@ -264,6 +410,113 @@ async def update_folder_is_expanded_by_id( ) +############################ +# Update Folder Access By Id +############################ + + +class FolderAccessGrantsForm(BaseModel): + access_grants: list[dict] + + +@router.post('/{id}/access/update') +async def update_folder_access_by_id( + request: Request, + id: str, + form_data: FolderAccessGrantsForm, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + await check_folders_permission(request, user, db=db) + folder = await Folders.get_folder_by_id(id, db=db) + if not folder: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + # Only owner, admin, or write-granted user can update access + if user.role != 'admin' and user.id != folder.user_id: + if not await _has_folder_access(user.id, folder, 'write', db): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + form_data.access_grants = await filter_allowed_access_grants( + await Config.get('user.permissions'), + user.id, + user.role, + form_data.access_grants, + None, + db=db, + ) + + await AccessGrants.set_access_grants('folder', id, form_data.access_grants, db=db) + + grants = await AccessGrants.get_grants_by_resource('folder', id, db=db) + await publish_event( + request, + EVENTS.FOLDER_ACCESS_UPDATED, + actor=user, + subject_id=id, + data={'grant_count': len(grants)}, + ) + return { + **folder.model_dump(), + 'access_grants': [g.model_dump() for g in grants], + } + + +############################ +# Get Shared Folder Chats +############################ + + +@router.get('/{id}/shared/chats') +async def get_shared_folder_chats( + request: Request, + id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): + """Get chats within a shared folder. Returns readonly flag based on permission.""" + await check_folders_permission(request, user, db=db) + folder = await Folders.get_folder_by_id(id, db=db) + if not folder: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + is_owner = user.id == folder.user_id + is_admin = user.role == 'admin' + has_write = is_owner or is_admin or await _has_folder_access(user.id, folder, 'write', db) + has_read = has_write or await _has_folder_access(user.id, folder, 'read', db) + + if not has_read: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + chats = await Chats.get_all_chats_by_folder_id(id, db=db) + + # Resolve owner names for display (avatar URLs are constructed client-side) + owner_cache: dict[str, str] = {} + for chat in chats: + uid = chat['user_id'] + if uid not in owner_cache: + u = await Users.get_user_by_id(uid, db=db) + owner_cache[uid] = u.name if u else 'Unknown' + chat['owner_name'] = owner_cache[uid] + + return { + 'chats': [{**chat, 'readonly': chat['user_id'] != user.id} for chat in chats], + 'folder_permission': 'write' if has_write else 'read', + } + + ############################ # Delete Folder By Id ############################ @@ -277,9 +530,37 @@ async def delete_folder_by_id( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if await Chats.count_chats_by_folder_id_and_user_id(id, user.id, db=db): + await check_folders_permission(request, user, db=db) + folder = await Folders.get_folder_by_id_and_user_id(id, user.id, db=db) + + if not folder: + # Check if it's a shared subfolder with write access + folder = await Folders.get_folder_by_id(id, db=db) + if folder and folder.parent_id: + if user.role != 'admin' and not await _has_folder_access(user.id, folder, 'write', db): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + elif folder and not folder.parent_id: + # Root shared folders can only be deleted by owner/admin + if user.role != 'admin': + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + else: + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + folder_owner_id = folder.user_id + + folder_ids = await Folders.get_folder_ids_by_id_and_user_id_in_subtree(id, folder_owner_id, db=db) + if await Chats.count_chats_by_folder_ids_and_user_id(folder_ids, folder_owner_id, db=db): chat_delete_permission = await has_permission( - user.id, 'chat.delete', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'chat.delete', await Config.get('user.permissions'), db=db ) if user.role != 'admin' and not chat_delete_permission: raise HTTPException( @@ -288,19 +569,29 @@ async def delete_folder_by_id( ) folders = [] - folders.append(await Folders.get_folder_by_id_and_user_id(id, user.id, db=db)) + folders.append(folder) while folders: folder = folders.pop() if folder: try: - folder_ids = await Folders.delete_folder_by_id_and_user_id(folder.id, user.id, db=db) + folder_ids = await Folders.delete_folder_by_id_and_user_id(folder.id, folder_owner_id, db=db) for folder_id in folder_ids: if delete_contents: - await Chats.delete_chats_by_user_id_and_folder_id(user.id, folder_id, db=db) + await Chats.delete_chats_by_user_id_and_folder_id(folder_owner_id, folder_id, db=db) else: - await Chats.move_chats_by_user_id_and_folder_id(user.id, folder_id, None, db=db) + await Chats.move_chats_by_user_id_and_folder_id(folder_owner_id, folder_id, None, db=db) + # Clean up access grants for this folder + await AccessGrants.revoke_all_access('folder', folder_id, db=db) + + await publish_event( + request, + EVENTS.FOLDER_DELETED, + actor=user, + subject_id=id, + data={'folder_ids': folder_ids, 'delete_contents': delete_contents}, + ) return True except Exception as e: log.exception(e) @@ -311,7 +602,7 @@ async def delete_folder_by_id( ) finally: # Get all subfolders - subfolders = await Folders.get_folders_by_parent_id_and_user_id(folder.id, user.id, db=db) + subfolders = await Folders.get_folders_by_parent_id_and_user_id(folder.id, folder_owner_id, db=db) folders.extend(subfolders) else: diff --git a/backend/open_webui/routers/functions.py b/backend/open_webui/routers/functions.py index 58ec93657e..8917bb37f0 100644 --- a/backend/open_webui/routers/functions.py +++ b/backend/open_webui/routers/functions.py @@ -11,6 +11,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.config import CACHE_DIR from open_webui.constants import ERROR_MESSAGES from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.functions import ( FunctionForm, @@ -22,6 +23,7 @@ from open_webui.models.functions import ( ) from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.plugin import ( + get_functions_cache, get_function_module_from_cache, load_function_module_by_id, replace_imports, @@ -130,8 +132,13 @@ async def load_function_from_url(request: Request, form_data: LoadUrlForm, user= 'name': function_name, 'content': data, } + except HTTPException: + raise except Exception as e: - raise HTTPException(status_code=500, detail=ERROR_MESSAGES.DEFAULT(e)) + raise HTTPException( + status_code=500, + detail=ERROR_MESSAGES.DEFAULT(e, 'Error fetching function'), + ) ############################ @@ -171,7 +178,7 @@ async def sync_functions( log.exception(f'Failed to load a function: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error loading function'), ) @@ -205,7 +212,7 @@ async def create_new_function( ) form_data.meta.manifest = frontmatter - FUNCTIONS = request.app.state.FUNCTIONS + FUNCTIONS = get_functions_cache(request) FUNCTIONS[form_data.id] = function_module function = await Functions.insert_new_function(user.id, function_type, form_data, db=db) @@ -217,17 +224,26 @@ async def create_new_function( await Functions.update_function_metadata_by_id(form_data.id, {'toggle': True}, db=db) if function: + await publish_event( + request, + EVENTS.FUNCTION_CREATED, + actor=user, + subject_id=function.id, + data={'type': function.type, 'name': function.name}, + ) return function else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error creating function'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Failed to create a new function: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error creating function'), ) else: raise HTTPException( @@ -260,12 +276,25 @@ async def get_function_by_id(id: str, user=Depends(get_admin_user), db: AsyncSes @router.post('/id/{id}/toggle', response_model=FunctionModel | None) -async def toggle_function_by_id(id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def toggle_function_by_id( + request: Request, + id: str, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): function = await Functions.get_function_by_id(id, db=db) if function: function = await Functions.update_function_by_id(id, {'is_active': not function.is_active}, db=db) if function: + await publish_event( + request, + EVENTS.FUNCTION_ENABLED if function.is_active else EVENTS.FUNCTION_DISABLED, + actor=user, + subject_id=function.id, + subject_type='function', + data={'type': function.type, 'name': function.name}, + ) return function else: raise HTTPException( @@ -285,12 +314,24 @@ async def toggle_function_by_id(id: str, user=Depends(get_admin_user), db: Async @router.post('/id/{id}/toggle/global', response_model=FunctionModel | None) -async def toggle_global_by_id(id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def toggle_global_by_id( + request: Request, + id: str, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): function = await Functions.get_function_by_id(id, db=db) if function: function = await Functions.update_function_by_id(id, {'is_global': not function.is_global}, db=db) if function: + await publish_event( + request, + EVENTS.FUNCTION_UPDATED, + actor=user, + subject_id=function.id, + data={'type': function.type, 'name': function.name, 'is_global': function.is_global}, + ) return function else: raise HTTPException( @@ -322,7 +363,7 @@ async def update_function_by_id( function_module, function_type, frontmatter = await load_function_module_by_id(id, content=form_data.content) form_data.meta.manifest = frontmatter - FUNCTIONS = request.app.state.FUNCTIONS + FUNCTIONS = get_functions_cache(request) FUNCTIONS[id] = function_module updated = {**form_data.model_dump(exclude={'id'}), 'type': function_type} @@ -334,6 +375,13 @@ async def update_function_by_id( await Functions.update_function_metadata_by_id(id, {'toggle': True}, db=db) if function: + await publish_event( + request, + EVENTS.FUNCTION_UPDATED, + actor=user, + subject_id=function.id, + data={'type': function.type, 'name': function.name}, + ) return function else: raise HTTPException( @@ -341,10 +389,12 @@ async def update_function_by_id( detail=ERROR_MESSAGES.DEFAULT('Error updating function'), ) + except HTTPException: + raise except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating function'), ) @@ -363,9 +413,14 @@ async def delete_function_by_id( result = await Functions.delete_function_by_id(id, db=db) if result: - FUNCTIONS = request.app.state.FUNCTIONS - if id in FUNCTIONS: - del FUNCTIONS[id] + FUNCTIONS = get_functions_cache(request) + FUNCTIONS.pop(id, None) + await publish_event( + request, + EVENTS.FUNCTION_DELETED, + actor=user, + subject_id=id, + ) return result @@ -387,7 +442,7 @@ async def get_function_valves_by_id( except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error getting function valves'), ) else: raise HTTPException( @@ -452,12 +507,18 @@ async def update_function_valves_by_id( valves_dict = valves.model_dump(exclude_unset=True) await Functions.update_function_valves_by_id(id, valves_dict, db=db) + await publish_event( + request, + EVENTS.FUNCTION_VALVES_UPDATED, + actor=user, + subject_id=id, + ) return valves_dict except Exception as e: log.exception(f'Error updating function values by id {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating function valves'), ) else: raise HTTPException( @@ -489,7 +550,7 @@ async def get_function_user_valves_by_id( except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error getting function user valves'), ) else: raise HTTPException( @@ -544,12 +605,19 @@ async def update_function_user_valves_by_id( user_valves = UserValves(**form_data) user_valves_dict = user_valves.model_dump(exclude_unset=True) await Functions.update_user_valves_by_id_and_user_id(id, user.id, user_valves_dict, db=db) + await publish_event( + request, + EVENTS.FUNCTION_VALVES_UPDATED, + actor=user, + subject_id=id, + data={'scope': 'user'}, + ) return user_valves_dict except Exception as e: log.exception(f'Error updating function user valves by id {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating function user valves'), ) else: raise HTTPException( diff --git a/backend/open_webui/routers/groups.py b/backend/open_webui/routers/groups.py index 6efcd3946e..4970666b61 100755 --- a/backend/open_webui/routers/groups.py +++ b/backend/open_webui/routers/groups.py @@ -6,6 +6,7 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.config import CACHE_DIR from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants from open_webui.models.groups import ( @@ -58,6 +59,7 @@ async def get_groups( @router.post('/create', response_model=Optional[GroupResponse]) async def create_new_group( + request: Request, form_data: GroupForm, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session), @@ -65,6 +67,13 @@ async def create_new_group( try: group = await Groups.insert_new_group(user.id, form_data, db=db) if group: + await publish_event( + request, + EVENTS.GROUP_CREATED, + actor=user, + subject_id=group.id, + data={'name': group.name}, + ) return GroupResponse( **group.model_dump(), member_count=await Groups.get_group_member_count_by_id(group.id, db=db), @@ -74,11 +83,13 @@ async def create_new_group( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error creating group'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Error creating a new group: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error creating group'), ) @@ -157,7 +168,7 @@ async def get_users_in_group(id: str, user=Depends(get_admin_user), db: AsyncSes log.exception(f'Error adding users to group {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error getting group members'), ) @@ -168,6 +179,7 @@ async def get_users_in_group(id: str, user=Depends(get_admin_user), db: AsyncSes @router.post('/id/{id}/update', response_model=Optional[GroupResponse]) async def update_group_by_id( + request: Request, id: str, form_data: GroupUpdateForm, user=Depends(get_admin_user), @@ -176,6 +188,13 @@ async def update_group_by_id( try: group = await Groups.update_group_by_id(id, form_data, db=db) if group: + await publish_event( + request, + EVENTS.GROUP_UPDATED, + actor=user, + subject_id=id, + data={'name': group.name}, + ) return GroupResponse( **group.model_dump(), member_count=await Groups.get_group_member_count_by_id(group.id, db=db), @@ -185,11 +204,13 @@ async def update_group_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error updating group'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Error updating group {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating group'), ) @@ -200,6 +221,7 @@ async def update_group_by_id( @router.post('/id/{id}/users/add', response_model=Optional[GroupResponse]) async def add_user_to_group( + request: Request, id: str, form_data: UserIdsForm, user=Depends(get_admin_user), @@ -211,6 +233,13 @@ async def add_user_to_group( group = await Groups.add_users_to_group(id, form_data.user_ids, db=db) if group: + await publish_event( + request, + EVENTS.GROUP_MEMBER_ADDED, + actor=user, + subject_id=id, + data={'user_ids': form_data.user_ids}, + ) return GroupResponse( **group.model_dump(), member_count=await Groups.get_group_member_count_by_id(group.id, db=db), @@ -220,16 +249,19 @@ async def add_user_to_group( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error adding users to group'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Error adding users to group {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error adding users to group'), ) @router.post('/id/{id}/users/remove', response_model=Optional[GroupResponse]) async def remove_users_from_group( + request: Request, id: str, form_data: UserIdsForm, user=Depends(get_admin_user), @@ -238,6 +270,13 @@ async def remove_users_from_group( try: group = await Groups.remove_users_from_group(id, form_data.user_ids, db=db) if group: + await publish_event( + request, + EVENTS.GROUP_MEMBER_REMOVED, + actor=user, + subject_id=id, + data={'user_ids': form_data.user_ids}, + ) return GroupResponse( **group.model_dump(), member_count=await Groups.get_group_member_count_by_id(group.id, db=db), @@ -247,11 +286,13 @@ async def remove_users_from_group( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error removing users from group'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Error removing users from group {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error removing users from group'), ) @@ -261,21 +302,31 @@ async def remove_users_from_group( @router.delete('/id/{id}/delete', response_model=bool) -async def delete_group_by_id(id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def delete_group_by_id( + request: Request, id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session) +): try: result = await Groups.delete_group_by_id(id, db=db) if result: + await publish_event( + request, + EVENTS.GROUP_DELETED, + actor=user, + subject_id=id, + ) return result else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error deleting group'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Error deleting group {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error deleting group'), ) diff --git a/backend/open_webui/routers/images.py b/backend/open_webui/routers/images.py index 9d65cebfb8..78247c0b7e 100644 --- a/backend/open_webui/routers/images.py +++ b/backend/open_webui/routers/images.py @@ -9,22 +9,27 @@ import mimetypes import re import uuid from pathlib import Path +from types import SimpleNamespace from typing import Optional from urllib.parse import quote, urlparse import aiohttp from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile from fastapi.responses import FileResponse +from PIL import Image, ImageOps from open_webui.config import ( CACHE_DIR, + ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION, IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN, IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN, ) from open_webui.constants import ERROR_MESSAGES from open_webui.env import AIOHTTP_CLIENT_ALLOW_REDIRECTS, AIOHTTP_CLIENT_SESSION_SSL, ENABLE_FORWARD_USER_INFO_HEADERS +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.chats import Chats -from open_webui.retrieval.web.utils import validate_url +from open_webui.models.config import Config +from open_webui.retrieval.web.utils import get_ssrf_safe_session, validate_url from open_webui.routers.files import get_file_content_by_id, upload_file_handler from open_webui.utils.access_control import has_permission from open_webui.utils.auth import get_admin_user, get_verified_user @@ -50,17 +55,130 @@ IMAGE_CACHE_DIR.mkdir(parents=True, exist_ok=True) router = APIRouter() +IMAGE_FILE_EXTENSIONS = { + 'image/jpeg': '.jpg', + 'image/jpg': '.jpg', + 'image/mpo': '.jpg', + 'image/png': '.png', + 'image/webp': '.webp', +} + +IMAGE_CONFIG_KEYS = { + 'ENABLE_IMAGE_GENERATION': 'image_generation.enable', + 'ENABLE_IMAGE_PROMPT_GENERATION': 'image_generation.prompt.enable', + 'IMAGE_GENERATION_ENGINE': 'image_generation.engine', + 'IMAGE_GENERATION_MODEL': 'image_generation.model', + 'IMAGE_SIZE': 'image_generation.size', + 'IMAGE_STEPS': 'image_generation.steps', + 'IMAGES_OPENAI_API_BASE_URL': 'image_generation.openai.api_base_url', + 'IMAGES_OPENAI_API_KEY': 'image_generation.openai.api_key', + 'IMAGES_OPENAI_API_VERSION': 'image_generation.openai.api_version', + 'IMAGES_OPENAI_API_PARAMS': 'image_generation.openai.params', + 'AUTOMATIC1111_BASE_URL': 'image_generation.automatic1111.base_url', + 'AUTOMATIC1111_API_AUTH': 'image_generation.automatic1111.api_auth', + 'AUTOMATIC1111_PARAMS': 'image_generation.automatic1111.api_params', + 'COMFYUI_BASE_URL': 'image_generation.comfyui.base_url', + 'COMFYUI_API_KEY': 'image_generation.comfyui.api_key', + 'COMFYUI_WORKFLOW': 'image_generation.comfyui.workflow', + 'COMFYUI_WORKFLOW_NODES': 'image_generation.comfyui.nodes', + 'IMAGES_GEMINI_API_BASE_URL': 'image_generation.gemini.api_base_url', + 'IMAGES_GEMINI_API_KEY': 'image_generation.gemini.api_key', + 'IMAGES_GEMINI_ENDPOINT_METHOD': 'image_generation.gemini.endpoint_method', + 'ENABLE_IMAGE_EDIT': 'images.edit.enable', + 'IMAGE_EDIT_ENGINE': 'images.edit.engine', + 'IMAGE_EDIT_MODEL': 'images.edit.model', + 'IMAGE_EDIT_SIZE': 'images.edit.size', + 'IMAGES_EDIT_OPENAI_API_BASE_URL': 'images.edit.openai.api_base_url', + 'IMAGES_EDIT_OPENAI_API_KEY': 'images.edit.openai.api_key', + 'IMAGES_EDIT_OPENAI_API_VERSION': 'images.edit.openai.api_version', + 'IMAGES_EDIT_GEMINI_API_BASE_URL': 'images.edit.gemini.api_base_url', + 'IMAGES_EDIT_GEMINI_API_KEY': 'images.edit.gemini.api_key', + 'IMAGES_EDIT_COMFYUI_BASE_URL': 'images.edit.comfyui.base_url', + 'IMAGES_EDIT_COMFYUI_API_KEY': 'images.edit.comfyui.api_key', + 'IMAGES_EDIT_COMFYUI_WORKFLOW': 'images.edit.comfyui.workflow', + 'IMAGES_EDIT_COMFYUI_WORKFLOW_NODES': 'images.edit.comfyui.nodes', + 'USER_PERMISSIONS': 'user.permissions', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +async def get_image_config() -> SimpleNamespace: + return SimpleNamespace(**await get_config_values(IMAGE_CONFIG_KEYS)) + + +def config_updates(data: dict, key_map: dict[str, str]) -> dict: + return {key_map[field]: value for field, value in data.items() if field in key_map} + + +def normalize_openai_edit_image_data_url(data_url: str) -> str: + if not data_url.startswith('data:') or ',' not in data_url: + return data_url + + header, encoded = data_url.split(',', 1) + mime_type = header.split(';')[0].lstrip('data:').lower() + if mime_type not in {'image/jpeg', 'image/jpg', 'image/mpo'}: + return data_url + + try: + image_bytes = base64.b64decode(encoded) + with Image.open(io.BytesIO(image_bytes)) as image: + orientation = image.getexif().get(274) + needs_normalization = ( + mime_type == 'image/mpo' + or image.format == 'MPO' + or getattr(image, 'n_frames', 1) > 1 + or orientation not in (None, 1) + or image.mode not in ('RGB', 'L') + ) + + if not needs_normalization: + return data_url + + image.seek(0) + image = ImageOps.exif_transpose(image) + if image.mode != 'RGB': + image = image.convert('RGB') + + output = io.BytesIO() + image.save(output, format='JPEG', quality=95) + normalized_image = base64.b64encode(output.getvalue()).decode('utf-8') + return f'data:image/jpeg;base64,{normalized_image}' + except Exception as e: + log.debug(f'Image edit normalization skipped: {e}') + + return data_url + + +def get_image_file_item(base64_string, param_name='image'): + header, encoded = base64_string.split(',', 1) + mime_type = header.split(';')[0].lstrip('data:') or 'image/png' + image_data = base64.b64decode(encoded) + extension = IMAGE_FILE_EXTENSIONS.get(mime_type.lower()) or mimetypes.guess_extension(mime_type) or '.png' + return ( + param_name, + ( + f'{uuid.uuid4()}{extension}', + io.BytesIO(image_data), + mime_type, + ), + ) + async def set_image_model(request: Request, model: str): log.info(f'Setting image model to {model}') - request.app.state.config.IMAGE_GENERATION_MODEL = model - if request.app.state.config.IMAGE_GENERATION_ENGINE in ['', 'automatic1111']: - api_auth = get_automatic1111_api_auth(request) + await Config.upsert({'image_generation.model': model}) + image_config = await get_image_config() + if image_config.IMAGE_GENERATION_ENGINE in ['', 'automatic1111']: + api_auth = get_automatic1111_api_auth(image_config) try: session = await get_session() async with session.get( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', headers={'authorization': api_auth}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: @@ -68,7 +186,7 @@ async def set_image_model(request: Request, model: str): if model != options['sd_model_checkpoint']: options['sd_model_checkpoint'] = model async with session.post( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', json=options, headers={'authorization': api_auth}, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -77,41 +195,33 @@ async def set_image_model(request: Request, model: str): except Exception as e: log.debug(f'{e}') - return request.app.state.config.IMAGE_GENERATION_MODEL + return image_config.IMAGE_GENERATION_MODEL async def get_image_model(request): - if request.app.state.config.IMAGE_GENERATION_ENGINE == 'openai': - return ( - request.app.state.config.IMAGE_GENERATION_MODEL - if request.app.state.config.IMAGE_GENERATION_MODEL - else 'dall-e-2' - ) - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'gemini': - return ( - request.app.state.config.IMAGE_GENERATION_MODEL - if request.app.state.config.IMAGE_GENERATION_MODEL - else 'imagen-3.0-generate-002' - ) - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'comfyui': - return ( - request.app.state.config.IMAGE_GENERATION_MODEL if request.app.state.config.IMAGE_GENERATION_MODEL else '' - ) - elif ( - request.app.state.config.IMAGE_GENERATION_ENGINE == 'automatic1111' - or request.app.state.config.IMAGE_GENERATION_ENGINE == '' - ): + image_config = await get_image_config() + if image_config.IMAGE_GENERATION_ENGINE == 'openai': + return image_config.IMAGE_GENERATION_MODEL if image_config.IMAGE_GENERATION_MODEL else 'dall-e-2' + elif image_config.IMAGE_GENERATION_ENGINE == 'gemini': + return image_config.IMAGE_GENERATION_MODEL if image_config.IMAGE_GENERATION_MODEL else 'imagen-3.0-generate-002' + elif image_config.IMAGE_GENERATION_ENGINE == 'comfyui': + return image_config.IMAGE_GENERATION_MODEL if image_config.IMAGE_GENERATION_MODEL else '' + elif image_config.IMAGE_GENERATION_ENGINE == 'automatic1111' or image_config.IMAGE_GENERATION_ENGINE == '': try: session = await get_session() async with session.get( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', - headers={'authorization': get_automatic1111_api_auth(request)}, + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', + headers={'authorization': get_automatic1111_api_auth(image_config)}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: options = await r.json() return options['sd_model_checkpoint'] except Exception as e: - raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e)) + log.exception(f'Failed to get default model from automatic1111: {e}') + raise HTTPException( + status_code=400, + detail=ERROR_MESSAGES.DEFAULT(e, 'Failed to connect to the image generation engine'), + ) class ImagesConfig(BaseModel): @@ -159,52 +269,11 @@ class ImagesConfig(BaseModel): @router.get('/config', response_model=ImagesConfig) async def get_config(request: Request, user=Depends(get_admin_user)): - return { - 'ENABLE_IMAGE_GENERATION': request.app.state.config.ENABLE_IMAGE_GENERATION, - 'ENABLE_IMAGE_PROMPT_GENERATION': request.app.state.config.ENABLE_IMAGE_PROMPT_GENERATION, - 'IMAGE_GENERATION_ENGINE': request.app.state.config.IMAGE_GENERATION_ENGINE, - 'IMAGE_GENERATION_MODEL': request.app.state.config.IMAGE_GENERATION_MODEL, - 'IMAGE_SIZE': request.app.state.config.IMAGE_SIZE, - 'IMAGE_STEPS': request.app.state.config.IMAGE_STEPS, - 'IMAGES_OPENAI_API_BASE_URL': request.app.state.config.IMAGES_OPENAI_API_BASE_URL, - 'IMAGES_OPENAI_API_KEY': request.app.state.config.IMAGES_OPENAI_API_KEY, - 'IMAGES_OPENAI_API_VERSION': request.app.state.config.IMAGES_OPENAI_API_VERSION, - 'IMAGES_OPENAI_API_PARAMS': request.app.state.config.IMAGES_OPENAI_API_PARAMS, - 'AUTOMATIC1111_BASE_URL': request.app.state.config.AUTOMATIC1111_BASE_URL, - 'AUTOMATIC1111_API_AUTH': request.app.state.config.AUTOMATIC1111_API_AUTH, - 'AUTOMATIC1111_PARAMS': request.app.state.config.AUTOMATIC1111_PARAMS, - 'COMFYUI_BASE_URL': request.app.state.config.COMFYUI_BASE_URL, - 'COMFYUI_API_KEY': request.app.state.config.COMFYUI_API_KEY, - 'COMFYUI_WORKFLOW': request.app.state.config.COMFYUI_WORKFLOW, - 'COMFYUI_WORKFLOW_NODES': request.app.state.config.COMFYUI_WORKFLOW_NODES, - 'IMAGES_GEMINI_API_BASE_URL': request.app.state.config.IMAGES_GEMINI_API_BASE_URL, - 'IMAGES_GEMINI_API_KEY': request.app.state.config.IMAGES_GEMINI_API_KEY, - 'IMAGES_GEMINI_ENDPOINT_METHOD': request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD, - 'ENABLE_IMAGE_EDIT': request.app.state.config.ENABLE_IMAGE_EDIT, - 'IMAGE_EDIT_ENGINE': request.app.state.config.IMAGE_EDIT_ENGINE, - 'IMAGE_EDIT_MODEL': request.app.state.config.IMAGE_EDIT_MODEL, - 'IMAGE_EDIT_SIZE': request.app.state.config.IMAGE_EDIT_SIZE, - 'IMAGES_EDIT_OPENAI_API_BASE_URL': request.app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL, - 'IMAGES_EDIT_OPENAI_API_KEY': request.app.state.config.IMAGES_EDIT_OPENAI_API_KEY, - 'IMAGES_EDIT_OPENAI_API_VERSION': request.app.state.config.IMAGES_EDIT_OPENAI_API_VERSION, - 'IMAGES_EDIT_GEMINI_API_BASE_URL': request.app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL, - 'IMAGES_EDIT_GEMINI_API_KEY': request.app.state.config.IMAGES_EDIT_GEMINI_API_KEY, - 'IMAGES_EDIT_COMFYUI_BASE_URL': request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL, - 'IMAGES_EDIT_COMFYUI_API_KEY': request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY, - 'IMAGES_EDIT_COMFYUI_WORKFLOW': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW, - 'IMAGES_EDIT_COMFYUI_WORKFLOW_NODES': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, - } + return await get_config_values(IMAGE_CONFIG_KEYS) @router.post('/config/update') async def update_config(request: Request, form_data: ImagesConfig, user=Depends(get_admin_user)): - request.app.state.config.ENABLE_IMAGE_GENERATION = form_data.ENABLE_IMAGE_GENERATION - - # Create Image - request.app.state.config.ENABLE_IMAGE_PROMPT_GENERATION = form_data.ENABLE_IMAGE_PROMPT_GENERATION - - request.app.state.config.IMAGE_GENERATION_ENGINE = form_data.IMAGE_GENERATION_ENGINE - await set_image_model(request, form_data.IMAGE_GENERATION_MODEL) if form_data.IMAGE_SIZE == 'auto' and not re.match( IMAGE_AUTO_SIZE_MODELS_REGEX_PATTERN, form_data.IMAGE_GENERATION_MODEL ): @@ -216,100 +285,44 @@ async def update_config(request: Request, form_data: ImagesConfig, user=Depends( ) pattern = r'^\d+x\d+$' - if form_data.IMAGE_SIZE == 'auto' or form_data.IMAGE_SIZE == '' or re.match(pattern, form_data.IMAGE_SIZE): - request.app.state.config.IMAGE_SIZE = form_data.IMAGE_SIZE - else: + if not (form_data.IMAGE_SIZE == 'auto' or form_data.IMAGE_SIZE == '' or re.match(pattern, form_data.IMAGE_SIZE)): raise HTTPException( status_code=400, detail=ERROR_MESSAGES.INCORRECT_FORMAT(' (e.g., 512x512).'), ) - if form_data.IMAGE_STEPS >= 0: - request.app.state.config.IMAGE_STEPS = form_data.IMAGE_STEPS - else: + if form_data.IMAGE_STEPS < 0: raise HTTPException( status_code=400, detail=ERROR_MESSAGES.INCORRECT_FORMAT(' (e.g., 50).'), ) - request.app.state.config.IMAGES_OPENAI_API_BASE_URL = form_data.IMAGES_OPENAI_API_BASE_URL - request.app.state.config.IMAGES_OPENAI_API_KEY = form_data.IMAGES_OPENAI_API_KEY - request.app.state.config.IMAGES_OPENAI_API_VERSION = form_data.IMAGES_OPENAI_API_VERSION - request.app.state.config.IMAGES_OPENAI_API_PARAMS = form_data.IMAGES_OPENAI_API_PARAMS - - request.app.state.config.AUTOMATIC1111_BASE_URL = form_data.AUTOMATIC1111_BASE_URL - request.app.state.config.AUTOMATIC1111_API_AUTH = form_data.AUTOMATIC1111_API_AUTH - request.app.state.config.AUTOMATIC1111_PARAMS = form_data.AUTOMATIC1111_PARAMS - - request.app.state.config.COMFYUI_BASE_URL = form_data.COMFYUI_BASE_URL.strip('/') - request.app.state.config.COMFYUI_API_KEY = form_data.COMFYUI_API_KEY - request.app.state.config.COMFYUI_WORKFLOW = form_data.COMFYUI_WORKFLOW - request.app.state.config.COMFYUI_WORKFLOW_NODES = form_data.COMFYUI_WORKFLOW_NODES - - request.app.state.config.IMAGES_GEMINI_API_BASE_URL = form_data.IMAGES_GEMINI_API_BASE_URL - request.app.state.config.IMAGES_GEMINI_API_KEY = form_data.IMAGES_GEMINI_API_KEY - request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD = form_data.IMAGES_GEMINI_ENDPOINT_METHOD - - # Edit Image - request.app.state.config.ENABLE_IMAGE_EDIT = form_data.ENABLE_IMAGE_EDIT - request.app.state.config.IMAGE_EDIT_ENGINE = form_data.IMAGE_EDIT_ENGINE - request.app.state.config.IMAGE_EDIT_MODEL = form_data.IMAGE_EDIT_MODEL - request.app.state.config.IMAGE_EDIT_SIZE = form_data.IMAGE_EDIT_SIZE - - request.app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL = form_data.IMAGES_EDIT_OPENAI_API_BASE_URL - request.app.state.config.IMAGES_EDIT_OPENAI_API_KEY = form_data.IMAGES_EDIT_OPENAI_API_KEY - request.app.state.config.IMAGES_EDIT_OPENAI_API_VERSION = form_data.IMAGES_EDIT_OPENAI_API_VERSION - - request.app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL = form_data.IMAGES_EDIT_GEMINI_API_BASE_URL - request.app.state.config.IMAGES_EDIT_GEMINI_API_KEY = form_data.IMAGES_EDIT_GEMINI_API_KEY - - request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL = form_data.IMAGES_EDIT_COMFYUI_BASE_URL.strip('/') - request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY = form_data.IMAGES_EDIT_COMFYUI_API_KEY - request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW = form_data.IMAGES_EDIT_COMFYUI_WORKFLOW - request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES = form_data.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES - - return { - 'ENABLE_IMAGE_GENERATION': request.app.state.config.ENABLE_IMAGE_GENERATION, - 'ENABLE_IMAGE_PROMPT_GENERATION': request.app.state.config.ENABLE_IMAGE_PROMPT_GENERATION, - 'IMAGE_GENERATION_ENGINE': request.app.state.config.IMAGE_GENERATION_ENGINE, - 'IMAGE_GENERATION_MODEL': request.app.state.config.IMAGE_GENERATION_MODEL, - 'IMAGE_SIZE': request.app.state.config.IMAGE_SIZE, - 'IMAGE_STEPS': request.app.state.config.IMAGE_STEPS, - 'IMAGES_OPENAI_API_BASE_URL': request.app.state.config.IMAGES_OPENAI_API_BASE_URL, - 'IMAGES_OPENAI_API_KEY': request.app.state.config.IMAGES_OPENAI_API_KEY, - 'IMAGES_OPENAI_API_VERSION': request.app.state.config.IMAGES_OPENAI_API_VERSION, - 'IMAGES_OPENAI_API_PARAMS': request.app.state.config.IMAGES_OPENAI_API_PARAMS, - 'AUTOMATIC1111_BASE_URL': request.app.state.config.AUTOMATIC1111_BASE_URL, - 'AUTOMATIC1111_API_AUTH': request.app.state.config.AUTOMATIC1111_API_AUTH, - 'AUTOMATIC1111_PARAMS': request.app.state.config.AUTOMATIC1111_PARAMS, - 'COMFYUI_BASE_URL': request.app.state.config.COMFYUI_BASE_URL, - 'COMFYUI_API_KEY': request.app.state.config.COMFYUI_API_KEY, - 'COMFYUI_WORKFLOW': request.app.state.config.COMFYUI_WORKFLOW, - 'COMFYUI_WORKFLOW_NODES': request.app.state.config.COMFYUI_WORKFLOW_NODES, - 'IMAGES_GEMINI_API_BASE_URL': request.app.state.config.IMAGES_GEMINI_API_BASE_URL, - 'IMAGES_GEMINI_API_KEY': request.app.state.config.IMAGES_GEMINI_API_KEY, - 'IMAGES_GEMINI_ENDPOINT_METHOD': request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD, - 'ENABLE_IMAGE_EDIT': request.app.state.config.ENABLE_IMAGE_EDIT, - 'IMAGE_EDIT_ENGINE': request.app.state.config.IMAGE_EDIT_ENGINE, - 'IMAGE_EDIT_MODEL': request.app.state.config.IMAGE_EDIT_MODEL, - 'IMAGE_EDIT_SIZE': request.app.state.config.IMAGE_EDIT_SIZE, - 'IMAGES_EDIT_OPENAI_API_BASE_URL': request.app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL, - 'IMAGES_EDIT_OPENAI_API_KEY': request.app.state.config.IMAGES_EDIT_OPENAI_API_KEY, - 'IMAGES_EDIT_OPENAI_API_VERSION': request.app.state.config.IMAGES_EDIT_OPENAI_API_VERSION, - 'IMAGES_EDIT_GEMINI_API_BASE_URL': request.app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL, - 'IMAGES_EDIT_GEMINI_API_KEY': request.app.state.config.IMAGES_EDIT_GEMINI_API_KEY, - 'IMAGES_EDIT_COMFYUI_BASE_URL': request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL, - 'IMAGES_EDIT_COMFYUI_API_KEY': request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY, - 'IMAGES_EDIT_COMFYUI_WORKFLOW': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW, - 'IMAGES_EDIT_COMFYUI_WORKFLOW_NODES': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, - } + updates = config_updates(form_data.model_dump(), IMAGE_CONFIG_KEYS) + updates['image_generation.comfyui.base_url'] = form_data.COMFYUI_BASE_URL.strip('/') + updates['images.edit.comfyui.base_url'] = form_data.IMAGES_EDIT_COMFYUI_BASE_URL.strip('/') + await Config.upsert(updates) + await set_image_model(request, form_data.IMAGE_GENERATION_MODEL) + values = await get_config_values(IMAGE_CONFIG_KEYS) + await publish_event( + request, + EVENTS.CONFIG_UPDATED, + actor=user, + subject_id='images', + data={ + 'image_generation_enabled': values.get('ENABLE_IMAGE_GENERATION'), + 'image_edit_enabled': values.get('ENABLE_IMAGE_EDIT'), + 'image_generation_engine': values.get('IMAGE_GENERATION_ENGINE'), + 'image_edit_engine': values.get('IMAGE_EDIT_ENGINE'), + }, + ) + return values -def get_automatic1111_api_auth(request: Request): - if request.app.state.config.AUTOMATIC1111_API_AUTH is None: +def get_automatic1111_api_auth(image_config): + if image_config.AUTOMATIC1111_API_AUTH is None: return '' else: - auth1111_byte_string = request.app.state.config.AUTOMATIC1111_API_AUTH.encode('utf-8') + auth1111_byte_string = image_config.AUTOMATIC1111_API_AUTH.encode('utf-8') auth1111_base64_encoded_bytes = base64.b64encode(auth1111_byte_string) auth1111_base64_encoded_string = auth1111_base64_encoded_bytes.decode('utf-8') return f'Basic {auth1111_base64_encoded_string}' @@ -317,26 +330,27 @@ def get_automatic1111_api_auth(request: Request): @router.get('/config/url/verify') async def verify_url(request: Request, user=Depends(get_admin_user)): - if request.app.state.config.IMAGE_GENERATION_ENGINE == 'automatic1111': + image_config = await get_image_config() + if image_config.IMAGE_GENERATION_ENGINE == 'automatic1111': try: session = await get_session() async with session.get( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', - headers={'authorization': get_automatic1111_api_auth(request)}, + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/options', + headers={'authorization': get_automatic1111_api_auth(image_config)}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: r.raise_for_status() return True except Exception: raise HTTPException(status_code=400, detail=ERROR_MESSAGES.INVALID_URL) - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'comfyui': + elif image_config.IMAGE_GENERATION_ENGINE == 'comfyui': headers = None - if request.app.state.config.COMFYUI_API_KEY: - headers = {'Authorization': f'Bearer {request.app.state.config.COMFYUI_API_KEY}'} + if image_config.COMFYUI_API_KEY: + headers = {'Authorization': f'Bearer {image_config.COMFYUI_API_KEY}'} try: session = await get_session() async with session.get( - url=f'{request.app.state.config.COMFYUI_BASE_URL}/object_info', + url=f'{image_config.COMFYUI_BASE_URL}/object_info', headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: @@ -350,33 +364,34 @@ async def verify_url(request: Request, user=Depends(get_admin_user)): @router.get('/models') async def get_models(request: Request, user=Depends(get_verified_user)): + image_config = await get_image_config() try: - if request.app.state.config.IMAGE_GENERATION_ENGINE == 'openai': + if image_config.IMAGE_GENERATION_ENGINE == 'openai': return [ {'id': 'dall-e-2', 'name': 'DALL·E 2'}, {'id': 'dall-e-3', 'name': 'DALL·E 3'}, {'id': 'gpt-image-1', 'name': 'GPT-IMAGE 1'}, {'id': 'gpt-image-1.5', 'name': 'GPT-IMAGE 1.5'}, ] - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'gemini': + elif image_config.IMAGE_GENERATION_ENGINE == 'gemini': return [ {'id': 'imagen-3.0-generate-002', 'name': 'imagen-3.0 generate-002'}, ] - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'comfyui': + elif image_config.IMAGE_GENERATION_ENGINE == 'comfyui': # TODO - get models from comfyui - headers = {'Authorization': f'Bearer {request.app.state.config.COMFYUI_API_KEY}'} + headers = {'Authorization': f'Bearer {image_config.COMFYUI_API_KEY}'} session = await get_session() async with session.get( - url=f'{request.app.state.config.COMFYUI_BASE_URL}/object_info', + url=f'{image_config.COMFYUI_BASE_URL}/object_info', headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: info = await r.json() - workflow = json.loads(request.app.state.config.COMFYUI_WORKFLOW) + workflow = json.loads(image_config.COMFYUI_WORKFLOW) model_node_id = None - for node in request.app.state.config.COMFYUI_WORKFLOW_NODES: + for node in image_config.COMFYUI_WORKFLOW_NODES: if node['type'] == 'model': if node['node_ids']: model_node_id = node['node_ids'][0] @@ -405,14 +420,11 @@ async def get_models(request: Request, user=Depends(get_verified_user)): info['CheckpointLoaderSimple']['input']['required']['ckpt_name'][0], ) ) - elif ( - request.app.state.config.IMAGE_GENERATION_ENGINE == 'automatic1111' - or request.app.state.config.IMAGE_GENERATION_ENGINE == '' - ): + elif image_config.IMAGE_GENERATION_ENGINE == 'automatic1111' or image_config.IMAGE_GENERATION_ENGINE == '': session = await get_session() async with session.get( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models', - headers={'authorization': get_automatic1111_api_auth(request)}, + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/sd-models', + headers={'authorization': get_automatic1111_api_auth(image_config)}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: models = await r.json() @@ -423,7 +435,11 @@ async def get_models(request: Request, user=Depends(get_verified_user)): ) ) except Exception as e: - raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e)) + log.exception(f'Failed to list image generation models: {e}') + raise HTTPException( + status_code=400, + detail=ERROR_MESSAGES.DEFAULT(e, 'Failed to retrieve image generation models'), + ) class CreateImageForm(BaseModel): @@ -468,12 +484,12 @@ async def get_image_data(data: str, headers=None, trusted_base_url: str | None = # ComfyUI on a private network), skip SSRF validation only when # the URL shares the exact same origin (scheme + host + port) # as the admin-configured base. This avoids both the global - # ENABLE_RAG_LOCAL_WEB_FETCH hammer and a blanket trust flag + # ENABLE_LOCAL_WEB_FETCH hammer and a blanket trust flag # that would follow arbitrary redirects. if trusted_base_url and _is_same_origin(data, trusted_base_url): log.debug(f'Skipping URL validation for trusted backend: {data}') else: - validate_url(data) + await asyncio.to_thread(validate_url, data) session = await get_session() async with session.get( data, @@ -540,21 +556,36 @@ async def upload_image(request, image_data, content_type, metadata, user, db=Non @router.post('/generations') async def generate_images(request: Request, form_data: CreateImageForm, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_IMAGE_GENERATION: + image_config = await get_image_config() + if not image_config.ENABLE_IMAGE_GENERATION: raise HTTPException( status_code=403, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) if user.role != 'admin' and not await has_permission( - user.id, 'features.image_generation', request.app.state.config.USER_PERMISSIONS + user.id, 'features.image_generation', image_config.USER_PERMISSIONS ): raise HTTPException( status_code=403, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - return await image_generations(request, form_data, user=user) + result = await image_generations(request, form_data, user=user) + await publish_event( + request, + EVENTS.IMAGE_GENERATED, + actor=user, + subject_id=None, + subject_type='image', + data={ + 'model': form_data.model, + 'size': form_data.size, + 'n': form_data.n, + 'prompt_preview': form_data.prompt[:300], + }, + ) + return result async def image_generations( @@ -563,13 +594,14 @@ async def image_generations( metadata: dict | None = None, user=None, ): + image_config = await get_image_config() # if IMAGE_SIZE = 'auto', default WidthxHeight to the 512x512 default # This is only relevant when the user has set IMAGE_SIZE to 'auto' with an # image model other than gpt-image-1, which is warned about on settings save size = '512x512' - if request.app.state.config.IMAGE_SIZE and 'x' in request.app.state.config.IMAGE_SIZE: - size = request.app.state.config.IMAGE_SIZE + if image_config.IMAGE_SIZE and 'x' in image_config.IMAGE_SIZE: + size = image_config.IMAGE_SIZE if form_data.size and 'x' in form_data.size: size = form_data.size @@ -581,41 +613,37 @@ async def image_generations( model = await get_image_model(request) try: - if request.app.state.config.IMAGE_GENERATION_ENGINE == 'openai': + if image_config.IMAGE_GENERATION_ENGINE == 'openai': headers = { - 'Authorization': f'Bearer {request.app.state.config.IMAGES_OPENAI_API_KEY}', + 'Authorization': f'Bearer {image_config.IMAGES_OPENAI_API_KEY}', 'Content-Type': 'application/json', } if ENABLE_FORWARD_USER_INFO_HEADERS: headers = include_user_info_headers(headers, user) - url = f'{request.app.state.config.IMAGES_OPENAI_API_BASE_URL}/images/generations' - if request.app.state.config.IMAGES_OPENAI_API_VERSION: - url = f'{url}?api-version={request.app.state.config.IMAGES_OPENAI_API_VERSION}' + url = f'{image_config.IMAGES_OPENAI_API_BASE_URL}/images/generations' + if image_config.IMAGES_OPENAI_API_VERSION: + url = f'{url}?api-version={image_config.IMAGES_OPENAI_API_VERSION}' data = { 'model': model, 'prompt': form_data.prompt, 'n': form_data.n, **( - {'size': form_data.size or request.app.state.config.IMAGE_SIZE} - if (form_data.size or request.app.state.config.IMAGE_SIZE) + {'size': form_data.size or image_config.IMAGE_SIZE} + if (form_data.size or image_config.IMAGE_SIZE) else {} ), **( {} if re.match( IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN, - request.app.state.config.IMAGE_GENERATION_MODEL, + image_config.IMAGE_GENERATION_MODEL, ) else {'response_format': 'b64_json'} ), - **( - {} - if not request.app.state.config.IMAGES_OPENAI_API_PARAMS - else request.app.state.config.IMAGES_OPENAI_API_PARAMS - ), + **({} if not image_config.IMAGES_OPENAI_API_PARAMS else image_config.IMAGES_OPENAI_API_PARAMS), } session = await get_session() @@ -643,17 +671,17 @@ async def image_generations( images.append({'url': url}) return images - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'gemini': + elif image_config.IMAGE_GENERATION_ENGINE == 'gemini': headers = { 'Content-Type': 'application/json', - 'x-goog-api-key': request.app.state.config.IMAGES_GEMINI_API_KEY, + 'x-goog-api-key': image_config.IMAGES_GEMINI_API_KEY, } data = {} if ( - request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD == '' - or request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD == 'predict' + image_config.IMAGES_GEMINI_ENDPOINT_METHOD == '' + or image_config.IMAGES_GEMINI_ENDPOINT_METHOD == 'predict' ): model = f'{model}:predict' data = { @@ -664,13 +692,13 @@ async def image_generations( }, } - elif request.app.state.config.IMAGES_GEMINI_ENDPOINT_METHOD == 'generateContent': + elif image_config.IMAGES_GEMINI_ENDPOINT_METHOD == 'generateContent': model = f'{model}:generateContent' data = {'contents': [{'parts': [{'text': form_data.prompt}]}]} session = await get_session() async with session.post( - url=f'{request.app.state.config.IMAGES_GEMINI_API_BASE_URL}/models/{model}', + url=f'{image_config.IMAGES_GEMINI_API_BASE_URL}/models/{model}', json=data, headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -701,7 +729,7 @@ async def image_generations( return images - elif request.app.state.config.IMAGE_GENERATION_ENGINE == 'comfyui': + elif image_config.IMAGE_GENERATION_ENGINE == 'comfyui': data = { 'prompt': form_data.prompt, 'width': width, @@ -709,8 +737,8 @@ async def image_generations( 'n': form_data.n, } - if request.app.state.config.IMAGE_STEPS is not None or form_data.steps is not None: - data['steps'] = form_data.steps if form_data.steps is not None else request.app.state.config.IMAGE_STEPS + if image_config.IMAGE_STEPS is not None or form_data.steps is not None: + data['steps'] = form_data.steps if form_data.steps is not None else image_config.IMAGE_STEPS if form_data.negative_prompt is not None: data['negative_prompt'] = form_data.negative_prompt @@ -719,8 +747,8 @@ async def image_generations( **{ 'workflow': ComfyUIWorkflow( **{ - 'workflow': request.app.state.config.COMFYUI_WORKFLOW, - 'nodes': request.app.state.config.COMFYUI_WORKFLOW_NODES, + 'workflow': image_config.COMFYUI_WORKFLOW, + 'nodes': image_config.COMFYUI_WORKFLOW_NODES, } ), **data, @@ -730,8 +758,8 @@ async def image_generations( model, form_data, str(uuid.uuid4()), - request.app.state.config.COMFYUI_BASE_URL, - request.app.state.config.COMFYUI_API_KEY, + image_config.COMFYUI_BASE_URL, + image_config.COMFYUI_API_KEY, ) log.debug(f'res: {res}') @@ -739,13 +767,13 @@ async def image_generations( for image in res['data']: headers = None - if request.app.state.config.COMFYUI_API_KEY: - headers = {'Authorization': f'Bearer {request.app.state.config.COMFYUI_API_KEY}'} + if image_config.COMFYUI_API_KEY: + headers = {'Authorization': f'Bearer {image_config.COMFYUI_API_KEY}'} image_data, content_type = await get_image_data( image['url'], headers, - trusted_base_url=request.app.state.config.COMFYUI_BASE_URL, + trusted_base_url=image_config.COMFYUI_BASE_URL, ) _, url = await upload_image( request, @@ -756,10 +784,7 @@ async def image_generations( ) images.append({'url': url}) return images - elif ( - request.app.state.config.IMAGE_GENERATION_ENGINE == 'automatic1111' - or request.app.state.config.IMAGE_GENERATION_ENGINE == '' - ): + elif image_config.IMAGE_GENERATION_ENGINE == 'automatic1111' or image_config.IMAGE_GENERATION_ENGINE == '': if form_data.model: await set_image_model(request, form_data.model) @@ -770,20 +795,20 @@ async def image_generations( 'height': height, } - if request.app.state.config.IMAGE_STEPS is not None or form_data.steps is not None: - data['steps'] = form_data.steps if form_data.steps is not None else request.app.state.config.IMAGE_STEPS + if image_config.IMAGE_STEPS is not None or form_data.steps is not None: + data['steps'] = form_data.steps if form_data.steps is not None else image_config.IMAGE_STEPS if form_data.negative_prompt is not None: data['negative_prompt'] = form_data.negative_prompt - if request.app.state.config.AUTOMATIC1111_PARAMS: - data = {**data, **request.app.state.config.AUTOMATIC1111_PARAMS} + if image_config.AUTOMATIC1111_PARAMS: + data = {**data, **image_config.AUTOMATIC1111_PARAMS} session = await get_session() async with session.post( - url=f'{request.app.state.config.AUTOMATIC1111_BASE_URL}/sdapi/v1/txt2img', + url=f'{image_config.AUTOMATIC1111_BASE_URL}/sdapi/v1/txt2img', json=data, - headers={'authorization': get_automatic1111_api_auth(request)}, + headers={'authorization': get_automatic1111_api_auth(image_config)}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as r: res = await r.json(content_type=None) @@ -820,23 +845,61 @@ class EditImageForm(BaseModel): @router.post('/edit') +async def edit_images(request: Request, form_data: EditImageForm, user=Depends(get_verified_user)): + # Authorize the direct route like /generations and the edit_image tool: enforce the + # global image-edit switch and the per-user image-generation permission. The internal + # callers (edit_image tool, chat middleware) gate themselves and call image_edits() + # directly, so they are unaffected by this wrapper. + image_config = await get_image_config() + if not image_config.ENABLE_IMAGE_EDIT: + raise HTTPException( + status_code=403, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + if user.role != 'admin' and not await has_permission( + user.id, 'features.image_generation', image_config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=403, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + result = await image_edits(request, form_data, user=user) + await publish_event( + request, + EVENTS.IMAGE_EDITED, + actor=user, + subject_id=None, + subject_type='image', + data={ + 'model': form_data.model, + 'size': form_data.size, + 'n': form_data.n, + 'prompt_preview': form_data.prompt[:300], + }, + ) + return result + + async def image_edits( request: Request, form_data: EditImageForm, metadata: dict | None = None, user=Depends(get_verified_user), ): + image_config = await get_image_config() size = None width, height = None, None metadata = metadata or {} - if (request.app.state.config.IMAGE_EDIT_SIZE and 'x' in request.app.state.config.IMAGE_EDIT_SIZE) or ( + if (image_config.IMAGE_EDIT_SIZE and 'x' in image_config.IMAGE_EDIT_SIZE) or ( form_data.size and 'x' in form_data.size ): - size = form_data.size if form_data.size else request.app.state.config.IMAGE_EDIT_SIZE + size = form_data.size if form_data.size else image_config.IMAGE_EDIT_SIZE width, height = tuple(map(int, size.split('x'))) - model = request.app.state.config.IMAGE_EDIT_MODEL if form_data.model is None else form_data.model + model = image_config.IMAGE_EDIT_MODEL if form_data.model is None else form_data.model try: @@ -850,15 +913,17 @@ async def image_edits( # called only on the originally-submitted URL; following 3xx redirects # without re-validation would let an attacker reach private IPs via a # public host that redirects internally (e.g. cloud-metadata exfil). - validate_url(data) - session = await get_session() - async with session.get( - data, ssl=AIOHTTP_CLIENT_SESSION_SSL, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS - ) as r: - r.raise_for_status() + await asyncio.to_thread(validate_url, data) + # SSRF-safe session: re-checks the connect-time IP so a rebinding DNS answer + # that passed validate_url cannot reach an internal address. + async with get_ssrf_safe_session() as session: + async with session.get( + data, ssl=AIOHTTP_CLIENT_SESSION_SSL, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS + ) as r: + r.raise_for_status() - image_data = base64.b64encode(await r.read()).decode('utf-8') - return f'data:{r.headers["content-type"]};base64,{image_data}' + image_data = base64.b64encode(await r.read()).decode('utf-8') + return f'data:{r.headers["content-type"]};base64,{image_data}' else: file_id = None @@ -885,27 +950,18 @@ async def image_edits( elif isinstance(form_data.image, list): # Load all images in parallel for better performance form_data.image = list(await asyncio.gather(*[load_url_image(img) for img in form_data.image])) + except HTTPException: + raise except Exception as e: - raise HTTPException(status_code=400, detail=ERROR_MESSAGES.DEFAULT(e)) - - def get_image_file_item(base64_string, param_name='image'): - data = base64_string - header, encoded = data.split(',', 1) - mime_type = header.split(';')[0].lstrip('data:') - image_data = base64.b64decode(encoded) - return ( - param_name, - ( - f'{uuid.uuid4()}.png', - io.BytesIO(image_data), - mime_type if mime_type else 'image/png', - ), + raise HTTPException( + status_code=400, + detail=ERROR_MESSAGES.DEFAULT(e, 'Error loading image'), ) try: - if request.app.state.config.IMAGE_EDIT_ENGINE == 'openai': + if image_config.IMAGE_EDIT_ENGINE == 'openai': headers = { - 'Authorization': f'Bearer {request.app.state.config.IMAGES_EDIT_OPENAI_API_KEY}', + 'Authorization': f'Bearer {image_config.IMAGES_EDIT_OPENAI_API_KEY}', } if ENABLE_FORWARD_USER_INFO_HEADERS: @@ -921,7 +977,7 @@ async def image_edits( {} if re.match( IMAGE_URL_RESPONSE_MODELS_REGEX_PATTERN, - request.app.state.config.IMAGE_EDIT_MODEL, + image_config.IMAGE_EDIT_MODEL, ) else {'response_format': 'b64_json'} ), @@ -929,14 +985,19 @@ async def image_edits( files = [] if isinstance(form_data.image, str): - files = [get_image_file_item(form_data.image)] + image = form_data.image + if ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION: + image = normalize_openai_edit_image_data_url(image) + files = [get_image_file_item(image)] elif isinstance(form_data.image, list): for img in form_data.image: + if ENABLE_OPENAI_IMAGE_EDIT_NORMALIZATION: + img = normalize_openai_edit_image_data_url(img) files.append(get_image_file_item(img, 'image[]')) url_search_params = '' - if request.app.state.config.IMAGES_EDIT_OPENAI_API_VERSION: - url_search_params += f'?api-version={request.app.state.config.IMAGES_EDIT_OPENAI_API_VERSION}' + if image_config.IMAGES_EDIT_OPENAI_API_VERSION: + url_search_params += f'?api-version={image_config.IMAGES_EDIT_OPENAI_API_VERSION}' # Build multipart form data for aiohttp form = aiohttp.FormData() @@ -955,7 +1016,7 @@ async def image_edits( session = await get_session() async with session.post( - url=f'{request.app.state.config.IMAGES_EDIT_OPENAI_API_BASE_URL}/images/edits{url_search_params}', + url=f'{image_config.IMAGES_EDIT_OPENAI_API_BASE_URL}/images/edits{url_search_params}', headers=headers, data=form, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -977,10 +1038,10 @@ async def image_edits( images.append({'url': url}) return images - elif request.app.state.config.IMAGE_EDIT_ENGINE == 'gemini': + elif image_config.IMAGE_EDIT_ENGINE == 'gemini': headers = { 'Content-Type': 'application/json', - 'x-goog-api-key': request.app.state.config.IMAGES_EDIT_GEMINI_API_KEY, + 'x-goog-api-key': image_config.IMAGES_EDIT_GEMINI_API_KEY, } model = f'{model}:generateContent' @@ -1010,7 +1071,7 @@ async def image_edits( session = await get_session() async with session.post( - url=f'{request.app.state.config.IMAGES_EDIT_GEMINI_API_BASE_URL}/models/{model}', + url=f'{image_config.IMAGES_EDIT_GEMINI_API_BASE_URL}/models/{model}', json=data, headers=headers, ssl=AIOHTTP_CLIENT_SESSION_SSL, @@ -1034,7 +1095,7 @@ async def image_edits( return images - elif request.app.state.config.IMAGE_EDIT_ENGINE == 'comfyui': + elif image_config.IMAGE_EDIT_ENGINE == 'comfyui': try: files = [] if isinstance(form_data.image, str): @@ -1048,8 +1109,8 @@ async def image_edits( for file_item in files: res = await comfyui_upload_image( file_item, - request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL, - request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY, + image_config.IMAGES_EDIT_COMFYUI_BASE_URL, + image_config.IMAGES_EDIT_COMFYUI_API_KEY, ) comfyui_images.append(res.get('name', file_item[1][0])) except Exception as e: @@ -1068,8 +1129,8 @@ async def image_edits( **{ 'workflow': ComfyUIWorkflow( **{ - 'workflow': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW, - 'nodes': request.app.state.config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, + 'workflow': image_config.IMAGES_EDIT_COMFYUI_WORKFLOW, + 'nodes': image_config.IMAGES_EDIT_COMFYUI_WORKFLOW_NODES, } ), **data, @@ -1079,8 +1140,8 @@ async def image_edits( model, form_data, str(uuid.uuid4()), - request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL, - request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY, + image_config.IMAGES_EDIT_COMFYUI_BASE_URL, + image_config.IMAGES_EDIT_COMFYUI_API_KEY, ) log.debug(f'res: {res}') @@ -1099,13 +1160,13 @@ async def image_edits( for image_url in image_urls: headers = None - if request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY: - headers = {'Authorization': f'Bearer {request.app.state.config.IMAGES_EDIT_COMFYUI_API_KEY}'} + if image_config.IMAGES_EDIT_COMFYUI_API_KEY: + headers = {'Authorization': f'Bearer {image_config.IMAGES_EDIT_COMFYUI_API_KEY}'} image_data, content_type = await get_image_data( image_url, headers, - trusted_base_url=request.app.state.config.IMAGES_EDIT_COMFYUI_BASE_URL, + trusted_base_url=image_config.IMAGES_EDIT_COMFYUI_BASE_URL, ) _, url = await upload_image( request, diff --git a/backend/open_webui/routers/knowledge.py b/backend/open_webui/routers/knowledge.py index 3506986429..b7a5772c1d 100644 --- a/backend/open_webui/routers/knowledge.py +++ b/backend/open_webui/routers/knowledge.py @@ -2,7 +2,10 @@ from __future__ import annotations import asyncio import io +import json import logging +import time +import uuid import zipfile from typing import List, Optional from urllib.parse import quote @@ -11,8 +14,10 @@ from fastapi import APIRouter, Depends, HTTPException, Query, Request, status from fastapi.responses import StreamingResponse from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.files import FileMetadataResponse, FileModel, FileModelResponse, Files from open_webui.models.groups import Groups from open_webui.models.knowledge import ( @@ -26,6 +31,7 @@ from open_webui.models.knowledge import ( ) from open_webui.models.models import ModelForm, Models from open_webui.retrieval.vector.async_client import ASYNC_VECTOR_DB_CLIENT +from open_webui.retrieval.external import retrieve_external_knowledge, retrieve_external_knowledge_for_connection from open_webui.routers.retrieval import ( BatchProcessFilesForm, ProcessFileForm, @@ -109,6 +115,17 @@ class KnowledgeAccessListResponse(BaseModel): total: int +def is_external_knowledge(knowledge) -> bool: + return (knowledge.meta or {}).get('source') == 'external' + + +def external_knowledge_error(): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='External knowledge bases are read-only.', + ) + + @router.get('/', response_model=KnowledgeAccessListResponse) async def get_knowledge_bases( page: int | None = 1, @@ -162,6 +179,7 @@ async def get_knowledge_bases( async def search_knowledge_bases( query: str | None = None, view_option: str | None = None, + source: str | None = None, page: int | None = 1, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), @@ -175,6 +193,8 @@ async def search_knowledge_bases( filter['query'] = query if view_option: filter['view_option'] = view_option + if source in {'local', 'external'}: + filter['source'] = source groups = await Groups.get_groups_by_member_id(user.id, db=db) user_group_ids = {group.id for group in groups} @@ -257,7 +277,7 @@ async def create_new_knowledge( # This prevents holding a connection during embed_knowledge_base_metadata() # which makes external embedding API calls (1-5+ seconds). if user.role != 'admin' and not await has_permission( - user.id, 'workspace.knowledge', request.app.state.config.USER_PERMISSIONS + user.id, 'workspace.knowledge', await Config.get('user.permissions') ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -265,7 +285,7 @@ async def create_new_knowledge( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -282,6 +302,13 @@ async def create_new_knowledge( knowledge.name, knowledge.description, ) + await publish_event( + request, + EVENTS.KNOWLEDGE_CREATED, + actor=user, + subject_id=knowledge.id, + data={'name': knowledge.name}, + ) return knowledge else: raise HTTPException( @@ -308,12 +335,19 @@ async def reindex_knowledge_files( ) knowledge_bases = await Knowledges.get_knowledge_bases(db=db) + knowledge_base_files = [ + (knowledge_base, await Knowledges.get_files_by_id(knowledge_base.id, db=db)) + for knowledge_base in knowledge_bases + ] + total_files = sum(len(files) for _, files in knowledge_base_files) + processed_files = 0 + failed_files = [] + start_time = time.monotonic() - log.info(f'Starting reindexing for {len(knowledge_bases)} knowledge bases') + log.info(f'Starting reindexing for {len(knowledge_bases)} knowledge bases ({total_files} files)') - for knowledge_base in knowledge_bases: + for kb_idx, (knowledge_base, files) in enumerate(knowledge_base_files, start=1): try: - files = await Knowledges.get_files_by_id(knowledge_base.id, db=db) try: if await ASYNC_VECTOR_DB_CLIENT.has_collection(collection_name=knowledge_base.id): await ASYNC_VECTOR_DB_CLIENT.delete_collection(collection_name=knowledge_base.id) @@ -321,8 +355,19 @@ async def reindex_knowledge_files( log.error(f'Error deleting collection {knowledge_base.id}: {str(e)}') continue # Skip, don't raise - failed_files = [] for file in files: + processed_files += 1 + eta = '' + if processed_files > 1: + elapsed = time.monotonic() - start_time + remaining_files = total_files - processed_files + 1 + eta = f', ETA: {round(elapsed / (processed_files - 1) * remaining_files)}s' + + log.info( + f'Reindexing knowledge base {kb_idx}/{len(knowledge_bases)} ' + f'file {processed_files}/{total_files}{eta}: {file.filename}' + ) + try: await process_file( request, @@ -340,12 +385,19 @@ async def reindex_knowledge_files( # Don't raise, just continue continue - if failed_files: - log.warning(f'Failed to process {len(failed_files)} files in knowledge base {knowledge_base.id}') - for failed in failed_files: - log.warning(f'File ID: {failed["file_id"]}, Error: {failed["error"]}') + if failed_files: + log.warning(f'Failed to process {len(failed_files)} files') + for failed in failed_files: + log.warning(f'File ID: {failed["file_id"]}, Error: {failed["error"]}') - log.info(f'Reindexing completed.') + log.info(f'Reindexing completed in {round(time.monotonic() - start_time)}s.') + await publish_event( + request, + EVENTS.KNOWLEDGE_REINDEXED, + actor=user, + subject_id='all', + data={'count': len(knowledge_bases)}, + ) return True @@ -378,6 +430,602 @@ async def reindex_knowledge_base_metadata_embeddings( return {'total': len(knowledge_bases), 'success': success_count} +############################ +# External Knowledge Sources +############################ + + +class ExternalKnowledgeSourceForm(BaseModel): + type: str = 'collection' + name: str + config: Optional[dict] = None + + +class ExternalKnowledgeCreateForm(BaseModel): + name: str + description: str = '' + connection_id: str + source: ExternalKnowledgeSourceForm + access_grants: Optional[list[dict]] = None + + +class ExternalKnowledgeSourceCreateForm(BaseModel): + name: str + description: str = '' + connection: ExternalKnowledgeConnectionForm + source: ExternalKnowledgeSourceForm + access_grants: Optional[list[dict]] = None + test_query: str + test_count: int = 5 + + +class ExternalKnowledgeSourceUpdateForm(ExternalKnowledgeSourceCreateForm): + pass + + +class ExternalKnowledgeSourceTestForm(BaseModel): + connection_id: Optional[str] = None + connection: ExternalKnowledgeConnectionForm + source: ExternalKnowledgeSourceForm + query: str + count: int = 5 + + +class ExternalKnowledgeRetrieveTestForm(BaseModel): + query: str + source: Optional[ExternalKnowledgeSourceForm] = None + count: int = 5 + + +class ExternalKnowledgeConnectionForm(BaseModel): + name: str + provider: str + endpoint: str + auth_config: Optional[dict] = None + config: Optional[dict] = None + capabilities: Optional[dict] = None + enabled: bool = True + + +class ExternalKnowledgeConnectionListResponse(BaseModel): + items: list[dict] + total: int + + +EXTERNAL_KNOWLEDGE_CONNECTIONS_CONFIG_KEY = 'external_knowledge.connections' +EXTERNAL_KNOWLEDGE_PROVIDERS = {'qdrant', 'milvus', 'pgvector'} + + +def _validate_external_connection_form(form_data: ExternalKnowledgeConnectionForm) -> tuple[str, dict]: + provider = form_data.provider.lower().strip() + if provider not in EXTERNAL_KNOWLEDGE_PROVIDERS: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='Unsupported external knowledge provider.', + ) + + if not form_data.name.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Knowledge source name is required.') + + if not form_data.endpoint.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Knowledge source endpoint is required.') + + config = form_data.config or {} + allowed_config_keys = {'timeout'} + if provider == 'milvus': + allowed_config_keys.add('db_name') + + return provider, {key: value for key, value in config.items() if key in allowed_config_keys} + + +def _external_auth_config(provider: str, incoming: Optional[dict], existing: Optional[dict] = None) -> dict: + if provider == 'pgvector': + return {} + return existing if incoming is None else incoming or {} + + +def _normalize_external_source(source: ExternalKnowledgeSourceForm, provider: str) -> ExternalKnowledgeSourceForm: + source.type = (source.type or 'collection').strip() + source.name = source.name.strip() + + if source.type != 'collection': + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Only collection sources are supported.') + if not source.name: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Collection name is required.') + + config = source.config or {} + allowed_keys = {'content_field', 'metadata_field', 'document_id_field'} + if provider in {'qdrant', 'milvus'}: + allowed_keys.add('vector_field') + if provider == 'pgvector': + allowed_keys.update({'table_name', 'collection_field', 'vector_field'}) + + normalized_config = { + key: value.strip() if isinstance(value, str) else value + for key, value in config.items() + if key in allowed_keys and value is not None and (not isinstance(value, str) or value.strip()) + } + + if not normalized_config.get('content_field'): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Content field is required.') + if provider in {'milvus', 'pgvector'} and not normalized_config.get('vector_field'): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Vector field is required.') + + source.config = normalized_config + return source + + +def _sanitize_external_connection(connection: dict) -> dict: + sanitized = {**connection} + sanitized.pop('auth_config', None) + sanitized['auth_configured'] = bool(connection.get('auth_config')) + return sanitized + + +async def _get_external_connections() -> list[dict]: + return await Config.get(EXTERNAL_KNOWLEDGE_CONNECTIONS_CONFIG_KEY, []) or [] + + +async def _set_external_connections(connections: list[dict]) -> None: + await Config.upsert({EXTERNAL_KNOWLEDGE_CONNECTIONS_CONFIG_KEY: connections}) + + +def _external_connection_dict( + form_data: ExternalKnowledgeConnectionForm, user_id: str, id: Optional[str] = None +) -> dict: + provider, config = _validate_external_connection_form(form_data) + now = int(time.time()) + return { + 'id': id or str(uuid.uuid4()), + 'name': form_data.name.strip(), + 'provider': provider, + 'endpoint': form_data.endpoint.strip(), + 'auth_config': _external_auth_config(provider, form_data.auth_config), + 'config': config, + 'capabilities': form_data.capabilities or {'retrieve': True}, + 'health': None, + 'enabled': form_data.enabled, + 'created_by': user_id, + 'created_at': now, + 'updated_at': now, + } + + +def _external_connection_update_dict( + form_data: ExternalKnowledgeConnectionForm, + existing: dict, +) -> dict: + provider, config = _validate_external_connection_form(form_data) + return { + **existing, + 'name': form_data.name.strip(), + 'provider': provider, + 'endpoint': form_data.endpoint.strip(), + 'auth_config': _external_auth_config(provider, form_data.auth_config, existing.get('auth_config')) or {}, + 'config': config, + 'capabilities': form_data.capabilities or {'retrieve': True}, + 'enabled': form_data.enabled, + 'updated_at': int(time.time()), + } + + +async def _get_external_connection(id: str) -> Optional[dict]: + connections = await _get_external_connections() + return next((connection for connection in connections if connection.get('id') == id), None) + + +async def _count_external_connection_mappings(connection_id: str, db: Optional[AsyncSession] = None) -> int: + count = 0 + for knowledge in await Knowledges.get_knowledge_bases(db=db): + if (knowledge.meta or {}).get('external', {}).get('connection_id') == connection_id: + count += 1 + return count + + +@router.get('/external/connections', response_model=ExternalKnowledgeConnectionListResponse) +async def get_external_knowledge_connections( + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connections = [_sanitize_external_connection(connection) for connection in await _get_external_connections()] + return ExternalKnowledgeConnectionListResponse(items=connections, total=len(connections)) + + +@router.post('/external/connections', response_model=dict) +async def create_external_knowledge_connection( + request: Request, + form_data: ExternalKnowledgeConnectionForm, + user=Depends(get_admin_user), +): + connections = await _get_external_connections() + connection = _external_connection_dict(form_data, user.id) + connections.append(connection) + await _set_external_connections(connections) + sanitized = _sanitize_external_connection(connection) + await publish_event( + request, + EVENTS.KNOWLEDGE_EXTERNAL_CONNECTION_CREATED, + actor=user, + subject_id=connection.get('id'), + data={'name': sanitized.get('name'), 'provider': sanitized.get('provider')}, + ) + return sanitized + + +@router.get('/external/connections/{id}', response_model=dict) +async def get_external_knowledge_connection( + id: str, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connection = await _get_external_connection(id) + if not connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + return _sanitize_external_connection(connection) + + +@router.patch('/external/connections/{id}', response_model=dict) +async def update_external_knowledge_connection( + request: Request, + id: str, + form_data: ExternalKnowledgeConnectionForm, + user=Depends(get_admin_user), +): + connections = await _get_external_connections() + idx = next((idx for idx, connection in enumerate(connections) if connection.get('id') == id), None) + if idx is None: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + + connection = _external_connection_update_dict(form_data, connections[idx]) + connections[idx] = connection + await _set_external_connections(connections) + sanitized = _sanitize_external_connection(connection) + await publish_event( + request, + EVENTS.KNOWLEDGE_EXTERNAL_CONNECTION_UPDATED, + actor=user, + subject_id=id, + data={'name': sanitized.get('name'), 'provider': sanitized.get('provider')}, + ) + return sanitized + + +@router.delete('/external/connections/{id}', response_model=bool) +async def delete_external_knowledge_connection( + request: Request, + id: str, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connection = await _get_external_connection(id) + if not connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + + if await _count_external_connection_mappings(id, db=db) > 0: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail='External connection is still used by knowledge bases.', + ) + + connections = [connection for connection in await _get_external_connections() if connection.get('id') != id] + await _set_external_connections(connections) + await publish_event( + request, + EVENTS.KNOWLEDGE_EXTERNAL_CONNECTION_DELETED, + actor=user, + subject_id=id, + data={'name': connection.get('name'), 'provider': connection.get('provider')}, + ) + return True + + +@router.post('/external/connections/{id}/test', response_model=dict) +async def test_external_knowledge_connection( + id: str, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connection = await _get_external_connection(id) + if not connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + + health = { + 'ok': bool(connection.get('enabled') and connection.get('endpoint')), + 'provider': connection.get('provider'), + 'checked_at': int(time.time()), + } + connections = await _get_external_connections() + for item in connections: + if item.get('id') == id: + item['health'] = health + item['updated_at'] = int(time.time()) + break + await _set_external_connections(connections) + return health + + +async def _test_external_source_definition( + request: Request, + connection: dict, + source: ExternalKnowledgeSourceForm, + query: str, + count: int, + user, +) -> dict: + if not query.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Test query is required.') + + source = _normalize_external_source(source, connection.get('provider')) + test_knowledge = KnowledgeResponse( + id='external-test', + user_id=user.id, + name=connection.get('name'), + description='', + meta={ + 'source': 'external', + 'read_only': True, + 'external': { + 'connection_id': connection.get('id'), + 'source': source.model_dump(), + 'provider': connection.get('provider'), + 'auth_mode': 'service_account', + 'capabilities': {'retrieve': True}, + }, + }, + access_grants=[], + created_at=int(time.time()), + updated_at=int(time.time()), + ) + result = await retrieve_external_knowledge_for_connection( + request, + test_knowledge, + connection, + [query.strip()], + count, + user=user, + ) + return { + 'documents': result.get('documents', [[]])[0], + 'metadatas': result.get('metadatas', [[]])[0], + 'distances': result.get('distances', [[]])[0], + } + + +@router.post('/external/source/test', response_model=dict) +async def test_external_knowledge_source( + request: Request, + form_data: ExternalKnowledgeSourceTestForm, + user=Depends(get_admin_user), +): + if form_data.connection_id: + existing_connection = await _get_external_connection(form_data.connection_id) + if not existing_connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='External connection not found.') + connection = _external_connection_update_dict(form_data.connection, existing_connection) + else: + connection = _external_connection_dict(form_data.connection, user.id, id='external-test') + + return await _test_external_source_definition( + request, + connection, + form_data.source, + form_data.query, + form_data.count, + user, + ) + + +@router.post('/external/connections/{id}/retrieve-test', response_model=dict) +async def test_external_knowledge_retrieval( + request: Request, + id: str, + form_data: ExternalKnowledgeRetrieveTestForm, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connection = await _get_external_connection(id) + if not connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + + source = form_data.source or ExternalKnowledgeSourceForm(name='test', config={'content_field': 'payload.text'}) + return await _test_external_source_definition(request, connection, source, form_data.query, form_data.count, user) + + +@router.post('/external/knowledge/create', response_model=KnowledgeResponse | None) +async def create_external_knowledge( + request: Request, + form_data: ExternalKnowledgeCreateForm, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + connection = await _get_external_connection(form_data.connection_id) + if not connection: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + if not form_data.name.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Knowledge name is required.') + source = _normalize_external_source(form_data.source, connection.get('provider')) + + form_data.access_grants = await filter_allowed_access_grants( + await Config.get('user.permissions'), + user.id, + user.role, + form_data.access_grants, + 'sharing.public_knowledge', + ) + + knowledge = await Knowledges.insert_new_knowledge( + user.id, + KnowledgeForm( + name=form_data.name.strip(), + description=form_data.description, + access_grants=form_data.access_grants, + ), + db=db, + ) + if not knowledge: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FILE_EXISTS) + + meta = { + 'source': 'external', + 'read_only': True, + 'external': { + 'connection_id': form_data.connection_id, + 'source': source.model_dump(), + 'provider': connection.get('provider'), + 'auth_mode': 'service_account', + 'capabilities': {'retrieve': True}, + }, + } + knowledge = await Knowledges.update_knowledge_meta_by_id(knowledge.id, meta, db=db) + await embed_knowledge_base_metadata(request, knowledge.id, knowledge.name, knowledge.description) + return knowledge + + +@router.post('/external/source/create', response_model=KnowledgeResponse | None) +async def create_external_knowledge_source( + request: Request, + form_data: ExternalKnowledgeSourceCreateForm, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + if not form_data.name.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Knowledge name is required.') + + connection = _external_connection_dict(form_data.connection, user.id) + source = _normalize_external_source(form_data.source, connection.get('provider')) + test_result = await _test_external_source_definition( + request, + connection, + source, + form_data.test_query, + form_data.test_count, + user, + ) + if not test_result.get('documents'): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Test query returned no results.') + + form_data.access_grants = await filter_allowed_access_grants( + await Config.get('user.permissions'), + user.id, + user.role, + form_data.access_grants, + 'sharing.public_knowledge', + ) + + connections = await _get_external_connections() + connections.append(connection) + await _set_external_connections(connections) + + knowledge = await Knowledges.insert_new_knowledge( + user.id, + KnowledgeForm( + name=form_data.name.strip(), + description=form_data.description, + access_grants=form_data.access_grants, + ), + db=db, + ) + if not knowledge: + connections = [item for item in await _get_external_connections() if item.get('id') != connection.get('id')] + await _set_external_connections(connections) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FILE_EXISTS) + + meta = { + 'source': 'external', + 'read_only': True, + 'external': { + 'connection_id': connection.get('id'), + 'source': source.model_dump(), + 'provider': connection.get('provider'), + 'auth_mode': 'service_account', + 'capabilities': {'retrieve': True}, + }, + } + knowledge = await Knowledges.update_knowledge_meta_by_id(knowledge.id, meta, db=db) + await embed_knowledge_base_metadata(request, knowledge.id, knowledge.name, knowledge.description) + return knowledge + + +@router.patch('/external/source/{id}', response_model=KnowledgeResponse | None) +async def update_external_knowledge_source( + request: Request, + id: str, + form_data: ExternalKnowledgeSourceUpdateForm, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + knowledge = await Knowledges.get_knowledge_by_id(id=id, db=db) + if not knowledge or not is_external_knowledge(knowledge): + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND) + if not form_data.name.strip(): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Knowledge name is required.') + + connection_id = (knowledge.meta or {}).get('external', {}).get('connection_id') + connections = await _get_external_connections() + idx = next((idx for idx, connection in enumerate(connections) if connection.get('id') == connection_id), None) + if idx is None: + raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail='External connection not found.') + + existing_connection = connections[idx] + connection = _external_connection_update_dict(form_data.connection, existing_connection) + source = _normalize_external_source(form_data.source, connection.get('provider')) + test_result = await _test_external_source_definition( + request, + connection, + source, + form_data.test_query, + form_data.test_count, + user, + ) + if not test_result.get('documents'): + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail='Test query returned no results.') + + form_data.access_grants = await filter_allowed_access_grants( + await Config.get('user.permissions'), + user.id, + user.role, + form_data.access_grants, + 'sharing.public_knowledge', + ) + + connections[idx] = connection + await _set_external_connections(connections) + + updated = await Knowledges.update_knowledge_by_id( + id=id, + form_data=KnowledgeForm( + name=form_data.name.strip(), + description=form_data.description, + access_grants=form_data.access_grants, + ), + db=db, + ) + if not updated: + connections[idx] = existing_connection + await _set_external_connections(connections) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + + meta = { + 'source': 'external', + 'read_only': True, + 'external': { + 'connection_id': connection.get('id'), + 'source': source.model_dump(), + 'provider': connection.get('provider'), + 'auth_mode': 'service_account', + 'capabilities': {'retrieve': True}, + }, + } + updated = await Knowledges.update_knowledge_meta_by_id(id, meta, db=db) + if not updated: + connections[idx] = existing_connection + await _set_external_connections(connections) + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + + await embed_knowledge_base_metadata(request, id, updated.name, updated.description) + return updated + + ############################ # GetKnowledgeById ############################ @@ -469,7 +1117,7 @@ async def update_knowledge_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -485,10 +1133,18 @@ async def update_knowledge_by_id( knowledge.name, knowledge.description, ) - return KnowledgeFilesResponse( + response = KnowledgeFilesResponse( **knowledge.model_dump(), files=await Knowledges.get_file_metadatas_by_id(knowledge.id), ) + await publish_event( + request, + EVENTS.KNOWLEDGE_UPDATED, + actor=user, + subject_id=knowledge.id, + data={'name': knowledge.name}, + ) + return response else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -537,7 +1193,7 @@ async def update_knowledge_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -546,10 +1202,18 @@ async def update_knowledge_access_by_id( knowledge.access_grants = await AccessGrants.set_access_grants('knowledge', id, form_data.access_grants, db=db) - return KnowledgeFilesResponse( + response = KnowledgeFilesResponse( **knowledge.model_dump(), files=await Knowledges.get_file_metadatas_by_id(id, db=db), ) + await publish_event( + request, + EVENTS.KNOWLEDGE_ACCESS_UPDATED, + actor=user, + subject_id=knowledge.id, + data={'name': knowledge.name}, + ) + return response ############################ @@ -710,6 +1374,8 @@ async def add_file_to_knowledge_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id @@ -772,10 +1438,18 @@ async def add_file_to_knowledge_by_id( ) if knowledge: - return KnowledgeFilesResponse( + response = KnowledgeFilesResponse( **knowledge.model_dump(), files=await Knowledges.get_file_metadatas_by_id(knowledge.id, db=db), ) + await publish_event( + request, + EVENTS.KNOWLEDGE_FILE_ADDED, + actor=user, + subject_id=form_data.file_id, + data={'knowledge_id': knowledge.id, 'directory_id': form_data.directory_id}, + ) + return response else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -797,6 +1471,8 @@ async def update_file_from_knowledge_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id @@ -846,10 +1522,18 @@ async def update_file_from_knowledge_by_id( ) if knowledge: - return KnowledgeFilesResponse( + response = KnowledgeFilesResponse( **knowledge.model_dump(), files=await Knowledges.get_file_metadatas_by_id(knowledge.id, db=db), ) + await publish_event( + request, + EVENTS.KNOWLEDGE_FILE_UPDATED, + actor=user, + subject_id=form_data.file_id, + data={'knowledge_id': knowledge.id}, + ) + return response else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -864,6 +1548,7 @@ async def update_file_from_knowledge_by_id( @router.post('/{id}/file/remove', response_model=KnowledgeFilesResponse | None) async def remove_file_from_knowledge_by_id( + request: Request, id: str, form_data: KnowledgeFileIdForm, delete_file: bool = Query(True), @@ -876,6 +1561,8 @@ async def remove_file_from_knowledge_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id @@ -939,10 +1626,18 @@ async def remove_file_from_knowledge_by_id( await Files.delete_file_by_id(form_data.file_id, db=db) if knowledge: - return KnowledgeFilesResponse( + response = KnowledgeFilesResponse( **knowledge.model_dump(), files=await Knowledges.get_file_metadatas_by_id(knowledge.id, db=db), ) + await publish_event( + request, + EVENTS.KNOWLEDGE_FILE_REMOVED, + actor=user, + subject_id=form_data.file_id, + data={'knowledge_id': knowledge.id, 'delete_file': delete_file}, + ) + return response else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -957,7 +1652,10 @@ async def remove_file_from_knowledge_by_id( @router.delete('/{id}/delete', response_model=bool) async def delete_knowledge_by_id( - id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, + id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), ): knowledge = await Knowledges.get_knowledge_by_id(id=id, db=db) if not knowledge: @@ -1003,16 +1701,32 @@ async def delete_knowledge_by_id( await Models.update_model_by_id(model.id, model_form, db=db) # Clean up vector DB - try: - await ASYNC_VECTOR_DB_CLIENT.delete_collection(collection_name=id) - except Exception as e: - log.debug(e) - pass + if is_external_knowledge(knowledge): + connection_id = (knowledge.meta or {}).get('external', {}).get('connection_id') + if connection_id: + connections = [ + connection for connection in await _get_external_connections() if connection.get('id') != connection_id + ] + await _set_external_connections(connections) + else: + try: + await ASYNC_VECTOR_DB_CLIENT.delete_collection(collection_name=id) + except Exception as e: + log.debug(e) + pass # Remove knowledge base embedding await remove_knowledge_base_metadata_embedding(id) result = await Knowledges.delete_knowledge_by_id(id=id, db=db) + if result: + await publish_event( + request, + EVENTS.KNOWLEDGE_DELETED, + actor=user, + subject_id=id, + data={'name': knowledge.name}, + ) return result @@ -1023,6 +1737,7 @@ async def delete_knowledge_by_id( @router.post('/{id}/reset', response_model=KnowledgeResponse | None) async def reset_knowledge_by_id( + request: Request, id: str, include_directories: bool = Query(True), user=Depends(get_verified_user), @@ -1034,6 +1749,8 @@ async def reset_knowledge_by_id( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id @@ -1058,6 +1775,14 @@ async def reset_knowledge_by_id( pass knowledge = await Knowledges.reset_knowledge_by_id(id=id, include_directories=include_directories, db=db) + if knowledge: + await publish_event( + request, + EVENTS.KNOWLEDGE_RESET, + actor=user, + subject_id=id, + data={'include_directories': include_directories}, + ) return knowledge @@ -1262,6 +1987,8 @@ async def add_files_to_knowledge_batch( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id @@ -1379,6 +2106,8 @@ async def export_knowledge_by_id(id: str, user=Depends(get_admin_user), db: Asyn status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() files = await Knowledges.get_files_by_id(id, db=db) @@ -1397,18 +2126,13 @@ async def export_knowledge_by_id(id: str, user=Depends(get_admin_user), db: Asyn zip_buffer.seek(0) # Sanitize knowledge name for filename - # ASCII-safe fallback for the basic filename parameter (latin-1 safe) - safe_name = ''.join(c if c.isascii() and (c.isalnum() or c in ' -_') else '_' for c in knowledge.name) + safe_name = ''.join(c if c.isalnum() or c in ' -_' else '_' for c in knowledge.name) zip_filename = f'{safe_name}.zip' - # Use RFC 5987 filename* for non-ASCII names so the browser gets the real name - quoted_name = quote(f'{knowledge.name}.zip') - content_disposition = f'attachment; filename="{zip_filename}"; filename*=UTF-8\'\'{quoted_name}' - return StreamingResponse( zip_buffer, media_type='application/zip', - headers={'Content-Disposition': content_disposition}, + headers={'Content-Disposition': f"attachment; filename*=UTF-8''{quote(zip_filename, safe='')}"}, ) @@ -1440,6 +2164,8 @@ async def _verify_knowledge_write_access(id: str, user, db: AsyncSession): status_code=status.HTTP_404_NOT_FOUND, detail=ERROR_MESSAGES.NOT_FOUND, ) + if is_external_knowledge(knowledge): + external_knowledge_error() if ( knowledge.user_id != user.id and not await AccessGrants.has_access( @@ -1460,6 +2186,7 @@ async def _verify_knowledge_write_access(id: str, user, db: AsyncSession): @router.post('/{id}/dirs/create', response_model=KnowledgeDirectoryModel) async def create_knowledge_directory( + request: Request, id: str, form_data: KnowledgeDirectoryCreateForm, user=Depends(get_verified_user), @@ -1479,11 +2206,19 @@ async def create_knowledge_directory( status_code=status.HTTP_400_BAD_REQUEST, detail='Failed to create directory. A directory with this name may already exist at this level.', ) + await publish_event( + request, + EVENTS.KNOWLEDGE_DIRECTORY_CREATED, + actor=user, + subject_id=directory.id, + data={'knowledge_id': id, 'name': directory.name, 'parent_id': directory.parent_id}, + ) return directory @router.post('/{id}/dirs/{dir_id}/update', response_model=KnowledgeDirectoryModel) async def update_knowledge_directory( + request: Request, id: str, dir_id: str, form_data: KnowledgeDirectoryUpdateForm, @@ -1511,11 +2246,19 @@ async def update_knowledge_directory( status_code=status.HTTP_400_BAD_REQUEST, detail='Failed to update directory. This may be caused by a naming conflict or circular move.', ) + await publish_event( + request, + EVENTS.KNOWLEDGE_DIRECTORY_UPDATED, + actor=user, + subject_id=result.id, + data={'knowledge_id': id, 'name': result.name, 'parent_id': result.parent_id}, + ) return result @router.delete('/{id}/dirs/{dir_id}/delete') async def delete_knowledge_directory( + request: Request, id: str, dir_id: str, move_files: bool = Query(True, description='If true, move contained files to parent. If false, delete them.'), @@ -1542,11 +2285,19 @@ async def delete_knowledge_directory( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail='Failed to delete directory.', ) + await publish_event( + request, + EVENTS.KNOWLEDGE_DIRECTORY_DELETED, + actor=user, + subject_id=dir_id, + data={'knowledge_id': id, 'move_files': move_files}, + ) return {'status': True} @router.post('/{id}/file/move') async def move_file_in_knowledge( + request: Request, id: str, form_data: KnowledgeFileMoveForm, user=Depends(get_verified_user), @@ -1581,4 +2332,11 @@ async def move_file_in_knowledge( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail='Failed to move file.', ) + await publish_event( + request, + EVENTS.KNOWLEDGE_FILE_MOVED, + actor=user, + subject_id=form_data.file_id, + data={'knowledge_id': id, 'directory_id': form_data.directory_id}, + ) return {'status': True} diff --git a/backend/open_webui/routers/memories.py b/backend/open_webui/routers/memories.py index aad881b6da..8e6d50f39a 100644 --- a/backend/open_webui/routers/memories.py +++ b/backend/open_webui/routers/memories.py @@ -2,16 +2,27 @@ from __future__ import annotations import asyncio import logging -from typing import Optional +from typing import Literal from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session +from open_webui.models.config import Config from open_webui.models.memories import Memories, MemoryModel from open_webui.retrieval.vector.async_client import ASYNC_VECTOR_DB_CLIENT from open_webui.config import RAG_EMBEDDING_QUERY_PREFIX from open_webui.utils.access_control import has_permission from open_webui.utils.auth import get_verified_user +from open_webui.utils.memory import ( + clean_memory_content, + clean_memory_path, + list_memory_path_groups, + memory_vector_text, + read_memory_path_rows, + search_memory_rows, + validate_memory_operations, +) from pydantic import BaseModel from sqlalchemy.ext.asyncio import AsyncSession @@ -20,6 +31,21 @@ log = logging.getLogger(__name__) router = APIRouter() +async def check_memories_permission(user): + config = await Config.get_many('memories.enable', 'user.permissions') + if not config.get('memories.enable'): + raise HTTPException( + status_code=status.HTTP_404_NOT_FOUND, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + if user.role != 'admin' and not await has_permission(user.id, 'features.memories', config.get('user.permissions')): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + + ############################ # GetMemories # Let what is remembered here spare someone the cost @@ -33,17 +59,7 @@ async def get_memories( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_memories_permission(user) return await Memories.get_memories_by_user_id(user.id, db=db) @@ -55,10 +71,57 @@ async def get_memories( class AddMemoryForm(BaseModel): content: str + type: Literal['user', 'context'] = 'context' + path: str | None = None class MemoryUpdateModel(BaseModel): content: str | None = None + type: Literal['user', 'context'] | None = None + path: str | None = None + + +class MemoryOperationModel(BaseModel): + action: Literal['add', 'replace', 'remove', 'move'] + id: str | None = None + content: str | None = None + type: Literal['user', 'context'] | None = None + path: str | None = None + + +class UpdateMemoriesForm(BaseModel): + operations: list[MemoryOperationModel] + source: Literal['tool', 'background_review'] | None = None + + +class SearchMemoriesForm(BaseModel): + query: str | None = None + type: Literal['user', 'context', 'all'] = 'all' + path: str | None = None + memory_id: str | None = None + limit: int = 20 + + +class ListMemoryPathsForm(BaseModel): + query: str | None = None + type: Literal['user', 'context', 'all'] = 'all' + limit: int = 100 + + +class ReadMemoryPathForm(BaseModel): + path: str + type: Literal['user', 'context', 'all'] = 'all' + include_children: bool = True + limit: int = 50 + + +def _memory_metadata(memory: MemoryModel) -> dict: + return { + 'created_at': memory.created_at, + 'updated_at': memory.updated_at, + 'type': memory.type, + 'path': memory.path, + } @router.post('/add', response_model=MemoryModel | None) @@ -73,37 +136,128 @@ async def add_memory( own short-lived sessions so a connection is not held during the external embedding API call (``EMBEDDING_FUNCTION``), which can take 1-5+ seconds. """ - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) + await check_memories_permission(user) - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + content = clean_memory_content(form_data.content) + path = clean_memory_path(form_data.path) + memory = await Memories.insert_new_memory( + user.id, + content, + memory_type=form_data.type, + path=path, + meta={'created_by': 'manual'}, + ) - memory = await Memories.insert_new_memory(user.id, form_data.content) - - vector = await request.app.state.EMBEDDING_FUNCTION(memory.content, user=user) + vector = await request.app.state.EMBEDDING_FUNCTION(memory_vector_text(memory.content, memory.path), user=user) await ASYNC_VECTOR_DB_CLIENT.upsert( collection_name=f'user-memory-{user.id}', items=[ { 'id': memory.id, - 'text': memory.content, + 'text': memory_vector_text(memory.content, memory.path), 'vector': vector, - 'metadata': {'created_at': memory.created_at}, + 'metadata': _memory_metadata(memory), } ], ) + await publish_event( + request, + EVENTS.MEMORY_CREATED, + actor=user, + subject_id=memory.id, + data={'content_preview': memory.content[:300], 'type': memory.type, 'path': memory.path}, + ) return memory +@router.post('/update', response_model=list[dict]) +async def update_memories( + request: Request, + form_data: UpdateMemoriesForm, + user=Depends(get_verified_user), +): + await check_memories_permission(user) + + operations = validate_memory_operations(form_data) + metadata = getattr(request.state, 'metadata', {}) or {} + source = form_data.source or 'tool' + for operation in operations: + if operation.get('action') in {'add', 'replace', 'move'}: + operation['meta'] = { + 'created_by': source, + 'chat_id': metadata.get('chat_id'), + 'message_id': metadata.get('message_id'), + 'model': metadata.get('model'), + } + + try: + results = await Memories.apply_memory_operations(user.id, operations) + except ValueError as e: + raise HTTPException(status_code=404, detail=str(e)) + + upsert_items = [] + delete_ids = [] + response = [] + + for result in results: + memory = result.get('memory') + if isinstance(memory, MemoryModel): + result = {**result, 'memory': memory.model_dump()} + if result.get('status') in {'created', 'updated'}: + vector = await request.app.state.EMBEDDING_FUNCTION( + memory_vector_text(memory.content, memory.path), + user=user, + ) + upsert_items.append( + { + 'id': memory.id, + 'text': memory_vector_text(memory.content, memory.path), + 'vector': vector, + 'metadata': _memory_metadata(memory), + } + ) + if result.get('status') == 'deleted' and result.get('id'): + delete_ids.append(result['id']) + response.append(result) + + if upsert_items: + await ASYNC_VECTOR_DB_CLIENT.upsert(collection_name=f'user-memory-{user.id}', items=upsert_items) + + if delete_ids: + await ASYNC_VECTOR_DB_CLIENT.delete(collection_name=f'user-memory-{user.id}', ids=delete_ids) + + for result in response: + status_value = result.get('status') + memory = result.get('memory') or {} + memory_id = memory.get('id') or result.get('id') + + if status_value == 'created': + event = EVENTS.MEMORY_CREATED + elif status_value == 'updated': + event = EVENTS.MEMORY_UPDATED + elif status_value == 'deleted': + event = EVENTS.MEMORY_DELETED + else: + continue + + await publish_event( + request, + event, + actor=user, + subject_id=memory_id, + data={ + 'content_preview': (memory.get('content') or '')[:300], + 'type': memory.get('type'), + 'path': memory.get('path'), + 'operation': result.get('action'), + }, + ) + + return response + + ############################ # QueryMemory ############################ @@ -124,17 +278,7 @@ async def query_memory( # Database operations (get_memories_by_user_id) manage their own short-lived sessions. # This prevents holding a connection during EMBEDDING_FUNCTION() # which makes external embedding API calls (1-5+ seconds). - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_memories_permission(user) memories = await Memories.get_memories_by_user_id(user.id) if not memories: @@ -154,7 +298,7 @@ async def query_memory( # same RELEVANCE_THRESHOLD used by RAG ensures only genuinely matching # memories are surfaced (distances are normalised to 0→1, higher is # better). - relevance_threshold = getattr(request.app.state.config, 'RELEVANCE_THRESHOLD', 0.0) + relevance_threshold = await Config.get('rag.relevance_threshold', 0.0) if results and relevance_threshold > 0.0 and results.distances and results.distances[0]: from open_webui.retrieval.vector.main import SearchResult @@ -183,6 +327,61 @@ async def query_memory( return results +@router.post('/search', response_model=list[MemoryModel]) +async def search_memories( + form_data: SearchMemoriesForm, + user=Depends(get_verified_user), +): + await check_memories_permission(user) + + memories = await Memories.get_memories_by_user_id(user.id) + return search_memory_rows( + memories, + query=form_data.query, + path=form_data.path, + memory_id=form_data.memory_id, + memory_type=form_data.type, + limit=form_data.limit, + ) + + +@router.post('/paths') +async def list_memory_paths( + form_data: ListMemoryPathsForm, + user=Depends(get_verified_user), +): + await check_memories_permission(user) + + memories = await Memories.get_memories_by_user_id(user.id) + return list_memory_path_groups( + memories, + query=form_data.query or '', + memory_type=form_data.type, + limit=form_data.limit, + ) + + +@router.post('/path') +async def read_memory_path( + form_data: ReadMemoryPathForm, + user=Depends(get_verified_user), +): + await check_memories_permission(user) + + memories = await Memories.get_memories_by_user_id(user.id) + result = read_memory_path_rows( + memories, + path=form_data.path, + memory_type=form_data.type, + include_children=form_data.include_children, + limit=form_data.limit, + ) + return { + **result, + 'memories': [memory.model_dump() for memory in result['memories']], + } + + ############################ # ResetMemoryFromVectorDB ############################ @@ -199,17 +398,7 @@ async def reset_memory_from_vector_db( calls simultaneously. With a session held, this could block a connection for MINUTES, completely exhausting the connection pool. """ - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_memories_permission(user) await ASYNC_VECTOR_DB_CLIENT.delete_collection(f'user-memory-{user.id}') @@ -217,7 +406,10 @@ async def reset_memory_from_vector_db( # Generate vectors in parallel vectors = await asyncio.gather( - *[request.app.state.EMBEDDING_FUNCTION(memory.content, user=user) for memory in memories] + *[ + request.app.state.EMBEDDING_FUNCTION(memory_vector_text(memory.content, memory.path), user=user) + for memory in memories + ] ) await ASYNC_VECTOR_DB_CLIENT.upsert( @@ -225,17 +417,22 @@ async def reset_memory_from_vector_db( items=[ { 'id': memory.id, - 'text': memory.content, + 'text': memory_vector_text(memory.content, memory.path), 'vector': vectors[idx], - 'metadata': { - 'created_at': memory.created_at, - 'updated_at': memory.updated_at, - }, + 'metadata': _memory_metadata(memory), } for idx, memory in enumerate(memories) ], ) + await publish_event( + request, + EVENTS.MEMORY_RESET, + actor=user, + subject_id=user.id, + subject_type='user', + data={'count': len(memories)}, + ) return True @@ -250,17 +447,7 @@ async def delete_memory_by_user_id( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_memories_permission(user) result = await Memories.delete_memories_by_user_id(user.id, db=db) @@ -269,6 +456,13 @@ async def delete_memory_by_user_id( await ASYNC_VECTOR_DB_CLIENT.delete_collection(f'user-memory-{user.id}') except Exception as e: log.error(e) + await publish_event( + request, + EVENTS.MEMORY_DELETED, + actor=user, + subject_id=user.id, + subject_type='user', + ) return True return False @@ -290,40 +484,46 @@ async def update_memory_by_id( # Database operations (update_memory_by_id_and_user_id) manage their own # short-lived sessions. This prevents holding a connection during # EMBEDDING_FUNCTION() which makes external API calls (1-5+ seconds). - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) + await check_memories_permission(user) - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) - - memory = await Memories.update_memory_by_id_and_user_id(memory_id, user.id, form_data.content) + content = clean_memory_content(form_data.content) if form_data.content is not None else None + path = clean_memory_path(form_data.path) + if content is None and form_data.type is None and form_data.path is None: + raise HTTPException(status_code=400, detail='No memory update provided') + memory = await Memories.update_memory_by_id_and_user_id( + memory_id, + user.id, + content, + memory_type=form_data.type, + path=path, + update_path=form_data.path is not None, + meta={'created_by': 'manual'}, + ) if memory is None: raise HTTPException(status_code=404, detail=ERROR_MESSAGES.NOT_FOUND) - if form_data.content is not None: - vector = await request.app.state.EMBEDDING_FUNCTION(memory.content, user=user) + if form_data.content is not None or form_data.path is not None: + vector = await request.app.state.EMBEDDING_FUNCTION(memory_vector_text(memory.content, memory.path), user=user) await ASYNC_VECTOR_DB_CLIENT.upsert( collection_name=f'user-memory-{user.id}', items=[ { 'id': memory.id, - 'text': memory.content, + 'text': memory_vector_text(memory.content, memory.path), 'vector': vector, - 'metadata': { - 'created_at': memory.created_at, - 'updated_at': memory.updated_at, - }, + 'metadata': _memory_metadata(memory), } ], ) + await publish_event( + request, + EVENTS.MEMORY_UPDATED, + actor=user, + subject_id=memory.id, + data={'content_preview': memory.content[:300], 'type': memory.type, 'path': memory.path}, + ) return memory @@ -339,22 +539,18 @@ async def delete_memory_by_id( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if not request.app.state.config.ENABLE_MEMORIES: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - if not await has_permission(user.id, 'features.memories', request.app.state.config.USER_PERMISSIONS): - raise HTTPException( - status_code=status.HTTP_403_FORBIDDEN, - detail=ERROR_MESSAGES.ACCESS_PROHIBITED, - ) + await check_memories_permission(user) result = await Memories.delete_memory_by_id_and_user_id(memory_id, user.id, db=db) if result: await ASYNC_VECTOR_DB_CLIENT.delete(collection_name=f'user-memory-{user.id}', ids=[memory_id]) + await publish_event( + request, + EVENTS.MEMORY_DELETED, + actor=user, + subject_id=memory_id, + ) return True return False diff --git a/backend/open_webui/routers/models.py b/backend/open_webui/routers/models.py index 75ee4e723b..59c025055e 100644 --- a/backend/open_webui/routers/models.py +++ b/backend/open_webui/routers/models.py @@ -20,9 +20,11 @@ from fastapi import ( from fastapi.responses import RedirectResponse, StreamingResponse from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ENABLE_PROFILE_IMAGE_URL_FORWARDING, PROFILE_IMAGE_ALLOWED_MIME_TYPES from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.models import ( ModelAccessListResponse, @@ -60,6 +62,9 @@ def _safe_static_redirect_path(url: str) -> str | None: if decoded == path: break path = decoded + # Fail closed: a value still encoded after the cap would be decoded further downstream. + if unquote(path) != path: + return None if '\x00' in path or '\\' in path: return None if not path.startswith('/'): @@ -193,9 +198,19 @@ async def get_models( ########################### +@router.get('/base/tags', response_model=list[str]) +async def get_base_model_tags(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): + tags = await Models.get_all_tags(user_id=user.id, is_admin=True, is_base_model=True, db=db) + return sorted(tags) + + @router.get('/base', response_model=list[ModelResponse]) -async def get_base_models(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): - return await Models.get_base_models(db=db) +async def get_base_models( + tag: str | None = None, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): + return await Models.get_base_models(tag=tag, db=db) ########################### @@ -227,7 +242,7 @@ async def create_new_model( ): """Create a new workspace model entry.""" if user.role != 'admin' and not await has_permission( - user.id, 'workspace.models', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'workspace.models', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -255,7 +270,7 @@ async def create_new_model( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -264,6 +279,13 @@ async def create_new_model( model = await Models.insert_new_model(form_data, user.id, db=db) if model: + await publish_event( + request, + EVENTS.MODEL_CREATED, + actor=user, + subject_id=model.id, + data={'name': model.name}, + ) return model else: raise HTTPException( @@ -286,7 +308,7 @@ async def export_models( if user.role != 'admin' and not await has_permission( user.id, 'workspace.models_export', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ): raise HTTPException( @@ -319,7 +341,7 @@ async def import_models( if user.role != 'admin' and not await has_permission( user.id, 'workspace.models_import', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ): raise HTTPException( @@ -356,10 +378,12 @@ async def import_models( else: writable_model_ids = set(existing_model_ids) + imported_ids = [] for model_data in data: model_id = model_data.get('id') if model_id and is_valid_model_id(model_id): + imported_ids.append(model_id) # Defense-in-depth: skip models referencing inaccessible files try: await _verify_knowledge_file_access( @@ -400,7 +424,7 @@ async def import_models( # metadata-only imports. if 'access_grants' in model_data: updated_model.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, updated_model.access_grants, @@ -413,13 +437,20 @@ async def import_models( model_data['params'] = model_data.get('params', {}) new_model = ModelForm(**model_data) new_model.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, new_model.access_grants, 'sharing.public_models', ) await Models.insert_new_model(user_id=user.id, form_data=new_model, db=db) + await publish_event( + request, + EVENTS.MODEL_IMPORTED, + actor=user, + subject_type='model', + data={'count': len(imported_ids), 'model_ids': imported_ids}, + ) return True else: raise HTTPException(status_code=400, detail='Invalid JSON format') @@ -444,7 +475,15 @@ async def sync_models( user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session), ): - return await Models.sync_models(user.id, form_data.models, db=db) + models = await Models.sync_models(user.id, form_data.models, db=db) + await publish_event( + request, + EVENTS.MODEL_SYNCED, + actor=user, + subject_type='model', + data={'count': len(models), 'model_ids': [model.id for model in models]}, + ) + return models ########################### @@ -528,11 +567,7 @@ async def get_model_profile_image( # Fallback: check arena models stored in config (not in the DB) if not profile_image_url: - arena_models = getattr( - getattr(request.app.state, 'config', None), - 'EVALUATION_ARENA_MODELS', - [], - ) + arena_models = await Config.get('evaluation.arena.models', []) or [] for arena_model in arena_models: if arena_model.get('id') == id: profile_image_url = arena_model.get('meta', {}).get('profile_image_url') @@ -596,7 +631,9 @@ async def get_model_profile_image( @router.post('/model/toggle', response_model=ModelResponse | None) -async def toggle_model_by_id(id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +async def toggle_model_by_id( + request: Request, id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) +): model = await Models.get_model_by_id(id, db=db) if model: if ( @@ -613,6 +650,14 @@ async def toggle_model_by_id(id: str, user=Depends(get_verified_user), db: Async model = await Models.toggle_model_by_id(id, db=db) if model: + await publish_event( + request, + EVENTS.MODEL_ENABLED if model.is_active else EVENTS.MODEL_DISABLED, + actor=user, + subject_id=model.id, + subject_type='model', + data={'name': model.name}, + ) return model else: raise HTTPException( @@ -674,7 +719,7 @@ async def update_model_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -682,6 +727,14 @@ async def update_model_by_id( ) model = await Models.update_model_by_id(form_data.id, ModelForm(**form_data.model_dump()), db=db) + if model: + await publish_event( + request, + EVENTS.MODEL_UPDATED, + actor=user, + subject_id=model.id, + data={'name': model.name}, + ) return model @@ -746,7 +799,7 @@ async def update_model_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -757,7 +810,14 @@ async def update_model_access_by_id( await Models.update_model_updated_at_by_id(form_data.id, db=db) - return await Models.get_model_by_id(form_data.id, db=db) + model = await Models.get_model_by_id(form_data.id, db=db) + await publish_event( + request, + EVENTS.MODEL_ACCESS_UPDATED, + actor=user, + subject_id=form_data.id, + ) + return model ############################ @@ -767,6 +827,7 @@ async def update_model_access_by_id( @router.post('/model/delete', response_model=bool) async def delete_model_by_id( + request: Request, form_data: ModelIdForm, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), @@ -795,10 +856,22 @@ async def delete_model_by_id( ) result = await Models.delete_model_by_id(form_data.id, db=db) + if result: + await publish_event( + request, + EVENTS.MODEL_DELETED, + actor=user, + subject_id=form_data.id, + data={'name': model.name}, + ) return result @router.delete('/delete/all', response_model=bool) -async def delete_all_models(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def delete_all_models( + request: Request, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session) +): result = await Models.delete_all_models(db=db) + if result: + await publish_event(request, EVENTS.MODEL_DELETED, actor=user, subject_type='model') return result diff --git a/backend/open_webui/routers/notes.py b/backend/open_webui/routers/notes.py index 6dccc73f6d..477558e423 100644 --- a/backend/open_webui/routers/notes.py +++ b/backend/open_webui/routers/notes.py @@ -9,8 +9,10 @@ from open_webui.config import ( ENABLE_ADMIN_EXPORT, ) from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.notes import ( NoteForm, @@ -66,7 +68,7 @@ async def get_notes( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -114,7 +116,7 @@ async def get_pinned_notes( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -155,7 +157,7 @@ async def search_notes( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -208,7 +210,7 @@ async def create_new_note( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -216,7 +218,7 @@ async def create_new_note( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -226,6 +228,13 @@ async def create_new_note( try: note = await Notes.insert_new_note(user.id, form_data, db=db) + await publish_event( + request, + EVENTS.NOTE_CREATED, + actor=user, + subject_id=note.id, + data={'title': note.title}, + ) return note except Exception as e: log.exception(e) @@ -249,7 +258,7 @@ async def get_note_by_id( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -308,7 +317,7 @@ async def update_note_by_id( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -332,7 +341,7 @@ async def update_note_by_id( raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -351,6 +360,13 @@ async def update_note_by_id( to=f'note:{note.id}', ) + await publish_event( + request, + EVENTS.NOTE_UPDATED, + actor=user, + subject_id=note.id, + data={'title': note.title}, + ) return note except Exception as e: log.exception(e) @@ -375,7 +391,7 @@ async def update_note_access_by_id( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -399,7 +415,7 @@ async def update_note_access_by_id( raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -411,6 +427,12 @@ async def update_note_access_by_id( note = await Notes.get_note_by_id(id, db=db) pinned_note_ids = await Notes.get_pinned_note_ids(user.id, db=db) note.is_pinned = note.id in pinned_note_ids + await publish_event( + request, + EVENTS.NOTE_ACCESS_UPDATED, + actor=user, + subject_id=note.id, + ) return note @@ -427,7 +449,7 @@ async def pin_note_by_id( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -453,6 +475,13 @@ async def pin_note_by_id( note = await Notes.toggle_note_pinned_by_id(id, user.id, db=db) pinned_note_ids = await Notes.get_pinned_note_ids(user.id, db=db) note.is_pinned = note.id in pinned_note_ids + await publish_event( + request, + EVENTS.NOTE_PINNED if note.is_pinned else EVENTS.NOTE_UNPINNED, + actor=user, + subject_id=note.id, + subject_type='note', + ) return note @@ -469,7 +498,7 @@ async def delete_note_by_id( db: AsyncSession = Depends(get_async_session), ): if user.role != 'admin' and not await has_permission( - user.id, 'features.notes', request.app.state.config.USER_PERMISSIONS, db=db + user.id, 'features.notes', await Config.get('user.permissions'), db=db ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -494,6 +523,12 @@ async def delete_note_by_id( try: note = await Notes.delete_note_by_id(id, db=db) + await publish_event( + request, + EVENTS.NOTE_DELETED, + actor=user, + subject_id=id, + ) return True except Exception as e: log.exception(e) diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index a4e166ba9e..b755acf80f 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -20,6 +20,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from open_webui.config import UPLOAD_DIR from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ( AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT, @@ -31,12 +32,13 @@ from open_webui.env import ( ) from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.models import Models from open_webui.models.users import UserModel from open_webui.utils.access_control import check_model_access from open_webui.utils.auth import get_admin_user, get_verified_user -from open_webui.utils.headers import include_user_info_headers +from open_webui.utils.headers import get_custom_headers, include_user_info_headers from open_webui.utils.misc import calculate_sha256 from open_webui.utils.payload import ( apply_model_params_to_body_ollama, @@ -97,6 +99,8 @@ async def send_request( stream: bool = False, content_type: str | None = None, metadata: dict | None = None, + api_config: dict | None = None, + request: Request | None = None, ): r = None streaming = False @@ -113,6 +117,10 @@ async def send_request( if metadata and metadata.get('chat_id'): headers[FORWARD_SESSION_INFO_HEADER_CHAT_ID] = metadata.get('chat_id') + # Custom per-connection headers last so admin-set headers take precedence. + if api_config and api_config.get('headers'): + headers.update(get_custom_headers(api_config['headers'], user, metadata, request=request)) + r = await session.request( method, url, @@ -181,6 +189,32 @@ def get_api_key(idx, url, configs): router = APIRouter() +OLLAMA_CONFIG_KEYS = { + 'ENABLE_OLLAMA_API': 'ollama.enable', + 'OLLAMA_BASE_URLS': 'ollama.base_urls', + 'OLLAMA_API_CONFIGS': 'ollama.api_configs', +} + + +async def get_ollama_config_values() -> dict: + values = await Config.get_many(*OLLAMA_CONFIG_KEYS.values()) + return {field: values[storage_key] for field, storage_key in OLLAMA_CONFIG_KEYS.items() if storage_key in values} + + +async def get_ollama_runtime_config() -> tuple[bool, list[str], dict]: + values = await Config.get_many('ollama.enable', 'ollama.base_urls', 'ollama.api_configs') + return ( + values.get('ollama.enable'), + values.get('ollama.base_urls') or [], + values.get('ollama.api_configs') or {}, + ) + + +async def get_ollama_connection(idx: int) -> tuple[str, dict, str | None]: + _, base_urls, api_configs = await get_ollama_runtime_config() + url = base_urls[idx] + return url, resolve_api_config(api_configs, idx, url), get_api_key(idx, url, api_configs) + @router.head('/') @router.get('/') @@ -236,11 +270,7 @@ async def get_config( user=Depends(get_admin_user), ) -> dict: """Return the current Ollama connection configuration.""" - return { - 'ENABLE_OLLAMA_API': request.app.state.config.ENABLE_OLLAMA_API, - 'OLLAMA_BASE_URLS': request.app.state.config.OLLAMA_BASE_URLS, - 'OLLAMA_API_CONFIGS': request.app.state.config.OLLAMA_API_CONFIGS, - } + return await get_ollama_config_values() class OllamaConfigForm(BaseModel): @@ -258,20 +288,32 @@ async def update_config( user=Depends(get_admin_user), ) -> dict: """Persist updated Ollama connection settings.""" - request.app.state.config.ENABLE_OLLAMA_API = form_data.ENABLE_OLLAMA_API - request.app.state.config.OLLAMA_BASE_URLS = form_data.OLLAMA_BASE_URLS - request.app.state.config.OLLAMA_API_CONFIGS = form_data.OLLAMA_API_CONFIGS - - # Prune stale config entries that no longer map to a URL index - valid_keys = {str(i) for i in range(len(request.app.state.config.OLLAMA_BASE_URLS))} - request.app.state.config.OLLAMA_API_CONFIGS = { - k: v for k, v in request.app.state.config.OLLAMA_API_CONFIGS.items() if k in valid_keys - } + valid_keys = {str(i) for i in range(len(form_data.OLLAMA_BASE_URLS))} + api_configs = {k: v for k, v in form_data.OLLAMA_API_CONFIGS.items() if k in valid_keys} + await Config.upsert( + { + 'ollama.enable': form_data.ENABLE_OLLAMA_API, + 'ollama.base_urls': form_data.OLLAMA_BASE_URLS, + 'ollama.api_configs': api_configs, + } + ) + await publish_event( + request, + EVENTS.MODEL_PROVIDER_CONFIG_UPDATED, + actor=user, + subject_id='ollama', + subject_type='model.provider_config', + data={ + 'provider': 'ollama', + 'enabled': form_data.ENABLE_OLLAMA_API, + 'base_url_count': len(form_data.OLLAMA_BASE_URLS), + }, + ) return { - 'ENABLE_OLLAMA_API': request.app.state.config.ENABLE_OLLAMA_API, - 'OLLAMA_BASE_URLS': request.app.state.config.OLLAMA_BASE_URLS, - 'OLLAMA_API_CONFIGS': request.app.state.config.OLLAMA_API_CONFIGS, + 'ENABLE_OLLAMA_API': form_data.ENABLE_OLLAMA_API, + 'OLLAMA_BASE_URLS': form_data.OLLAMA_BASE_URLS, + 'OLLAMA_API_CONFIGS': api_configs, } @@ -293,29 +335,32 @@ def merge_models_lists(model_lists) -> list[dict]: return list(merged.values()) -def _resolve_api_config(request: Request, idx: int, url: str) -> dict: +def resolve_api_config(api_configs: dict, idx: int, url: str) -> dict: """Look up the API config for a backend by numeric index, falling back to URL key (legacy).""" - api_configs = request.app.state.config.OLLAMA_API_CONFIGS return api_configs.get(str(idx), api_configs.get(url, {})) @cached( ttl=MODELS_CACHE_TTL, - key=lambda _, user: f'ollama_all_models_{user.id}' if user else 'ollama_all_models', + # key_builder (not key) is the per-call hook in aiocache 0.12; `key=` is a + # static key, so a `key=lambda` collapsed every caller to one shared entry. + key_builder=lambda _func, request, user=None: f'ollama_all_models_{user.id}' if user else 'ollama_all_models', ) async def get_all_models(request: Request, user: UserModel | None = None): """Aggregate model tags from every enabled Ollama backend.""" log.info('get_all_models()') - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): models_dict: dict = {'models': []} request.app.state.OLLAMA_MODELS = {} return models_dict # Fan-out tag requests to every backend tasks = [] - for idx, url in enumerate(request.app.state.config.OLLAMA_BASE_URLS): - api_config = _resolve_api_config(request, idx, url) + base_urls = await Config.get('ollama.base_urls', []) + api_configs = await Config.get('ollama.api_configs', {}) + for idx, url in enumerate(base_urls): + api_config = resolve_api_config(api_configs, idx, url) if not api_config: tasks.append(send_get_request(f'{url}/api/tags', user=user)) elif api_config.get('enable', True): @@ -325,12 +370,16 @@ async def get_all_models(request: Request, user: UserModel | None = None): responses = await asyncio.gather(*tasks) + # Track which backends failed so we can skip them for /api/ps + failed_idxs: set[int] = set() + # Post-process each response: apply prefix_id, tags, model filtering for idx, response in enumerate(responses): if not response: + failed_idxs.add(idx) continue - url = request.app.state.config.OLLAMA_BASE_URLS[idx] - api_config = _resolve_api_config(request, idx, url) + url = base_urls[idx] + api_config = resolve_api_config(api_configs, idx, url) connection_type = api_config.get('connection_type', 'local') prefix_id = api_config.get('prefix_id') @@ -352,7 +401,7 @@ async def get_all_models(request: Request, user: UserModel | None = None): # Annotate with expiry info from loaded-model state try: - loaded = await get_ollama_loaded_models(request, user=user) + loaded = await get_ollama_loaded_models(request, user=user, skip_idxs=failed_idxs) expires_map = {m['model']: m['expires_at'] for m in loaded['models'] if 'expires_at' in m} for m in models_dict['models']: if m['model'] in expires_map: @@ -394,14 +443,14 @@ async def get_ollama_tags( user=Depends(get_verified_user), ): """List Ollama model tags, optionally from a specific backend.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) if url_idx is None: result = await get_all_models(request, user=user) else: - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + url = (await Config.get('ollama.base_urls', []))[url_idx] + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) result = await send_request(f'{url}/api/tags', 'GET', key=key, user=user) if user.role == 'user' and not BYPASS_MODEL_ACCESS_CONTROL: @@ -414,14 +463,20 @@ async def get_ollama_tags( async def get_ollama_loaded_models( request: Request, user=Depends(get_admin_user), + skip_idxs: set[int] | None = None, ) -> dict: """List models currently loaded in Ollama memory across all backends.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): return {'models': []} tasks = [] - for idx, url in enumerate(request.app.state.config.OLLAMA_BASE_URLS): - api_config = _resolve_api_config(request, idx, url) + base_urls = await Config.get('ollama.base_urls', []) + api_configs = await Config.get('ollama.api_configs', {}) + for idx, url in enumerate(base_urls): + if skip_idxs and idx in skip_idxs: + tasks.append(asyncio.ensure_future(asyncio.sleep(0, None))) + continue + api_config = resolve_api_config(api_configs, idx, url) if not api_config: tasks.append(send_get_request(f'{url}/api/ps', user=user)) elif api_config.get('enable', True): @@ -434,7 +489,7 @@ async def get_ollama_loaded_models( for idx, response in enumerate(responses): if not response: continue - api_config = _resolve_api_config(request.app.state.config, idx, request.app.state.config.OLLAMA_BASE_URLS[idx]) + api_config = resolve_api_config(api_configs, idx, base_urls[idx]) prefix_id = api_config.get('prefix_id') if prefix_id: for m in response.get('models', []): @@ -450,19 +505,19 @@ async def get_ollama_versions( url_idx: int | None = None, ): """Return the lowest Ollama version across all configured backends.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): return {'version': False} if url_idx is not None: - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] return await send_request(f'{url}/api/version', 'GET') # Fan-out to every enabled backend tasks = [] - for idx, url in enumerate(request.app.state.config.OLLAMA_BASE_URLS): - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + for idx, url in enumerate(await Config.get('ollama.base_urls', [])): + api_config = (await Config.get('ollama.api_configs', {})).get( str(idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), + (await Config.get('ollama.api_configs', {})).get(url, {}), ) if api_config.get('enable', True): tasks.append(send_get_request(f'{url}/api/version', api_config.get('key'))) @@ -511,11 +566,11 @@ async def unload_model( results = [] errors = [] for idx in url_indices: - url = request.app.state.config.OLLAMA_BASE_URLS[idx] - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( - str(idx), request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}) + url = (await Config.get('ollama.base_urls', []))[idx] + api_config = (await Config.get('ollama.api_configs', {})).get( + str(idx), (await Config.get('ollama.api_configs', {})).get(url, {}) ) - key = get_api_key(idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + key = get_api_key(idx, url, (await Config.get('ollama.api_configs', {}))) prefix_id = api_config.get('prefix_id', None) if prefix_id and model.startswith(f'{prefix_id}.'): @@ -552,20 +607,20 @@ async def pull_model( url_idx: int = 0, user=Depends(get_admin_user), ): - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) form_data = form_data.model_dump(exclude_none=True) form_data['model'] = form_data.get('model', form_data.get('name')) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] log.info(f'url: {url}') # Admins may pull from any registry return await send_request( f'{url}/api/pull', payload=json.dumps({**form_data, 'insecure': True}), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=True, ) @@ -588,7 +643,7 @@ async def push_model( user=Depends(get_admin_user), ): """Push a local model to a remote registry.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) if url_idx is None: @@ -598,13 +653,13 @@ async def push_model( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.model)) url_idx = models[form_data.model]['urls'][0] - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] log.debug(f'url: {url}') return await send_request( f'{url}/api/push', payload=form_data.model_dump_json(exclude_none=True).encode(), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=True, ) @@ -627,16 +682,16 @@ async def create_model( url_idx: int = 0, user=Depends(get_admin_user), ): - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) log.debug(f'form_data: {form_data}') - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] return await send_request( f'{url}/api/create', payload=form_data.model_dump_json(exclude_none=True).encode(), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=True, ) @@ -658,7 +713,7 @@ async def copy_model( user=Depends(get_admin_user), ): """Duplicate an existing model under a new name.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) if url_idx is None: @@ -668,8 +723,8 @@ async def copy_model( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.source)) url_idx = models[form_data.source]['urls'][0] - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + url = (await Config.get('ollama.base_urls', []))[url_idx] + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) await send_request( f'{url}/api/copy', @@ -677,6 +732,13 @@ async def copy_model( key=key, user=user, ) + await publish_event( + request, + EVENTS.MODEL_PROVIDER_MODEL_CREATED, + actor=user, + subject_id=form_data.destination, + data={'provider': 'ollama', 'source': form_data.source, 'url_idx': url_idx}, + ) return True @@ -689,7 +751,7 @@ async def delete_model( user=Depends(get_admin_user), ): """Remove a model from an Ollama backend.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) payload = form_data.model_dump(exclude_none=True) @@ -703,8 +765,8 @@ async def delete_model( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(model)) url_idx = models[model]['urls'][0] - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + url = (await Config.get('ollama.base_urls', []))[url_idx] + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) await send_request( f'{url}/api/delete', @@ -713,6 +775,13 @@ async def delete_model( key=key, user=user, ) + await publish_event( + request, + EVENTS.MODEL_PROVIDER_MODEL_DELETED, + actor=user, + subject_id=model, + data={'provider': 'ollama', 'url_idx': url_idx}, + ) return True @@ -723,7 +792,7 @@ async def show_model_info( user=Depends(get_verified_user), ): """Retrieve model metadata from the Ollama backend.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) payload = form_data.model_dump(exclude_none=True) @@ -739,8 +808,8 @@ async def show_model_info( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(model)) url_idx = random.choice(models[model]['urls']) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + url = (await Config.get('ollama.base_urls', []))[url_idx] + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) return await send_request( f'{url}/api/show', @@ -770,7 +839,7 @@ async def embed( user=Depends(get_verified_user), ): """Generate embeddings via the Ollama /api/embed endpoint.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) log.info(f'generate_ollama_batch_embeddings {form_data}') @@ -787,12 +856,12 @@ async def embed( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.model)) url_idx = random.choice(models[model]['urls']) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + url = (await Config.get('ollama.base_urls', []))[url_idx] + api_config = (await Config.get('ollama.api_configs', {})).get( str(url_idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), + (await Config.get('ollama.api_configs', {})).get(url, {}), ) - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) prefix_id = api_config.get('prefix_id') if prefix_id: @@ -824,7 +893,7 @@ async def embeddings( user=Depends(get_verified_user), ): """Generate embeddings via the legacy Ollama /api/embeddings endpoint.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) log.info(f'generate_ollama_embeddings {form_data}') @@ -841,12 +910,12 @@ async def embeddings( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.model)) url_idx = random.choice(models[model]['urls']) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + url = (await Config.get('ollama.base_urls', []))[url_idx] + api_config = (await Config.get('ollama.api_configs', {})).get( str(url_idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), + (await Config.get('ollama.api_configs', {})).get(url, {}), ) - key = get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS) + key = get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))) prefix_id = api_config.get('prefix_id') if prefix_id: @@ -886,7 +955,7 @@ async def generate_completion( user=Depends(get_verified_user), ): """Run text completion via Ollama /api/generate.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) await check_model_access(user, await Models.get_model_by_id(form_data.model), BYPASS_MODEL_ACCESS_CONTROL) @@ -900,10 +969,10 @@ async def generate_completion( raise HTTPException(status_code=400, detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.model)) url_idx = random.choice(models[model]['urls']) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + url = (await Config.get('ollama.base_urls', []))[url_idx] + api_config = (await Config.get('ollama.api_configs', {})).get( str(url_idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), + (await Config.get('ollama.api_configs', {})).get(url, {}), ) prefix_id = api_config.get('prefix_id') @@ -913,7 +982,7 @@ async def generate_completion( return await send_request( f'{url}/api/generate', payload=form_data.model_dump_json(exclude_none=True).encode(), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=True, ) @@ -973,7 +1042,7 @@ async def get_ollama_url(request: Request, model: str, url_idx: int | None = Non detail=ERROR_MESSAGES.MODEL_NOT_FOUND(model), ) url_idx = random.choice(models[model].get('urls', [])) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] return url, url_idx @@ -986,7 +1055,7 @@ async def generate_chat_completion( user=Depends(get_verified_user), # noqa: B008 ): """Forward a chat completion request to an Ollama backend.""" - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) # NOTE: We intentionally do NOT use Depends(get_async_session) here. @@ -1035,7 +1104,7 @@ async def generate_chat_completion( await check_model_access(user, None, bypass_filter) url, url_idx = await get_ollama_url(request, payload['model'], url_idx, user) - api_config = _resolve_api_config(request, url_idx, url) + api_config = resolve_api_config((await Config.get('ollama.api_configs', {})), url_idx, url) prefix_id = api_config.get('prefix_id') if prefix_id: @@ -1044,11 +1113,13 @@ async def generate_chat_completion( return await send_request( f'{url}/api/chat', payload=json.dumps(payload), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=form_data.stream, content_type='application/x-ndjson', metadata=metadata, + api_config=api_config, + request=request, ) @@ -1121,7 +1192,7 @@ async def generate_openai_completion( await check_model_access(user, None) url, url_idx = await get_ollama_url(request, payload['model'], url_idx, user) - api_config = _resolve_api_config(request, url_idx, url) + api_config = resolve_api_config((await Config.get('ollama.api_configs', {})), url_idx, url) prefix_id = api_config.get('prefix_id') if prefix_id: @@ -1130,10 +1201,12 @@ async def generate_openai_completion( return await send_request( f'{url}/v1/completions', payload=json.dumps(payload), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=payload.get('stream', False), metadata=metadata, + api_config=api_config, + request=request, ) @@ -1178,7 +1251,7 @@ async def generate_openai_chat_completion( await check_model_access(user, None) url, url_idx = await get_ollama_url(request, payload['model'], url_idx, user) - api_config = _resolve_api_config(request, url_idx, url) + api_config = resolve_api_config((await Config.get('ollama.api_configs', {})), url_idx, url) prefix_id = api_config.get('prefix_id') if prefix_id: @@ -1187,10 +1260,12 @@ async def generate_openai_chat_completion( return await send_request( f'{url}/v1/chat/completions', payload=json.dumps(payload), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=payload.get('stream', False), metadata=metadata, + api_config=api_config, + request=request, ) @@ -1211,7 +1286,7 @@ async def generate_anthropic_messages( See https://docs.ollama.com/api/anthropic-compatibility """ - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) payload = {**form_data} @@ -1227,9 +1302,9 @@ async def generate_anthropic_messages( await check_model_access(user, None) url, url_idx = await get_ollama_url(request, payload['model'], url_idx, user) - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + api_config = (await Config.get('ollama.api_configs', {})).get( str(url_idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), # Legacy support + (await Config.get('ollama.api_configs', {})).get(url, {}), # Legacy support ) prefix_id = api_config.get('prefix_id', None) @@ -1239,10 +1314,12 @@ async def generate_anthropic_messages( return await send_request( f'{url}/v1/messages', payload=json.dumps(payload), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=payload.get('stream', False), content_type='text/event-stream' if payload.get('stream', False) else None, + api_config=api_config, + request=request, ) @@ -1269,7 +1346,7 @@ async def generate_responses( See https://ollama.com/blog/responses-api """ - if not request.app.state.config.ENABLE_OLLAMA_API: + if not await Config.get('ollama.enable'): raise HTTPException(status_code=503, detail=ERROR_MESSAGES.OLLAMA_API_DISABLED) payload = form_data.model_dump() @@ -1285,9 +1362,9 @@ async def generate_responses( await check_model_access(user, None) url, url_idx = await get_ollama_url(request, payload['model'], url_idx, user) - api_config = request.app.state.config.OLLAMA_API_CONFIGS.get( + api_config = (await Config.get('ollama.api_configs', {})).get( str(url_idx), - request.app.state.config.OLLAMA_API_CONFIGS.get(url, {}), # Legacy support + (await Config.get('ollama.api_configs', {})).get(url, {}), # Legacy support ) prefix_id = api_config.get('prefix_id', None) @@ -1297,10 +1374,12 @@ async def generate_responses( return await send_request( f'{url}/v1/responses', payload=json.dumps(payload), - key=get_api_key(url_idx, url, request.app.state.config.OLLAMA_API_CONFIGS), + key=get_api_key(url_idx, url, (await Config.get('ollama.api_configs', {}))), user=user, stream=payload.get('stream', False), content_type='text/event-stream' if payload.get('stream', False) else None, + api_config=api_config, + request=request, ) @@ -1317,7 +1396,7 @@ async def get_openai_models( model_list = await get_all_models(request, user=user) raw_models = model_list['models'] else: - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx] + url = (await Config.get('ollama.base_urls', []))[url_idx] model_list = await send_request(f'{url}/api/tags', 'GET') raw_models = model_list.get('models', []) @@ -1394,10 +1473,13 @@ async def download_file_stream( if done: f.close() - hashed = calculate_sha256(file_path, chunk_size) + hashed = await asyncio.to_thread(calculate_sha256, file_path, chunk_size) - with open(file_path, 'rb') as blob_f: - blob_data = blob_f.read() + def _read_blob(): + with open(file_path, 'rb') as blob_f: + return blob_f.read() + + blob_data = await asyncio.to_thread(_read_blob) blob_url = f'{ollama_url}/api/blobs/sha256:{hashed}' async with session.post( @@ -1429,7 +1511,7 @@ async def download_model( detail='Invalid file_url. Only URLs from allowed hosts are permitted.', ) - url = request.app.state.config.OLLAMA_BASE_URLS[url_idx if url_idx is not None else 0] + url = (await Config.get('ollama.base_urls', []))[url_idx if url_idx is not None else 0] file_name = parse_huggingface_url(form_data.url) if not file_name: @@ -1450,7 +1532,7 @@ async def upload_model( user=Depends(get_admin_user), ): """Upload a local model file, push it as a blob, and create the model in Ollama.""" - ollama_url = request.app.state.config.OLLAMA_BASE_URLS[url_idx if url_idx is not None else 0] + ollama_url = (await Config.get('ollama.base_urls', []))[url_idx if url_idx is not None else 0] filename = os.path.basename(file.filename) file_path = os.path.join(UPLOAD_DIR, filename) @@ -1458,12 +1540,16 @@ async def upload_model( # Stage 1: persist the uploaded file to disk chunk_size = 1024 * 1024 * 2 # 2 MiB - with open(file_path, 'wb') as out_f: - while True: - chunk = file.file.read(chunk_size) - if not chunk: - break - out_f.write(chunk) + + def _persist_upload(): + with open(file_path, 'wb') as out_f: + while True: + chunk = file.file.read(chunk_size) + if not chunk: + break + out_f.write(chunk) + + await asyncio.to_thread(_persist_upload) async def file_process_stream(): nonlocal ollama_url @@ -1471,7 +1557,7 @@ async def upload_model( log.info(f'Total Model Size: {total_size}') # Stage 2: hash the file and emit SSE progress - file_hash = calculate_sha256(file_path, chunk_size) + file_hash = await asyncio.to_thread(calculate_sha256, file_path, chunk_size) log.info(f'Model Hash: {file_hash}') try: @@ -1483,8 +1569,11 @@ async def upload_model( yield f'data: {json.dumps({"progress": progress, "total": total_size, "completed": bytes_read})}\n\n' # Stage 3: push blob to Ollama - with open(file_path, 'rb') as f: - blob_data = f.read() + def _read_blob(): + with open(file_path, 'rb') as f: + return f.read() + + blob_data = await asyncio.to_thread(_read_blob) session = await get_session() blob_url = f'{ollama_url}/api/blobs/sha256:{file_hash}' diff --git a/backend/open_webui/routers/openai.py b/backend/open_webui/routers/openai.py index 8aa8eff36e..f7019fbf3a 100644 --- a/backend/open_webui/routers/openai.py +++ b/backend/open_webui/routers/openai.py @@ -22,6 +22,7 @@ from open_webui.config import ( CACHE_DIR, ) from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ( AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT, @@ -34,10 +35,11 @@ from open_webui.env import ( ) from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.models import Models from open_webui.models.users import UserModel -from open_webui.utils.access_control import check_model_access, has_connection_access +from open_webui.utils.access_control import check_model_access, has_connection_access, has_permission from open_webui.utils.anthropic import get_anthropic_models, is_anthropic_url from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.headers import get_custom_headers, include_user_info_headers @@ -207,7 +209,7 @@ async def get_headers_and_cookies( headers['Authorization'] = f'Bearer {token}' if config.get('headers') and isinstance(config.get('headers'), dict): - custom_headers = get_custom_headers(config.get('headers'), user, metadata) + custom_headers = get_custom_headers(config.get('headers'), user, metadata, request=request) headers.update(custom_headers) return headers, cookies @@ -236,15 +238,72 @@ def get_microsoft_entra_id_access_token(): router = APIRouter() +LLAMACPP_LOADED_STATES = {'loaded', 'sleeping'} +LLAMACPP_UNLOADED_STATES = {'loading', 'unloaded'} + + +def get_llamacpp_model_loaded_state(model: dict, provider: str, manual_model_ids: bool = False) -> bool | None: + if provider != 'llama.cpp': + return None + + status = model.get('status') + if isinstance(status, dict): + value = status.get('value') + if value in LLAMACPP_LOADED_STATES: + return True + if value in LLAMACPP_UNLOADED_STATES: + return False + + if not manual_model_ids and 'status' not in model: + return True + + return None + + +OPENAI_CONFIG_KEYS = { + 'ENABLE_OPENAI_API': 'openai.enable', + 'OPENAI_API_BASE_URLS': 'openai.api_base_urls', + 'OPENAI_API_KEYS': 'openai.api_keys', + 'OPENAI_API_CONFIGS': 'openai.api_configs', +} + + +async def get_openai_config() -> dict: + values = await Config.get_many(*OPENAI_CONFIG_KEYS.values()) + return {field: values[storage_key] for field, storage_key in OPENAI_CONFIG_KEYS.items() if storage_key in values} + + +async def get_openai_runtime_config() -> tuple[bool, list[str], list[str], dict]: + values = await Config.get_many('openai.enable', 'openai.api_base_urls', 'openai.api_keys', 'openai.api_configs') + return ( + values.get('openai.enable'), + values.get('openai.api_base_urls') or [], + values.get('openai.api_keys') or [], + values.get('openai.api_configs') or {}, + ) + + +async def normalize_openai_api_keys(api_base_urls: list[str], api_keys: list[str]) -> list[str]: + if len(api_keys) > len(api_base_urls): + api_keys = api_keys[: len(api_base_urls)] + elif len(api_keys) < len(api_base_urls): + api_keys = [*api_keys, *([''] * (len(api_base_urls) - len(api_keys)))] + + await Config.upsert({'openai.api_keys': api_keys}) + return api_keys + + +async def get_openai_connection(idx: int) -> tuple[str, str, dict]: + _, api_base_urls, api_keys, api_configs = await get_openai_runtime_config() + url = api_base_urls[idx] + key = api_keys[idx] + api_config = api_configs.get(str(idx), api_configs.get(url, {})) + return url, key, api_config + @router.get('/config') async def get_config(request: Request, user=Depends(get_admin_user)): - return { - 'ENABLE_OPENAI_API': request.app.state.config.ENABLE_OPENAI_API, - 'OPENAI_API_BASE_URLS': request.app.state.config.OPENAI_API_BASE_URLS, - 'OPENAI_API_KEYS': request.app.state.config.OPENAI_API_KEYS, - 'OPENAI_API_CONFIGS': request.app.state.config.OPENAI_API_CONFIGS, - } + return await get_openai_config() class OpenAIConfigForm(BaseModel): @@ -256,42 +315,57 @@ class OpenAIConfigForm(BaseModel): @router.post('/config/update') async def update_config(request: Request, form_data: OpenAIConfigForm, user=Depends(get_admin_user)): - request.app.state.config.ENABLE_OPENAI_API = form_data.ENABLE_OPENAI_API - request.app.state.config.OPENAI_API_BASE_URLS = form_data.OPENAI_API_BASE_URLS - request.app.state.config.OPENAI_API_KEYS = form_data.OPENAI_API_KEYS + api_keys = form_data.OPENAI_API_KEYS - # Check if API KEYS length is same than API URLS length - if len(request.app.state.config.OPENAI_API_KEYS) != len(request.app.state.config.OPENAI_API_BASE_URLS): - if len(request.app.state.config.OPENAI_API_KEYS) > len(request.app.state.config.OPENAI_API_BASE_URLS): - request.app.state.config.OPENAI_API_KEYS = request.app.state.config.OPENAI_API_KEYS[ - : len(request.app.state.config.OPENAI_API_BASE_URLS) - ] - else: - request.app.state.config.OPENAI_API_KEYS += [''] * ( - len(request.app.state.config.OPENAI_API_BASE_URLS) - len(request.app.state.config.OPENAI_API_KEYS) - ) + if len(api_keys) > len(form_data.OPENAI_API_BASE_URLS): + api_keys = api_keys[: len(form_data.OPENAI_API_BASE_URLS)] + elif len(api_keys) < len(form_data.OPENAI_API_BASE_URLS): + api_keys = [*api_keys, *([''] * (len(form_data.OPENAI_API_BASE_URLS) - len(api_keys)))] - request.app.state.config.OPENAI_API_CONFIGS = form_data.OPENAI_API_CONFIGS + valid_keys = set(map(str, range(len(form_data.OPENAI_API_BASE_URLS)))) + api_configs = {key: value for key, value in form_data.OPENAI_API_CONFIGS.items() if key in valid_keys} - # Remove the API configs that are not in the API URLS - keys = list(map(str, range(len(request.app.state.config.OPENAI_API_BASE_URLS)))) - request.app.state.config.OPENAI_API_CONFIGS = { - key: value for key, value in request.app.state.config.OPENAI_API_CONFIGS.items() if key in keys - } + await Config.upsert( + { + 'openai.enable': form_data.ENABLE_OPENAI_API, + 'openai.api_base_urls': form_data.OPENAI_API_BASE_URLS, + 'openai.api_keys': api_keys, + 'openai.api_configs': api_configs, + } + ) + await publish_event( + request, + EVENTS.MODEL_PROVIDER_CONFIG_UPDATED, + actor=user, + subject_id='openai', + subject_type='model.provider_config', + data={ + 'provider': 'openai', + 'enabled': form_data.ENABLE_OPENAI_API, + 'base_url_count': len(form_data.OPENAI_API_BASE_URLS), + }, + ) return { - 'ENABLE_OPENAI_API': request.app.state.config.ENABLE_OPENAI_API, - 'OPENAI_API_BASE_URLS': request.app.state.config.OPENAI_API_BASE_URLS, - 'OPENAI_API_KEYS': request.app.state.config.OPENAI_API_KEYS, - 'OPENAI_API_CONFIGS': request.app.state.config.OPENAI_API_CONFIGS, + 'ENABLE_OPENAI_API': form_data.ENABLE_OPENAI_API, + 'OPENAI_API_BASE_URLS': form_data.OPENAI_API_BASE_URLS, + 'OPENAI_API_KEYS': api_keys, + 'OPENAI_API_CONFIGS': api_configs, } @router.post('/audio/speech') async def speech(request: Request, user=Depends(get_verified_user)): + if user.role != 'admin' and not await has_permission(user.id, 'chat.tts', await Config.get('user.permissions')): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + idx = None try: - idx = request.app.state.config.OPENAI_API_BASE_URLS.index('https://api.openai.com/v1') + _, api_base_urls, _, _ = await get_openai_runtime_config() + idx = api_base_urls.index('https://api.openai.com/v1') body = await request.body() name = hashlib.sha256(body).hexdigest() @@ -305,12 +379,7 @@ async def speech(request: Request, user=Depends(get_verified_user)): if file_path.is_file(): return FileResponse(file_path) - url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = request.app.state.config.OPENAI_API_KEYS[idx] - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(idx), - request.app.state.config.OPENAI_API_CONFIGS.get(url, {}), # Legacy support - ) + url, key, api_config = await get_openai_connection(idx) headers, cookies = await get_headers_and_cookies(request, url, key, api_config, user=user) @@ -360,29 +429,15 @@ async def speech(request: Request, user=Depends(get_verified_user)): async def get_all_models_responses(request: Request, user: UserModel) -> list: - if not request.app.state.config.ENABLE_OPENAI_API: + enable_openai_api, api_base_urls, api_keys, api_configs = await get_openai_runtime_config() + if not enable_openai_api: return [] - # Cache config values locally to avoid repeated Redis lookups. - # Each access to request.app.state.config. triggers a Redis GET; - # caching here avoids hundreds of redundant round-trips. - api_base_urls = request.app.state.config.OPENAI_API_BASE_URLS - api_keys = list(request.app.state.config.OPENAI_API_KEYS) - api_configs = request.app.state.config.OPENAI_API_CONFIGS - - # Check if API KEYS length is same than API URLS length num_urls = len(api_base_urls) num_keys = len(api_keys) if num_keys != num_urls: - # if there are more keys than urls, remove the extra keys - if num_keys > num_urls: - api_keys = api_keys[:num_urls] - request.app.state.config.OPENAI_API_KEYS = api_keys - # if there are more urls than keys, add empty keys - else: - api_keys += [''] * (num_urls - num_keys) - request.app.state.config.OPENAI_API_KEYS = api_keys + api_keys = await normalize_openai_api_keys(api_base_urls, api_keys) request_tasks = [] for idx, url in enumerate(api_base_urls): @@ -487,18 +542,17 @@ async def get_filtered_models(models, user, db=None): @cached( ttl=MODELS_CACHE_TTL, - key=lambda _, user: f'openai_all_models_{user.id}' if user else 'openai_all_models', + # key_builder (not key) is the per-call hook in aiocache 0.12; `key=` is a + # static key, so a `key=lambda` collapsed every caller to one shared entry. + key_builder=lambda _func, request, user=None: f'openai_all_models_{user.id}' if user else 'openai_all_models', ) async def get_all_models(request: Request, user: UserModel) -> dict[str, list]: log.info('get_all_models()') - if not request.app.state.config.ENABLE_OPENAI_API: + enable_openai_api, api_base_urls, _, api_configs = await get_openai_runtime_config() + if not enable_openai_api: return {'data': []} - # Cache config value locally to avoid repeated Redis lookups inside - # the nested loop in get_merged_models (one GET per model otherwise). - api_base_urls = request.app.state.config.OPENAI_API_BASE_URLS - responses = await get_all_models_responses(request, user=user) def extract_data(response): @@ -539,21 +593,25 @@ async def get_all_models(request: Request, user: UserModel) -> dict[str, list]: continue if model_id and model_id not in models: + api_config = api_configs.get(str(idx), api_configs.get(base_url, {})) + provider = model.get('provider', '') merged = { **model, 'name': model.get('name', model_id), 'owned_by': 'openai', 'openai': model, 'connection_type': model.get('connection_type', 'external'), - 'provider': model.get('provider', ''), + 'provider': provider, 'urlIdx': idx, } - # llama.cpp router mode: derive loaded state from - # the status object returned by GET /v1/models. - status = model.get('status') - if isinstance(status, dict) and 'value' in status: - merged['loaded'] = status['value'] in ('loaded', 'sleeping') + loaded = get_llamacpp_model_loaded_state( + model, + provider, + manual_model_ids=bool(api_config.get('model_ids')), + ) + if loaded is not None: + merged['loaded'] = loaded models[model_id] = merged @@ -569,7 +627,7 @@ async def get_all_models(request: Request, user: UserModel) -> dict[str, list]: @router.get('/models') @router.get('/models/{url_idx}') async def get_models(request: Request, url_idx: int | None = None, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_OPENAI_API: + if not await Config.get('openai.enable'): raise HTTPException(status_code=503, detail='OpenAI API is disabled') models = { @@ -579,13 +637,7 @@ async def get_models(request: Request, url_idx: int | None = None, user=Depends( if url_idx is None: models = await get_all_models(request, user=user) else: - url = request.app.state.config.OPENAI_API_BASE_URLS[url_idx] - key = request.app.state.config.OPENAI_API_KEYS[url_idx] - - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(url_idx), - request.app.state.config.OPENAI_API_CONFIGS.get(url, {}), # Legacy support - ) + url, key, api_config = await get_openai_connection(url_idx) r = None async with aiohttp.ClientSession( @@ -1114,13 +1166,7 @@ async def generate_chat_completion( detail=ERROR_MESSAGES.MODEL_NOT_FOUND(), ) - # Get the API config for the model - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(idx), - request.app.state.config.OPENAI_API_CONFIGS.get( - request.app.state.config.OPENAI_API_BASE_URLS[idx], {} - ), # Legacy support - ) + url, key, api_config = await get_openai_connection(idx) prefix_id = api_config.get('prefix_id', None) if prefix_id: @@ -1135,9 +1181,6 @@ async def generate_chat_completion( 'role': user.role, } - url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = request.app.state.config.OPENAI_API_KEYS[idx] - # Check if model is a reasoning model that needs special handling if is_openai_new_model(payload['model']): payload = openai_reasoning_model_handler(payload) @@ -1303,12 +1346,7 @@ async def embeddings(request: Request, form_data: dict, user): if model_id in models: idx = models[model_id]['urlIdx'] - url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = request.app.state.config.OPENAI_API_KEYS[idx] - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(idx), - request.app.state.config.OPENAI_API_CONFIGS.get(url, {}), # Legacy support - ) + url, key, api_config = await get_openai_connection(idx) r = None streaming = False @@ -1426,12 +1464,7 @@ async def responses( if model_id in models: idx = models[model_id]['urlIdx'] - url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = request.app.state.config.OPENAI_API_KEYS[idx] - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(idx), - request.app.state.config.OPENAI_API_CONFIGS.get(url, {}), # Legacy support - ) + url, key, api_config = await get_openai_connection(idx) r = None streaming = False @@ -1535,14 +1568,7 @@ async def proxy(path: str, request: Request, user=Depends(get_verified_user)): if model_id in models: idx = models[model_id]['urlIdx'] - url = request.app.state.config.OPENAI_API_BASE_URLS[idx] - key = request.app.state.config.OPENAI_API_KEYS[idx] - api_config = request.app.state.config.OPENAI_API_CONFIGS.get( - str(idx), - request.app.state.config.OPENAI_API_CONFIGS.get( - request.app.state.config.OPENAI_API_BASE_URLS[idx], {} - ), # Legacy support - ) + url, key, api_config = await get_openai_connection(idx) r = None streaming = False diff --git a/backend/open_webui/routers/pipelines.py b/backend/open_webui/routers/pipelines.py index 5e0d4dc199..604e45375d 100644 --- a/backend/open_webui/routers/pipelines.py +++ b/backend/open_webui/routers/pipelines.py @@ -1,3 +1,4 @@ +import asyncio import logging import os import shutil @@ -18,6 +19,8 @@ from fastapi import ( from open_webui.config import CACHE_DIR from open_webui.constants import ERROR_MESSAGES from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL +from open_webui.events import EVENTS, publish_event +from open_webui.models.config import Config from open_webui.routers.openai import get_all_models_responses from open_webui.utils.auth import get_admin_user from pydantic import BaseModel @@ -51,6 +54,12 @@ def get_sorted_filters(model_id, models): return sorted_filters +async def get_openai_connection(url_idx: int) -> tuple[str, str]: + base_urls = await Config.get('openai.api_base_urls', []) + api_keys = await Config.get('openai.api_keys', []) + return base_urls[url_idx], api_keys[url_idx] + + async def process_pipeline_inlet_filter(request, payload, user, models): user = {'id': user.id, 'email': user.email, 'name': user.name, 'role': user.role} model_id = payload['model'] @@ -69,8 +78,7 @@ async def process_pipeline_inlet_filter(request, payload, user, models): except Exception: continue - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) if not key: continue @@ -133,8 +141,7 @@ async def process_pipeline_outlet_filter(request, payload, user, models): except Exception: continue - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) if not key: continue @@ -194,11 +201,12 @@ async def get_pipelines_list(request: Request, user=Depends(get_admin_user)): log.debug(f'get_pipelines_list: get_openai_models_responses returned {responses}') urlIdxs = [idx for idx, response in enumerate(responses) if response is not None and 'pipelines' in response] + base_urls = await Config.get('openai.api_base_urls', []) return { 'data': [ { - 'url': request.app.state.config.OPENAI_API_BASE_URLS[urlIdx], + 'url': base_urls[urlIdx], 'idx': urlIdx, } for urlIdx in urlIdxs @@ -229,12 +237,14 @@ async def upload_pipeline( response = None try: - # Save the uploaded file - with open(file_path, 'wb') as buffer: - shutil.copyfileobj(file.file, buffer) + # Save the uploaded file off the event loop (uploads can be large). + def _save_upload(): + with open(file_path, 'wb') as buffer: + shutil.copyfileobj(file.file, buffer) - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + await asyncio.to_thread(_save_upload) + + url, key = await get_openai_connection(urlIdx) headers = {'Authorization': f'Bearer {key}'} @@ -257,6 +267,13 @@ async def upload_pipeline( response.raise_for_status() data = await response.json() + await publish_event( + request, + EVENTS.PIPELINE_UPLOADED, + actor=user, + subject_id=data.get('id') or filename, + data={'url_idx': urlIdx, 'filename': filename}, + ) return {**data} except Exception as e: # Handle connection error here @@ -294,8 +311,7 @@ async def add_pipeline(request: Request, form_data: AddPipelineForm, user=Depend try: urlIdx = form_data.urlIdx - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.post( @@ -307,6 +323,13 @@ async def add_pipeline(request: Request, form_data: AddPipelineForm, user=Depend response.raise_for_status() data = await response.json() + await publish_event( + request, + EVENTS.PIPELINE_ADDED, + actor=user, + subject_id=data.get('id') or form_data.url, + data={'url_idx': urlIdx, 'url': form_data.url}, + ) return {**data} except Exception as e: # Handle connection error here @@ -338,8 +361,7 @@ async def delete_pipeline(request: Request, form_data: DeletePipelineForm, user= try: urlIdx = form_data.urlIdx - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.delete( @@ -351,6 +373,13 @@ async def delete_pipeline(request: Request, form_data: DeletePipelineForm, user= response.raise_for_status() data = await response.json() + await publish_event( + request, + EVENTS.PIPELINE_DELETED, + actor=user, + subject_id=form_data.id, + data={'url_idx': urlIdx}, + ) return {**data} except Exception as e: # Handle connection error here @@ -375,8 +404,7 @@ async def delete_pipeline(request: Request, form_data: DeletePipelineForm, user= async def get_pipelines(request: Request, urlIdx: Optional[int] = None, user=Depends(get_admin_user)): response = None try: - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.get( @@ -416,8 +444,7 @@ async def get_pipeline_valves( ): response = None try: - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.get( @@ -428,6 +455,13 @@ async def get_pipeline_valves( response.raise_for_status() data = await response.json() + await publish_event( + request, + EVENTS.PIPELINE_VALVES_UPDATED, + actor=user, + subject_id=pipeline_id, + data={'url_idx': urlIdx}, + ) return {**data} except Exception as e: # Handle connection error here @@ -457,8 +491,7 @@ async def get_pipeline_valves_spec( ): response = None try: - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.get( @@ -499,8 +532,7 @@ async def update_pipeline_valves( ): response = None try: - url = request.app.state.config.OPENAI_API_BASE_URLS[urlIdx] - key = request.app.state.config.OPENAI_API_KEYS[urlIdx] + url, key = await get_openai_connection(urlIdx) async with aiohttp.ClientSession(trust_env=True) as session: async with session.post( diff --git a/backend/open_webui/routers/prompts.py b/backend/open_webui/routers/prompts.py index 1054288da0..0e3c9c6ee4 100644 --- a/backend/open_webui/routers/prompts.py +++ b/backend/open_webui/routers/prompts.py @@ -5,8 +5,10 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.prompt_history import ( PromptHistories, @@ -149,13 +151,13 @@ async def create_new_prompt( await has_permission( user.id, 'workspace.prompts', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ) or await has_permission( user.id, 'workspace.prompts_import', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ) ): @@ -165,7 +167,7 @@ async def create_new_prompt( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -177,6 +179,13 @@ async def create_new_prompt( prompt = await Prompts.insert_new_prompt(user.id, form_data, db=db) if prompt: + await publish_event( + request, + EVENTS.PROMPT_CREATED, + actor=user, + subject_id=prompt.id, + data={'name': prompt.name, 'command': prompt.command}, + ) return prompt raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -281,7 +290,7 @@ async def update_prompt_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -291,6 +300,13 @@ async def update_prompt_by_id( # Use the ID from the found prompt updated_prompt = await Prompts.update_prompt_by_id(prompt.id, form_data, user.id, db=db) if updated_prompt: + await publish_event( + request, + EVENTS.PROMPT_UPDATED, + actor=user, + subject_id=updated_prompt.id, + data={'name': updated_prompt.name, 'command': updated_prompt.command}, + ) return updated_prompt else: raise HTTPException( @@ -306,6 +322,7 @@ async def update_prompt_by_id( @router.post('/id/{prompt_id}/update/meta', response_model=PromptModel | None) async def update_prompt_metadata( + request: Request, prompt_id: str, form_data: PromptMetadataForm, user=Depends(get_verified_user), @@ -349,6 +366,13 @@ async def update_prompt_metadata( prompt.id, form_data.name, form_data.command, form_data.tags, db=db ) if updated_prompt: + await publish_event( + request, + EVENTS.PROMPT_UPDATED, + actor=user, + subject_id=updated_prompt.id, + data={'name': updated_prompt.name, 'command': updated_prompt.command}, + ) return updated_prompt else: raise HTTPException( @@ -359,6 +383,7 @@ async def update_prompt_metadata( @router.post('/id/{prompt_id}/update/version', response_model=PromptModel | None) async def set_prompt_version( + request: Request, prompt_id: str, form_data: PromptVersionUpdateForm, user=Depends(get_verified_user), @@ -389,6 +414,13 @@ async def set_prompt_version( updated_prompt = await Prompts.update_prompt_version(prompt.id, form_data.version_id, db=db) if updated_prompt: + await publish_event( + request, + EVENTS.PROMPT_VERSION_UPDATED, + actor=user, + subject_id=updated_prompt.id, + data={'version_id': updated_prompt.version_id}, + ) return updated_prompt else: raise HTTPException( @@ -438,7 +470,7 @@ async def update_prompt_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -447,7 +479,15 @@ async def update_prompt_access_by_id( await AccessGrants.set_access_grants('prompt', prompt_id, form_data.access_grants, db=db) - return await Prompts.get_prompt_by_id(prompt_id, db=db) + updated_prompt = await Prompts.get_prompt_by_id(prompt_id, db=db) + await publish_event( + request, + EVENTS.PROMPT_ACCESS_UPDATED, + actor=user, + subject_id=prompt_id, + data={'name': updated_prompt.name if updated_prompt else None}, + ) + return updated_prompt ############################ @@ -457,7 +497,10 @@ async def update_prompt_access_by_id( @router.post('/id/{prompt_id}/toggle', response_model=PromptModel | None) async def toggle_prompt_active( - prompt_id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, + prompt_id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), ): prompt = await Prompts.get_prompt_by_id(prompt_id, db=db) @@ -485,6 +528,14 @@ async def toggle_prompt_active( result = await Prompts.toggle_prompt_active(prompt.id, db=db) if result: + await publish_event( + request, + EVENTS.PROMPT_ENABLED if result.is_active else EVENTS.PROMPT_DISABLED, + actor=user, + subject_id=result.id, + subject_type='prompt', + data={'name': result.name, 'command': result.command}, + ) return result raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -499,7 +550,10 @@ async def toggle_prompt_active( @router.delete('/id/{prompt_id}/delete', response_model=bool) async def delete_prompt_by_id( - prompt_id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session) + request: Request, + prompt_id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), ): prompt = await Prompts.get_prompt_by_id(prompt_id, db=db) @@ -526,6 +580,14 @@ async def delete_prompt_by_id( ) result = await Prompts.delete_prompt_by_id(prompt.id, db=db) + if result: + await publish_event( + request, + EVENTS.PROMPT_DELETED, + actor=user, + subject_id=prompt.id, + data={'name': prompt.name, 'command': prompt.command}, + ) return result diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 70f6cf6309..3f62af4af4 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -10,6 +10,7 @@ import shutil import uuid from datetime import datetime from pathlib import Path +from types import SimpleNamespace from typing import Callable, Iterator, Optional, Sequence, Union import tiktoken @@ -55,14 +56,17 @@ from open_webui.env import ( SENTENCE_TRANSFORMERS_CROSS_ENCODER_SIGMOID_ACTIVATION_FUNCTION, SENTENCE_TRANSFORMERS_MODEL_KWARGS, ) +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_db, get_async_session from open_webui.models.files import FileModel, Files, FileUpdateForm from open_webui.models.knowledge import Knowledges +from open_webui.models.config import Config # Document loaders from open_webui.retrieval.loaders.youtube import YoutubeLoader from open_webui.retrieval.utils import ( build_loader_from_config, + get_loader_config, filter_accessible_collections, get_content_from_url, get_embedding_function, @@ -91,6 +95,7 @@ from open_webui.retrieval.web.kagi import search_kagi # Web search engines from open_webui.retrieval.web.main import SearchResult +from open_webui.retrieval.web.microsoft_web_iq import search_microsoft_web_iq from open_webui.retrieval.web.mojeek import search_mojeek from open_webui.retrieval.web.ollama import search_ollama_cloud from open_webui.retrieval.web.perplexity import search_perplexity @@ -99,6 +104,7 @@ from open_webui.retrieval.web.searchapi import search_searchapi from open_webui.retrieval.web.searxng import search_searxng from open_webui.retrieval.web.serpapi import search_serpapi from open_webui.retrieval.web.serper import search_serper +from open_webui.retrieval.web.serphouse import search_serphouse from open_webui.retrieval.web.serply import search_serply from open_webui.retrieval.web.serpstack import search_serpstack from open_webui.retrieval.web.sougou import search_sougou @@ -176,7 +182,7 @@ def get_rf( except Exception as e: log.error(f'ColBERT: {e}') - raise Exception(ERROR_MESSAGES.DEFAULT(e)) + raise Exception(ERROR_MESSAGES.DEFAULT(e, 'Error loading reranking model')) else: if engine == 'external': try: @@ -190,7 +196,7 @@ def get_rf( ) except Exception as e: log.error(f'ExternalReranking: {e}') - raise Exception(ERROR_MESSAGES.DEFAULT(e)) + raise Exception(ERROR_MESSAGES.DEFAULT(e, 'Error loading reranking model')) else: import sentence_transformers import torch @@ -210,7 +216,7 @@ def get_rf( ) except Exception as e: log.error(f'CrossEncoder: {e}') - raise Exception(ERROR_MESSAGES.DEFAULT('CrossEncoder error')) + raise Exception(ERROR_MESSAGES.DEFAULT(e, 'CrossEncoder error')) # Safely adjust pad_token_id if missing as some models do not have this in config try: @@ -240,6 +246,190 @@ def get_rf( router = APIRouter() +RETRIEVAL_CONFIG_KEYS = { + 'ALLOWED_FILE_EXTENSIONS': 'rag.file.allowed_extensions', + 'AZURE_AI_SEARCH_API_KEY': 'web.search.azure_ai_search_api_key', + 'AZURE_AI_SEARCH_ENDPOINT': 'web.search.azure_ai_search_endpoint', + 'AZURE_AI_SEARCH_INDEX_NAME': 'web.search.azure_ai_search_index_name', + 'BING_SEARCH_V7_ENDPOINT': 'web.search.bing_search_v7_endpoint', + 'BING_SEARCH_V7_SUBSCRIPTION_KEY': 'web.search.bing_search_v7_subscription_key', + 'BOCHA_SEARCH_API_KEY': 'web.search.bocha_search_api_key', + 'BRAVE_SEARCH_API_KEY': 'web.search.brave_search_api_key', + 'BRAVE_SEARCH_CONTEXT_TOKENS': 'web.search.brave_search_context_tokens', + 'BYPASS_EMBEDDING_AND_RETRIEVAL': 'rag.bypass_embedding_and_retrieval', + 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL': 'web.search.bypass_embedding_and_retrieval', + 'BYPASS_WEB_SEARCH_WEB_LOADER': 'web.search.bypass_web_loader', + 'CHUNK_MIN_SIZE_TARGET': 'rag.chunk_min_size_target', + 'CHUNK_OVERLAP': 'rag.chunk_overlap', + 'CHUNK_SIZE': 'rag.chunk_size', + 'CONTENT_EXTRACTION_ENGINE': 'rag.content_extraction_engine', + 'DATALAB_MARKER_ADDITIONAL_CONFIG': 'rag.datalab_marker_additional_config', + 'DATALAB_MARKER_API_BASE_URL': 'rag.datalab_marker_api_base_url', + 'DATALAB_MARKER_API_KEY': 'rag.datalab_marker_api_key', + 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': 'rag.datalab_marker_disable_image_extraction', + 'DATALAB_MARKER_FORCE_OCR': 'rag.datalab_marker_force_ocr', + 'DATALAB_MARKER_FORMAT_LINES': 'rag.datalab_marker_format_lines', + 'DATALAB_MARKER_OUTPUT_FORMAT': 'rag.datalab_marker_output_format', + 'DATALAB_MARKER_PAGINATE': 'rag.datalab_marker_paginate', + 'DATALAB_MARKER_SKIP_CACHE': 'rag.datalab_marker_skip_cache', + 'DATALAB_MARKER_STRIP_EXISTING_OCR': 'rag.datalab_marker_strip_existing_ocr', + 'DATALAB_MARKER_USE_LLM': 'rag.datalab_marker_use_llm', + 'DDGS_BACKEND': 'web.search.ddgs_backend', + 'DOCLING_API_KEY': 'rag.docling_api_key', + 'DOCLING_PARAMS': 'rag.docling_params', + 'DOCLING_SERVER_URL': 'rag.docling_server_url', + 'DOCUMENT_INTELLIGENCE_ENDPOINT': 'rag.document_intelligence_endpoint', + 'DOCUMENT_INTELLIGENCE_KEY': 'rag.document_intelligence_key', + 'DOCUMENT_INTELLIGENCE_MODEL': 'rag.document_intelligence_model', + 'ENABLE_ASYNC_EMBEDDING': 'rag.enable_async_embedding', + 'ENABLE_GOOGLE_DRIVE_INTEGRATION': 'google_drive.enable', + 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER': 'rag.enable_markdown_header_text_splitter', + 'ENABLE_ONEDRIVE_INTEGRATION': 'onedrive.enable', + 'ENABLE_RAG_HYBRID_SEARCH': 'rag.enable_hybrid_search', + 'ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS': 'rag.enable_hybrid_search_enriched_texts', + 'ENABLE_WEB_LOADER_SSL_VERIFICATION': 'web.loader.ssl_verification', + 'ENABLE_WEB_SEARCH': 'web.search.enable', + 'ENABLE_WEB_SEARCH_CONFIRMATION': 'web.search.confirmation.enable', + 'WEB_SEARCH_CONFIRMATION_CONTENT': 'web.search.confirmation.content', + 'EXA_API_KEY': 'web.search.exa_api_key', + 'EXTERNAL_DOCUMENT_LOADER_API_KEY': 'rag.external_document_loader_api_key', + 'EXTERNAL_DOCUMENT_LOADER_HEADERS': 'rag.external_document_loader_headers', + 'EXTERNAL_DOCUMENT_LOADER_URL': 'rag.external_document_loader_url', + 'EXTERNAL_WEB_LOADER_API_KEY': 'web.loader.external_web_loader_api_key', + 'EXTERNAL_WEB_LOADER_URL': 'web.loader.external_web_loader_url', + 'EXTERNAL_WEB_SEARCH_API_KEY': 'web.search.external_web_search_api_key', + 'EXTERNAL_WEB_SEARCH_URL': 'web.search.external_web_search_url', + 'FILE_IMAGE_COMPRESSION_HEIGHT': 'file.image_compression_height', + 'FILE_IMAGE_COMPRESSION_WIDTH': 'file.image_compression_width', + 'FILE_MAX_COUNT': 'rag.file.max_count', + 'FILE_MAX_SIZE': 'rag.file.max_size', + 'FIRECRAWL_API_BASE_URL': 'web.loader.firecrawl_api_url', + 'FIRECRAWL_API_KEY': 'web.loader.firecrawl_api_key', + 'FIRECRAWL_TIMEOUT': 'web.loader.firecrawl_timeout', + 'GOOGLE_PSE_API_KEY': 'web.search.google_pse_api_key', + 'GOOGLE_PSE_ENGINE_ID': 'web.search.google_pse_engine_id', + 'HYBRID_BM25_WEIGHT': 'rag.hybrid_bm25_weight', + 'JINA_API_BASE_URL': 'web.search.jina_api_base_url', + 'JINA_API_KEY': 'web.search.jina_api_key', + 'KAGI_SEARCH_API_KEY': 'web.search.kagi_search_api_key', + 'LINKUP_API_KEY': 'web.search.linkup_api_key', + 'LINKUP_SEARCH_PARAMS': 'web.search.linkup_search_params', + 'MINERU_API_KEY': 'rag.mineru_api_key', + 'MINERU_API_MODE': 'rag.mineru_api_mode', + 'MINERU_API_TIMEOUT': 'rag.mineru_api_timeout', + 'MINERU_API_URL': 'rag.mineru_api_url', + 'MINERU_FILE_EXTENSIONS': 'rag.mineru_file_extensions', + 'MINERU_PARAMS': 'rag.mineru_params', + 'MICROSOFT_WEB_IQ_API_BASE_URL': 'web.search.microsoft_web_iq_api_base_url', + 'MICROSOFT_WEB_IQ_API_KEY': 'web.search.microsoft_web_iq_api_key', + 'MICROSOFT_WEB_IQ_LANGUAGE': 'web.search.microsoft_web_iq_language', + 'MISTRAL_OCR_API_BASE_URL': 'rag.mistral_ocr_api_base_url', + 'MISTRAL_OCR_API_KEY': 'rag.mistral_ocr_api_key', + 'MISTRAL_OCR_USE_BASE64': 'rag.mistral_ocr_use_base64', + 'MOJEEK_SEARCH_API_KEY': 'web.search.mojeek_search_api_key', + 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY': 'web.search.ollama_cloud_api_key', + 'PADDLEOCR_VL_BASE_URL': 'rag.paddleocr_vl_base_url', + 'PADDLEOCR_VL_TOKEN': 'rag.paddleocr_vl_token', + 'PDF_EXTRACT_IMAGES': 'rag.pdf_extract_images', + 'PDF_LOADER_MODE': 'rag.pdf_loader_mode', + 'PERPLEXITY_API_KEY': 'web.search.perplexity_api_key', + 'PERPLEXITY_MODEL': 'web.search.perplexity_model', + 'PERPLEXITY_SEARCH_API_URL': 'web.search.perplexity_search_api_url', + 'PERPLEXITY_SEARCH_CONTEXT_USAGE': 'web.search.perplexity_search_context_usage', + 'PLAYWRIGHT_TIMEOUT': 'web.loader.playwright_timeout', + 'PLAYWRIGHT_WS_URL': 'web.loader.playwright_ws_url', + 'RAG_AZURE_OPENAI_API_KEY': 'rag.azure_openai.api_key', + 'RAG_AZURE_OPENAI_API_VERSION': 'rag.azure_openai.api_version', + 'RAG_AZURE_OPENAI_BASE_URL': 'rag.azure_openai.base_url', + 'RAG_EMBEDDING_BATCH_SIZE': 'rag.embedding_batch_size', + 'RAG_EMBEDDING_CONCURRENT_REQUESTS': 'rag.embedding_concurrent_requests', + 'RAG_EMBEDDING_ENGINE': 'rag.embedding_engine', + 'RAG_EMBEDDING_MODEL': 'rag.embedding_model', + 'RAG_TOKENIZER_MODEL': 'rag.tokenizer_model', + 'RAG_EXTERNAL_RERANKER_API_KEY': 'rag.external_reranker_api_key', + 'RAG_EXTERNAL_RERANKER_TIMEOUT': 'rag.external_reranker_timeout', + 'RAG_EXTERNAL_RERANKER_URL': 'rag.external_reranker_url', + 'RAG_FULL_CONTEXT': 'rag.full_context', + 'RAG_OLLAMA_API_KEY': 'rag.ollama.api_key', + 'RAG_OLLAMA_BASE_URL': 'rag.ollama.base_url', + 'RAG_OPENAI_API_BASE_URL': 'rag.openai.api_base_url', + 'RAG_OPENAI_API_KEY': 'rag.openai.api_key', + 'RAG_RERANKING_BATCH_SIZE': 'rag.reranking_batch_size', + 'RAG_RERANKING_ENGINE': 'rag.reranking_engine', + 'RAG_RERANKING_MODEL': 'rag.reranking_model', + 'RAG_TEMPLATE': 'rag.template', + 'RELEVANCE_THRESHOLD': 'rag.relevance_threshold', + 'SEARCHAPI_API_KEY': 'web.search.searchapi_api_key', + 'SEARCHAPI_ENGINE': 'web.search.searchapi_engine', + 'SEARXNG_LANGUAGE': 'web.search.searxng_language', + 'SEARXNG_QUERY_URL': 'web.search.searxng_query_url', + 'SERPAPI_API_KEY': 'web.search.serpapi_api_key', + 'SERPAPI_ENGINE': 'web.search.serpapi_engine', + 'SERPER_API_KEY': 'web.search.serper_api_key', + 'SERPHOUSE_API_KEY': 'web.search.serphouse_api_key', + 'SERPHOUSE_DOMAIN': 'web.search.serphouse_domain', + 'SERPLY_API_KEY': 'web.search.serply_api_key', + 'SERPSTACK_API_KEY': 'web.search.serpstack_api_key', + 'SERPSTACK_HTTPS': 'web.search.serpstack_https', + 'SOUGOU_API_SID': 'web.search.sougou_api_sid', + 'SOUGOU_API_SK': 'web.search.sougou_api_sk', + 'TAVILY_API_KEY': 'web.search.tavily_api_key', + 'TAVILY_EXTRACT_DEPTH': 'web.search.tavily_extract_depth', + 'TEXT_SPLITTER': 'rag.text_splitter', + 'TIKA_SERVER_URL': 'rag.tika_server_url', + 'TIKTOKEN_ENCODING_NAME': 'rag.tiktoken_encoding_name', + 'TOP_K': 'rag.top_k', + 'TOP_K_RERANKER': 'rag.top_k_reranker', + 'USER_PERMISSIONS': 'user.permissions', + 'WEBUI_URL': 'webui.url', + 'WEB_FETCH_MAX_CONTENT_LENGTH': 'web.fetch.max_content_length', + 'WEB_LOADER_CONCURRENT_REQUESTS': 'web.loader.concurrent_requests', + 'WEB_LOADER_ENGINE': 'web.loader.engine', + 'WEB_LOADER_TIMEOUT': 'web.loader.timeout', + 'WEB_SEARCH_CONCURRENT_REQUESTS': 'web.search.concurrent_requests', + 'WEB_SEARCH_DOMAIN_FILTER_LIST': 'web.search.domain.filter_list', + 'WEB_SEARCH_ENGINE': 'web.search.engine', + 'WEB_SEARCH_RESULT_COUNT': 'web.search.result_count', + 'WEB_SEARCH_TRUST_ENV': 'web.search.trust_env', + 'YACY_PASSWORD': 'web.search.yacy_password', + 'YACY_QUERY_URL': 'web.search.yacy_query_url', + 'YACY_USERNAME': 'web.search.yacy_username', + 'YANDEX_WEB_SEARCH_API_KEY': 'web.search.yandex_web_search_api_key', + 'YANDEX_WEB_SEARCH_CONFIG': 'web.search.yandex_web_search_config', + 'YANDEX_WEB_SEARCH_URL': 'web.search.yandex_web_search_url', + 'YOUCOM_API_KEY': 'web.search.youcom_api_key', + 'YOUTUBE_LOADER_LANGUAGE': 'rag.youtube_loader_language', + 'YOUTUBE_LOADER_PROXY_URL': 'rag.youtube_loader_proxy_url', +} + + +class RetrievalConfig(SimpleNamespace): + def __init__(self, values: dict): + super().__init__(**values) + object.__setattr__(self, '_updates', {}) + + def __setattr__(self, key: str, value): + if key.startswith('_'): + object.__setattr__(self, key, value) + return + object.__setattr__(self, key, value) + if key in RETRIEVAL_CONFIG_KEYS: + self._updates[RETRIEVAL_CONFIG_KEYS[key]] = value + + async def save(self) -> None: + if self._updates: + await Config.upsert(dict(self._updates)) + self._updates.clear() + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +async def get_retrieval_config() -> RetrievalConfig: + return RetrievalConfig(await get_config_values(RETRIEVAL_CONFIG_KEYS)) + class CollectionNameForm(BaseModel): collection_name: str | None = None @@ -255,25 +445,26 @@ class SearchForm(BaseModel): @router.get('/embedding') async def get_embedding_config(request: Request, user=Depends(get_admin_user)): + config = await get_retrieval_config() return { 'status': True, - 'RAG_EMBEDDING_ENGINE': request.app.state.config.RAG_EMBEDDING_ENGINE, - 'RAG_EMBEDDING_MODEL': request.app.state.config.RAG_EMBEDDING_MODEL, - 'RAG_EMBEDDING_BATCH_SIZE': request.app.state.config.RAG_EMBEDDING_BATCH_SIZE, - 'ENABLE_ASYNC_EMBEDDING': request.app.state.config.ENABLE_ASYNC_EMBEDDING, - 'RAG_EMBEDDING_CONCURRENT_REQUESTS': request.app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS, + 'RAG_EMBEDDING_ENGINE': config.RAG_EMBEDDING_ENGINE, + 'RAG_EMBEDDING_MODEL': config.RAG_EMBEDDING_MODEL, + 'RAG_EMBEDDING_BATCH_SIZE': config.RAG_EMBEDDING_BATCH_SIZE, + 'ENABLE_ASYNC_EMBEDDING': config.ENABLE_ASYNC_EMBEDDING, + 'RAG_EMBEDDING_CONCURRENT_REQUESTS': config.RAG_EMBEDDING_CONCURRENT_REQUESTS, 'openai_config': { - 'url': request.app.state.config.RAG_OPENAI_API_BASE_URL, - 'key': request.app.state.config.RAG_OPENAI_API_KEY, + 'url': config.RAG_OPENAI_API_BASE_URL, + 'key': config.RAG_OPENAI_API_KEY, }, 'ollama_config': { - 'url': request.app.state.config.RAG_OLLAMA_BASE_URL, - 'key': request.app.state.config.RAG_OLLAMA_API_KEY, + 'url': config.RAG_OLLAMA_BASE_URL, + 'key': config.RAG_OLLAMA_API_KEY, }, 'azure_openai_config': { - 'url': request.app.state.config.RAG_AZURE_OPENAI_BASE_URL, - 'key': request.app.state.config.RAG_AZURE_OPENAI_API_KEY, - 'version': request.app.state.config.RAG_AZURE_OPENAI_API_VERSION, + 'url': config.RAG_AZURE_OPENAI_BASE_URL, + 'key': config.RAG_AZURE_OPENAI_API_KEY, + 'version': config.RAG_AZURE_OPENAI_API_VERSION, }, } @@ -305,8 +496,9 @@ class EmbeddingModelUpdateForm(BaseModel): RAG_EMBEDDING_CONCURRENT_REQUESTS: int | None = 0 -def unload_embedding_model(request: Request): - if request.app.state.config.RAG_EMBEDDING_ENGINE == '': +async def unload_embedding_model(request: Request): + config = await get_retrieval_config() + if config.RAG_EMBEDDING_ENGINE == '': # unloads current internal embedding model and clears VRAM cache request.app.state.ef = None request.app.state.EMBEDDING_FUNCTION = None @@ -322,247 +514,259 @@ def unload_embedding_model(request: Request): @router.post('/embedding/update') async def update_embedding_config(request: Request, form_data: EmbeddingModelUpdateForm, user=Depends(get_admin_user)): - log.info( - f'Updating embedding model: {request.app.state.config.RAG_EMBEDDING_MODEL} to {form_data.RAG_EMBEDDING_MODEL}' - ) - unload_embedding_model(request) + config = await get_retrieval_config() + log.info(f'Updating embedding model: {config.RAG_EMBEDDING_MODEL} to {form_data.RAG_EMBEDDING_MODEL}') + await unload_embedding_model(request) try: - request.app.state.config.RAG_EMBEDDING_ENGINE = form_data.RAG_EMBEDDING_ENGINE - request.app.state.config.RAG_EMBEDDING_MODEL = form_data.RAG_EMBEDDING_MODEL.strip() - request.app.state.config.RAG_EMBEDDING_BATCH_SIZE = form_data.RAG_EMBEDDING_BATCH_SIZE - request.app.state.config.ENABLE_ASYNC_EMBEDDING = form_data.ENABLE_ASYNC_EMBEDDING - request.app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS = form_data.RAG_EMBEDDING_CONCURRENT_REQUESTS + config.RAG_EMBEDDING_ENGINE = form_data.RAG_EMBEDDING_ENGINE + config.RAG_EMBEDDING_MODEL = form_data.RAG_EMBEDDING_MODEL.strip() + config.RAG_EMBEDDING_BATCH_SIZE = form_data.RAG_EMBEDDING_BATCH_SIZE + config.ENABLE_ASYNC_EMBEDDING = form_data.ENABLE_ASYNC_EMBEDDING + config.RAG_EMBEDDING_CONCURRENT_REQUESTS = form_data.RAG_EMBEDDING_CONCURRENT_REQUESTS - if request.app.state.config.RAG_EMBEDDING_ENGINE in [ + if config.RAG_EMBEDDING_ENGINE in [ 'ollama', 'openai', 'azure_openai', ]: if form_data.openai_config is not None: - request.app.state.config.RAG_OPENAI_API_BASE_URL = form_data.openai_config.url - request.app.state.config.RAG_OPENAI_API_KEY = form_data.openai_config.key + config.RAG_OPENAI_API_BASE_URL = form_data.openai_config.url + config.RAG_OPENAI_API_KEY = form_data.openai_config.key if form_data.ollama_config is not None: - request.app.state.config.RAG_OLLAMA_BASE_URL = form_data.ollama_config.url - request.app.state.config.RAG_OLLAMA_API_KEY = form_data.ollama_config.key + config.RAG_OLLAMA_BASE_URL = form_data.ollama_config.url + config.RAG_OLLAMA_API_KEY = form_data.ollama_config.key if form_data.azure_openai_config is not None: - request.app.state.config.RAG_AZURE_OPENAI_BASE_URL = form_data.azure_openai_config.url - request.app.state.config.RAG_AZURE_OPENAI_API_KEY = form_data.azure_openai_config.key - request.app.state.config.RAG_AZURE_OPENAI_API_VERSION = form_data.azure_openai_config.version + config.RAG_AZURE_OPENAI_BASE_URL = form_data.azure_openai_config.url + config.RAG_AZURE_OPENAI_API_KEY = form_data.azure_openai_config.key + config.RAG_AZURE_OPENAI_API_VERSION = form_data.azure_openai_config.version request.app.state.ef = get_ef( - request.app.state.config.RAG_EMBEDDING_ENGINE, - request.app.state.config.RAG_EMBEDDING_MODEL, + config.RAG_EMBEDDING_ENGINE, + config.RAG_EMBEDDING_MODEL, ) request.app.state.EMBEDDING_FUNCTION = get_embedding_function( - request.app.state.config.RAG_EMBEDDING_ENGINE, - request.app.state.config.RAG_EMBEDDING_MODEL, + config.RAG_EMBEDDING_ENGINE, + config.RAG_EMBEDDING_MODEL, request.app.state.ef, ( - request.app.state.config.RAG_OPENAI_API_BASE_URL - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'openai' + config.RAG_OPENAI_API_BASE_URL + if config.RAG_EMBEDDING_ENGINE == 'openai' else ( - request.app.state.config.RAG_OLLAMA_BASE_URL - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else request.app.state.config.RAG_AZURE_OPENAI_BASE_URL + config.RAG_OLLAMA_BASE_URL + if config.RAG_EMBEDDING_ENGINE == 'ollama' + else config.RAG_AZURE_OPENAI_BASE_URL ) ), ( - request.app.state.config.RAG_OPENAI_API_KEY - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'openai' + config.RAG_OPENAI_API_KEY + if config.RAG_EMBEDDING_ENGINE == 'openai' else ( - request.app.state.config.RAG_OLLAMA_API_KEY - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else request.app.state.config.RAG_AZURE_OPENAI_API_KEY + config.RAG_OLLAMA_API_KEY + if config.RAG_EMBEDDING_ENGINE == 'ollama' + else config.RAG_AZURE_OPENAI_API_KEY ) ), - request.app.state.config.RAG_EMBEDDING_BATCH_SIZE, + config.RAG_EMBEDDING_BATCH_SIZE, azure_api_version=( - request.app.state.config.RAG_AZURE_OPENAI_API_VERSION - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'azure_openai' - else None + config.RAG_AZURE_OPENAI_API_VERSION if config.RAG_EMBEDDING_ENGINE == 'azure_openai' else None ), - enable_async=request.app.state.config.ENABLE_ASYNC_EMBEDDING, - concurrent_requests=request.app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS, + enable_async=config.ENABLE_ASYNC_EMBEDDING, + concurrent_requests=config.RAG_EMBEDDING_CONCURRENT_REQUESTS, ) + await config.save() return { 'status': True, - 'RAG_EMBEDDING_ENGINE': request.app.state.config.RAG_EMBEDDING_ENGINE, - 'RAG_EMBEDDING_MODEL': request.app.state.config.RAG_EMBEDDING_MODEL, - 'RAG_EMBEDDING_BATCH_SIZE': request.app.state.config.RAG_EMBEDDING_BATCH_SIZE, - 'ENABLE_ASYNC_EMBEDDING': request.app.state.config.ENABLE_ASYNC_EMBEDDING, - 'RAG_EMBEDDING_CONCURRENT_REQUESTS': request.app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS, + 'RAG_EMBEDDING_ENGINE': config.RAG_EMBEDDING_ENGINE, + 'RAG_EMBEDDING_MODEL': config.RAG_EMBEDDING_MODEL, + 'RAG_EMBEDDING_BATCH_SIZE': config.RAG_EMBEDDING_BATCH_SIZE, + 'ENABLE_ASYNC_EMBEDDING': config.ENABLE_ASYNC_EMBEDDING, + 'RAG_EMBEDDING_CONCURRENT_REQUESTS': config.RAG_EMBEDDING_CONCURRENT_REQUESTS, 'openai_config': { - 'url': request.app.state.config.RAG_OPENAI_API_BASE_URL, - 'key': request.app.state.config.RAG_OPENAI_API_KEY, + 'url': config.RAG_OPENAI_API_BASE_URL, + 'key': config.RAG_OPENAI_API_KEY, }, 'ollama_config': { - 'url': request.app.state.config.RAG_OLLAMA_BASE_URL, - 'key': request.app.state.config.RAG_OLLAMA_API_KEY, + 'url': config.RAG_OLLAMA_BASE_URL, + 'key': config.RAG_OLLAMA_API_KEY, }, 'azure_openai_config': { - 'url': request.app.state.config.RAG_AZURE_OPENAI_BASE_URL, - 'key': request.app.state.config.RAG_AZURE_OPENAI_API_KEY, - 'version': request.app.state.config.RAG_AZURE_OPENAI_API_VERSION, + 'url': config.RAG_AZURE_OPENAI_BASE_URL, + 'key': config.RAG_AZURE_OPENAI_API_KEY, + 'version': config.RAG_AZURE_OPENAI_API_VERSION, }, } except Exception as e: log.exception(f'Problem updating embedding model: {e}') raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating embedding configuration'), ) @router.get('/config') async def get_rag_config(request: Request, user=Depends(get_admin_user)): + config = await get_retrieval_config() + await config.save() return { 'status': True, # RAG settings - 'RAG_TEMPLATE': request.app.state.config.RAG_TEMPLATE, - 'TOP_K': request.app.state.config.TOP_K, - 'BYPASS_EMBEDDING_AND_RETRIEVAL': request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL, - 'RAG_FULL_CONTEXT': request.app.state.config.RAG_FULL_CONTEXT, + 'RAG_TEMPLATE': config.RAG_TEMPLATE, + 'TOP_K': config.TOP_K, + 'BYPASS_EMBEDDING_AND_RETRIEVAL': config.BYPASS_EMBEDDING_AND_RETRIEVAL, + 'RAG_FULL_CONTEXT': config.RAG_FULL_CONTEXT, # Hybrid search settings - 'ENABLE_RAG_HYBRID_SEARCH': request.app.state.config.ENABLE_RAG_HYBRID_SEARCH, - 'ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS': request.app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, - 'TOP_K_RERANKER': request.app.state.config.TOP_K_RERANKER, - 'RELEVANCE_THRESHOLD': request.app.state.config.RELEVANCE_THRESHOLD, - 'HYBRID_BM25_WEIGHT': request.app.state.config.HYBRID_BM25_WEIGHT, + 'ENABLE_RAG_HYBRID_SEARCH': config.ENABLE_RAG_HYBRID_SEARCH, + 'ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS': config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS, + 'TOP_K_RERANKER': config.TOP_K_RERANKER, + 'RELEVANCE_THRESHOLD': config.RELEVANCE_THRESHOLD, + 'HYBRID_BM25_WEIGHT': config.HYBRID_BM25_WEIGHT, # Content extraction settings - 'CONTENT_EXTRACTION_ENGINE': request.app.state.config.CONTENT_EXTRACTION_ENGINE, - 'PDF_EXTRACT_IMAGES': request.app.state.config.PDF_EXTRACT_IMAGES, - 'PDF_LOADER_MODE': request.app.state.config.PDF_LOADER_MODE, - 'DATALAB_MARKER_API_KEY': request.app.state.config.DATALAB_MARKER_API_KEY, - 'DATALAB_MARKER_API_BASE_URL': request.app.state.config.DATALAB_MARKER_API_BASE_URL, - 'DATALAB_MARKER_ADDITIONAL_CONFIG': request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG, - 'DATALAB_MARKER_SKIP_CACHE': request.app.state.config.DATALAB_MARKER_SKIP_CACHE, - 'DATALAB_MARKER_FORCE_OCR': request.app.state.config.DATALAB_MARKER_FORCE_OCR, - 'DATALAB_MARKER_PAGINATE': request.app.state.config.DATALAB_MARKER_PAGINATE, - 'DATALAB_MARKER_STRIP_EXISTING_OCR': request.app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR, - 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': request.app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, - 'DATALAB_MARKER_FORMAT_LINES': request.app.state.config.DATALAB_MARKER_FORMAT_LINES, - 'DATALAB_MARKER_USE_LLM': request.app.state.config.DATALAB_MARKER_USE_LLM, - 'DATALAB_MARKER_OUTPUT_FORMAT': request.app.state.config.DATALAB_MARKER_OUTPUT_FORMAT, - 'EXTERNAL_DOCUMENT_LOADER_URL': request.app.state.config.EXTERNAL_DOCUMENT_LOADER_URL, - 'EXTERNAL_DOCUMENT_LOADER_API_KEY': request.app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY, - 'TIKA_SERVER_URL': request.app.state.config.TIKA_SERVER_URL, - 'DOCLING_SERVER_URL': request.app.state.config.DOCLING_SERVER_URL, - 'DOCLING_API_KEY': request.app.state.config.DOCLING_API_KEY, - 'DOCLING_PARAMS': request.app.state.config.DOCLING_PARAMS, - 'DOCUMENT_INTELLIGENCE_ENDPOINT': request.app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT, - 'DOCUMENT_INTELLIGENCE_KEY': request.app.state.config.DOCUMENT_INTELLIGENCE_KEY, - 'DOCUMENT_INTELLIGENCE_MODEL': request.app.state.config.DOCUMENT_INTELLIGENCE_MODEL, - 'MISTRAL_OCR_API_BASE_URL': request.app.state.config.MISTRAL_OCR_API_BASE_URL, - 'MISTRAL_OCR_API_KEY': request.app.state.config.MISTRAL_OCR_API_KEY, - 'PADDLEOCR_VL_BASE_URL': request.app.state.config.PADDLEOCR_VL_BASE_URL, - 'PADDLEOCR_VL_TOKEN': request.app.state.config.PADDLEOCR_VL_TOKEN, + 'CONTENT_EXTRACTION_ENGINE': config.CONTENT_EXTRACTION_ENGINE, + 'PDF_EXTRACT_IMAGES': config.PDF_EXTRACT_IMAGES, + 'PDF_LOADER_MODE': config.PDF_LOADER_MODE, + 'DATALAB_MARKER_API_KEY': config.DATALAB_MARKER_API_KEY, + 'DATALAB_MARKER_API_BASE_URL': config.DATALAB_MARKER_API_BASE_URL, + 'DATALAB_MARKER_ADDITIONAL_CONFIG': config.DATALAB_MARKER_ADDITIONAL_CONFIG, + 'DATALAB_MARKER_SKIP_CACHE': config.DATALAB_MARKER_SKIP_CACHE, + 'DATALAB_MARKER_FORCE_OCR': config.DATALAB_MARKER_FORCE_OCR, + 'DATALAB_MARKER_PAGINATE': config.DATALAB_MARKER_PAGINATE, + 'DATALAB_MARKER_STRIP_EXISTING_OCR': config.DATALAB_MARKER_STRIP_EXISTING_OCR, + 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, + 'DATALAB_MARKER_FORMAT_LINES': config.DATALAB_MARKER_FORMAT_LINES, + 'DATALAB_MARKER_USE_LLM': config.DATALAB_MARKER_USE_LLM, + 'DATALAB_MARKER_OUTPUT_FORMAT': config.DATALAB_MARKER_OUTPUT_FORMAT, + 'EXTERNAL_DOCUMENT_LOADER_URL': config.EXTERNAL_DOCUMENT_LOADER_URL, + 'EXTERNAL_DOCUMENT_LOADER_API_KEY': config.EXTERNAL_DOCUMENT_LOADER_API_KEY, + 'EXTERNAL_DOCUMENT_LOADER_HEADERS': config.EXTERNAL_DOCUMENT_LOADER_HEADERS, + 'TIKA_SERVER_URL': config.TIKA_SERVER_URL, + 'DOCLING_SERVER_URL': config.DOCLING_SERVER_URL, + 'DOCLING_API_KEY': config.DOCLING_API_KEY, + 'DOCLING_PARAMS': config.DOCLING_PARAMS, + 'DOCUMENT_INTELLIGENCE_ENDPOINT': config.DOCUMENT_INTELLIGENCE_ENDPOINT, + 'DOCUMENT_INTELLIGENCE_KEY': config.DOCUMENT_INTELLIGENCE_KEY, + 'DOCUMENT_INTELLIGENCE_MODEL': config.DOCUMENT_INTELLIGENCE_MODEL, + 'MISTRAL_OCR_API_BASE_URL': config.MISTRAL_OCR_API_BASE_URL, + 'MISTRAL_OCR_API_KEY': config.MISTRAL_OCR_API_KEY, + 'MISTRAL_OCR_USE_BASE64': config.MISTRAL_OCR_USE_BASE64, + 'PADDLEOCR_VL_BASE_URL': config.PADDLEOCR_VL_BASE_URL, + 'PADDLEOCR_VL_TOKEN': config.PADDLEOCR_VL_TOKEN, # MinerU settings - 'MINERU_API_MODE': request.app.state.config.MINERU_API_MODE, - 'MINERU_API_URL': request.app.state.config.MINERU_API_URL, - 'MINERU_API_KEY': request.app.state.config.MINERU_API_KEY, - 'MINERU_API_TIMEOUT': request.app.state.config.MINERU_API_TIMEOUT, - 'MINERU_PARAMS': request.app.state.config.MINERU_PARAMS, - 'MINERU_FILE_EXTENSIONS': request.app.state.config.MINERU_FILE_EXTENSIONS, + 'MINERU_API_MODE': config.MINERU_API_MODE, + 'MINERU_API_URL': config.MINERU_API_URL, + 'MINERU_API_KEY': config.MINERU_API_KEY, + 'MINERU_API_TIMEOUT': config.MINERU_API_TIMEOUT, + 'MINERU_PARAMS': config.MINERU_PARAMS, + 'MINERU_FILE_EXTENSIONS': config.MINERU_FILE_EXTENSIONS, # Reranking settings - 'RAG_RERANKING_MODEL': request.app.state.config.RAG_RERANKING_MODEL, - 'RAG_RERANKING_ENGINE': request.app.state.config.RAG_RERANKING_ENGINE, - 'RAG_RERANKING_BATCH_SIZE': request.app.state.config.RAG_RERANKING_BATCH_SIZE, - 'RAG_EXTERNAL_RERANKER_URL': request.app.state.config.RAG_EXTERNAL_RERANKER_URL, - 'RAG_EXTERNAL_RERANKER_API_KEY': request.app.state.config.RAG_EXTERNAL_RERANKER_API_KEY, - 'RAG_EXTERNAL_RERANKER_TIMEOUT': request.app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT, + 'RAG_RERANKING_MODEL': config.RAG_RERANKING_MODEL, + 'RAG_RERANKING_ENGINE': config.RAG_RERANKING_ENGINE, + 'RAG_RERANKING_BATCH_SIZE': config.RAG_RERANKING_BATCH_SIZE, + 'RAG_EXTERNAL_RERANKER_URL': config.RAG_EXTERNAL_RERANKER_URL, + 'RAG_EXTERNAL_RERANKER_API_KEY': config.RAG_EXTERNAL_RERANKER_API_KEY, + 'RAG_EXTERNAL_RERANKER_TIMEOUT': config.RAG_EXTERNAL_RERANKER_TIMEOUT, # Chunking settings - 'TEXT_SPLITTER': request.app.state.config.TEXT_SPLITTER, - 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER': request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, - 'CHUNK_SIZE': request.app.state.config.CHUNK_SIZE, - 'CHUNK_MIN_SIZE_TARGET': request.app.state.config.CHUNK_MIN_SIZE_TARGET, - 'CHUNK_OVERLAP': request.app.state.config.CHUNK_OVERLAP, + 'TEXT_SPLITTER': config.TEXT_SPLITTER, + 'RAG_TOKENIZER_MODEL': config.RAG_TOKENIZER_MODEL, + 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER': config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, + 'CHUNK_SIZE': config.CHUNK_SIZE, + 'CHUNK_MIN_SIZE_TARGET': config.CHUNK_MIN_SIZE_TARGET, + 'CHUNK_OVERLAP': config.CHUNK_OVERLAP, # File upload settings - 'FILE_MAX_SIZE': request.app.state.config.FILE_MAX_SIZE, - 'FILE_MAX_COUNT': request.app.state.config.FILE_MAX_COUNT, - 'FILE_IMAGE_COMPRESSION_WIDTH': request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH, - 'FILE_IMAGE_COMPRESSION_HEIGHT': request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT, - 'ALLOWED_FILE_EXTENSIONS': request.app.state.config.ALLOWED_FILE_EXTENSIONS, + 'FILE_MAX_SIZE': config.FILE_MAX_SIZE, + 'FILE_MAX_COUNT': config.FILE_MAX_COUNT, + 'FILE_IMAGE_COMPRESSION_WIDTH': config.FILE_IMAGE_COMPRESSION_WIDTH, + 'FILE_IMAGE_COMPRESSION_HEIGHT': config.FILE_IMAGE_COMPRESSION_HEIGHT, + 'ALLOWED_FILE_EXTENSIONS': config.ALLOWED_FILE_EXTENSIONS, # Integration settings - 'ENABLE_GOOGLE_DRIVE_INTEGRATION': request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION, - 'ENABLE_ONEDRIVE_INTEGRATION': request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION, + 'ENABLE_GOOGLE_DRIVE_INTEGRATION': config.ENABLE_GOOGLE_DRIVE_INTEGRATION, + 'ENABLE_ONEDRIVE_INTEGRATION': config.ENABLE_ONEDRIVE_INTEGRATION, # Web search settings 'web': { - 'ENABLE_WEB_SEARCH': request.app.state.config.ENABLE_WEB_SEARCH, - 'WEB_SEARCH_ENGINE': request.app.state.config.WEB_SEARCH_ENGINE, - 'WEB_SEARCH_TRUST_ENV': request.app.state.config.WEB_SEARCH_TRUST_ENV, - 'WEB_SEARCH_RESULT_COUNT': request.app.state.config.WEB_SEARCH_RESULT_COUNT, - 'WEB_SEARCH_CONCURRENT_REQUESTS': request.app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS, - 'WEB_FETCH_MAX_CONTENT_LENGTH': request.app.state.config.WEB_FETCH_MAX_CONTENT_LENGTH, - 'WEB_LOADER_CONCURRENT_REQUESTS': request.app.state.config.WEB_LOADER_CONCURRENT_REQUESTS, - 'WEB_SEARCH_DOMAIN_FILTER_LIST': request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL': request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, - 'BYPASS_WEB_SEARCH_WEB_LOADER': request.app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER, - 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY': request.app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, - 'SEARXNG_QUERY_URL': request.app.state.config.SEARXNG_QUERY_URL, - 'SEARXNG_LANGUAGE': request.app.state.config.SEARXNG_LANGUAGE, - 'YACY_QUERY_URL': request.app.state.config.YACY_QUERY_URL, - 'YACY_USERNAME': request.app.state.config.YACY_USERNAME, - 'YACY_PASSWORD': request.app.state.config.YACY_PASSWORD, - 'GOOGLE_PSE_API_KEY': request.app.state.config.GOOGLE_PSE_API_KEY, - 'GOOGLE_PSE_ENGINE_ID': request.app.state.config.GOOGLE_PSE_ENGINE_ID, - 'BRAVE_SEARCH_API_KEY': request.app.state.config.BRAVE_SEARCH_API_KEY, - 'BRAVE_SEARCH_CONTEXT_TOKENS': request.app.state.config.BRAVE_SEARCH_CONTEXT_TOKENS, - 'KAGI_SEARCH_API_KEY': request.app.state.config.KAGI_SEARCH_API_KEY, - 'MOJEEK_SEARCH_API_KEY': request.app.state.config.MOJEEK_SEARCH_API_KEY, - 'BOCHA_SEARCH_API_KEY': request.app.state.config.BOCHA_SEARCH_API_KEY, - 'SERPSTACK_API_KEY': request.app.state.config.SERPSTACK_API_KEY, - 'SERPSTACK_HTTPS': request.app.state.config.SERPSTACK_HTTPS, - 'SERPER_API_KEY': request.app.state.config.SERPER_API_KEY, - 'SERPLY_API_KEY': request.app.state.config.SERPLY_API_KEY, - 'DDGS_BACKEND': request.app.state.config.DDGS_BACKEND, - 'TAVILY_API_KEY': request.app.state.config.TAVILY_API_KEY, - 'SEARCHAPI_API_KEY': request.app.state.config.SEARCHAPI_API_KEY, - 'SEARCHAPI_ENGINE': request.app.state.config.SEARCHAPI_ENGINE, - 'SERPAPI_API_KEY': request.app.state.config.SERPAPI_API_KEY, - 'SERPAPI_ENGINE': request.app.state.config.SERPAPI_ENGINE, - 'JINA_API_KEY': request.app.state.config.JINA_API_KEY, - 'JINA_API_BASE_URL': request.app.state.config.JINA_API_BASE_URL, - 'BING_SEARCH_V7_ENDPOINT': request.app.state.config.BING_SEARCH_V7_ENDPOINT, - 'BING_SEARCH_V7_SUBSCRIPTION_KEY': request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY, - 'EXA_API_KEY': request.app.state.config.EXA_API_KEY, - 'PERPLEXITY_API_KEY': request.app.state.config.PERPLEXITY_API_KEY, - 'PERPLEXITY_MODEL': request.app.state.config.PERPLEXITY_MODEL, - 'PERPLEXITY_SEARCH_CONTEXT_USAGE': request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE, - 'PERPLEXITY_SEARCH_API_URL': request.app.state.config.PERPLEXITY_SEARCH_API_URL, - 'SOUGOU_API_SID': request.app.state.config.SOUGOU_API_SID, - 'SOUGOU_API_SK': request.app.state.config.SOUGOU_API_SK, - 'WEB_LOADER_ENGINE': request.app.state.config.WEB_LOADER_ENGINE, - 'WEB_LOADER_TIMEOUT': request.app.state.config.WEB_LOADER_TIMEOUT, - 'ENABLE_WEB_LOADER_SSL_VERIFICATION': request.app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION, - 'PLAYWRIGHT_WS_URL': request.app.state.config.PLAYWRIGHT_WS_URL, - 'PLAYWRIGHT_TIMEOUT': request.app.state.config.PLAYWRIGHT_TIMEOUT, - 'FIRECRAWL_API_KEY': request.app.state.config.FIRECRAWL_API_KEY, - 'FIRECRAWL_API_BASE_URL': request.app.state.config.FIRECRAWL_API_BASE_URL, - 'FIRECRAWL_TIMEOUT': request.app.state.config.FIRECRAWL_TIMEOUT, - 'TAVILY_EXTRACT_DEPTH': request.app.state.config.TAVILY_EXTRACT_DEPTH, - 'EXTERNAL_WEB_SEARCH_URL': request.app.state.config.EXTERNAL_WEB_SEARCH_URL, - 'EXTERNAL_WEB_SEARCH_API_KEY': request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY, - 'EXTERNAL_WEB_LOADER_URL': request.app.state.config.EXTERNAL_WEB_LOADER_URL, - 'EXTERNAL_WEB_LOADER_API_KEY': request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY, - 'YOUTUBE_LOADER_LANGUAGE': request.app.state.config.YOUTUBE_LOADER_LANGUAGE, - 'YOUTUBE_LOADER_PROXY_URL': request.app.state.config.YOUTUBE_LOADER_PROXY_URL, + 'ENABLE_WEB_SEARCH': config.ENABLE_WEB_SEARCH, + 'ENABLE_WEB_SEARCH_CONFIRMATION': config.ENABLE_WEB_SEARCH_CONFIRMATION, + 'WEB_SEARCH_CONFIRMATION_CONTENT': config.WEB_SEARCH_CONFIRMATION_CONTENT, + 'WEB_SEARCH_ENGINE': config.WEB_SEARCH_ENGINE, + 'WEB_SEARCH_TRUST_ENV': config.WEB_SEARCH_TRUST_ENV, + 'WEB_SEARCH_RESULT_COUNT': config.WEB_SEARCH_RESULT_COUNT, + 'WEB_SEARCH_CONCURRENT_REQUESTS': config.WEB_SEARCH_CONCURRENT_REQUESTS, + 'WEB_FETCH_MAX_CONTENT_LENGTH': config.WEB_FETCH_MAX_CONTENT_LENGTH, + 'WEB_LOADER_CONCURRENT_REQUESTS': config.WEB_LOADER_CONCURRENT_REQUESTS, + 'WEB_SEARCH_DOMAIN_FILTER_LIST': config.WEB_SEARCH_DOMAIN_FILTER_LIST, + 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL': config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, + 'BYPASS_WEB_SEARCH_WEB_LOADER': config.BYPASS_WEB_SEARCH_WEB_LOADER, + 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY': config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, + 'SEARXNG_QUERY_URL': config.SEARXNG_QUERY_URL, + 'SEARXNG_LANGUAGE': config.SEARXNG_LANGUAGE, + 'YACY_QUERY_URL': config.YACY_QUERY_URL, + 'YACY_USERNAME': config.YACY_USERNAME, + 'YACY_PASSWORD': config.YACY_PASSWORD, + 'GOOGLE_PSE_API_KEY': config.GOOGLE_PSE_API_KEY, + 'GOOGLE_PSE_ENGINE_ID': config.GOOGLE_PSE_ENGINE_ID, + 'BRAVE_SEARCH_API_KEY': config.BRAVE_SEARCH_API_KEY, + 'BRAVE_SEARCH_CONTEXT_TOKENS': config.BRAVE_SEARCH_CONTEXT_TOKENS, + 'KAGI_SEARCH_API_KEY': config.KAGI_SEARCH_API_KEY, + 'MOJEEK_SEARCH_API_KEY': config.MOJEEK_SEARCH_API_KEY, + 'BOCHA_SEARCH_API_KEY': config.BOCHA_SEARCH_API_KEY, + 'SERPSTACK_API_KEY': config.SERPSTACK_API_KEY, + 'SERPSTACK_HTTPS': config.SERPSTACK_HTTPS, + 'SERPER_API_KEY': config.SERPER_API_KEY, + 'SERPHOUSE_API_KEY': config.SERPHOUSE_API_KEY, + 'SERPHOUSE_DOMAIN': config.SERPHOUSE_DOMAIN, + 'SERPLY_API_KEY': config.SERPLY_API_KEY, + 'DDGS_BACKEND': config.DDGS_BACKEND, + 'TAVILY_API_KEY': config.TAVILY_API_KEY, + 'SEARCHAPI_API_KEY': config.SEARCHAPI_API_KEY, + 'SEARCHAPI_ENGINE': config.SEARCHAPI_ENGINE, + 'SERPAPI_API_KEY': config.SERPAPI_API_KEY, + 'SERPAPI_ENGINE': config.SERPAPI_ENGINE, + 'JINA_API_KEY': config.JINA_API_KEY, + 'JINA_API_BASE_URL': config.JINA_API_BASE_URL, + 'BING_SEARCH_V7_ENDPOINT': config.BING_SEARCH_V7_ENDPOINT, + 'BING_SEARCH_V7_SUBSCRIPTION_KEY': config.BING_SEARCH_V7_SUBSCRIPTION_KEY, + 'EXA_API_KEY': config.EXA_API_KEY, + 'PERPLEXITY_API_KEY': config.PERPLEXITY_API_KEY, + 'PERPLEXITY_MODEL': config.PERPLEXITY_MODEL, + 'PERPLEXITY_SEARCH_CONTEXT_USAGE': config.PERPLEXITY_SEARCH_CONTEXT_USAGE, + 'PERPLEXITY_SEARCH_API_URL': config.PERPLEXITY_SEARCH_API_URL, + 'MICROSOFT_WEB_IQ_API_BASE_URL': config.MICROSOFT_WEB_IQ_API_BASE_URL, + 'MICROSOFT_WEB_IQ_API_KEY': config.MICROSOFT_WEB_IQ_API_KEY, + 'MICROSOFT_WEB_IQ_LANGUAGE': config.MICROSOFT_WEB_IQ_LANGUAGE, + 'SOUGOU_API_SID': config.SOUGOU_API_SID, + 'SOUGOU_API_SK': config.SOUGOU_API_SK, + 'WEB_LOADER_ENGINE': config.WEB_LOADER_ENGINE, + 'WEB_LOADER_TIMEOUT': config.WEB_LOADER_TIMEOUT, + 'ENABLE_WEB_LOADER_SSL_VERIFICATION': config.ENABLE_WEB_LOADER_SSL_VERIFICATION, + 'PLAYWRIGHT_WS_URL': config.PLAYWRIGHT_WS_URL, + 'PLAYWRIGHT_TIMEOUT': config.PLAYWRIGHT_TIMEOUT, + 'FIRECRAWL_API_KEY': config.FIRECRAWL_API_KEY, + 'FIRECRAWL_API_BASE_URL': config.FIRECRAWL_API_BASE_URL, + 'FIRECRAWL_TIMEOUT': config.FIRECRAWL_TIMEOUT, + 'TAVILY_EXTRACT_DEPTH': config.TAVILY_EXTRACT_DEPTH, + 'EXTERNAL_WEB_SEARCH_URL': config.EXTERNAL_WEB_SEARCH_URL, + 'EXTERNAL_WEB_SEARCH_API_KEY': config.EXTERNAL_WEB_SEARCH_API_KEY, + 'EXTERNAL_WEB_LOADER_URL': config.EXTERNAL_WEB_LOADER_URL, + 'EXTERNAL_WEB_LOADER_API_KEY': config.EXTERNAL_WEB_LOADER_API_KEY, + 'YOUTUBE_LOADER_LANGUAGE': config.YOUTUBE_LOADER_LANGUAGE, + 'YOUTUBE_LOADER_PROXY_URL': config.YOUTUBE_LOADER_PROXY_URL, 'YOUTUBE_LOADER_TRANSLATION': request.app.state.YOUTUBE_LOADER_TRANSLATION, - 'YANDEX_WEB_SEARCH_URL': request.app.state.config.YANDEX_WEB_SEARCH_URL, - 'YANDEX_WEB_SEARCH_API_KEY': request.app.state.config.YANDEX_WEB_SEARCH_API_KEY, - 'YANDEX_WEB_SEARCH_CONFIG': request.app.state.config.YANDEX_WEB_SEARCH_CONFIG, - 'YOUCOM_API_KEY': request.app.state.config.YOUCOM_API_KEY, - 'LINKUP_API_KEY': request.app.state.config.LINKUP_API_KEY, - 'LINKUP_SEARCH_PARAMS': request.app.state.config.LINKUP_SEARCH_PARAMS, + 'YANDEX_WEB_SEARCH_URL': config.YANDEX_WEB_SEARCH_URL, + 'YANDEX_WEB_SEARCH_API_KEY': config.YANDEX_WEB_SEARCH_API_KEY, + 'YANDEX_WEB_SEARCH_CONFIG': config.YANDEX_WEB_SEARCH_CONFIG, + 'YOUCOM_API_KEY': config.YOUCOM_API_KEY, + 'LINKUP_API_KEY': config.LINKUP_API_KEY, + 'LINKUP_SEARCH_PARAMS': config.LINKUP_SEARCH_PARAMS, }, } class WebConfig(BaseModel): ENABLE_WEB_SEARCH: bool | None = None + ENABLE_WEB_SEARCH_CONFIRMATION: bool | None = None + WEB_SEARCH_CONFIRMATION_CONTENT: str | None = None WEB_SEARCH_ENGINE: str | None = None WEB_SEARCH_TRUST_ENV: bool | None = None WEB_SEARCH_RESULT_COUNT: int | None = None @@ -588,6 +792,8 @@ class WebConfig(BaseModel): SERPSTACK_API_KEY: str | None = None SERPSTACK_HTTPS: bool | None = None SERPER_API_KEY: str | None = None + SERPHOUSE_API_KEY: str | None = None + SERPHOUSE_DOMAIN: str | None = None SERPLY_API_KEY: str | None = None DDGS_BACKEND: str | None = None TAVILY_API_KEY: str | None = None @@ -604,6 +810,9 @@ class WebConfig(BaseModel): PERPLEXITY_MODEL: str | None = None PERPLEXITY_SEARCH_CONTEXT_USAGE: str | None = None PERPLEXITY_SEARCH_API_URL: str | None = None + MICROSOFT_WEB_IQ_API_BASE_URL: str | None = None + MICROSOFT_WEB_IQ_API_KEY: str | None = None + MICROSOFT_WEB_IQ_LANGUAGE: str | None = None SOUGOU_API_SID: str | None = None SOUGOU_API_SK: str | None = None WEB_LOADER_ENGINE: str | None = None @@ -663,6 +872,7 @@ class ConfigForm(BaseModel): EXTERNAL_DOCUMENT_LOADER_URL: str | None = None EXTERNAL_DOCUMENT_LOADER_API_KEY: str | None = None + EXTERNAL_DOCUMENT_LOADER_HEADERS: dict | None = None TIKA_SERVER_URL: str | None = None DOCLING_SERVER_URL: str | None = None @@ -673,6 +883,7 @@ class ConfigForm(BaseModel): DOCUMENT_INTELLIGENCE_MODEL: str | None = None MISTRAL_OCR_API_BASE_URL: str | None = None MISTRAL_OCR_API_KEY: str | None = None + MISTRAL_OCR_USE_BASE64: bool | None = None PADDLEOCR_VL_BASE_URL: str | None = None PADDLEOCR_VL_TOKEN: str | None = None @@ -680,7 +891,7 @@ class ConfigForm(BaseModel): MINERU_API_MODE: str | None = None MINERU_API_URL: str | None = None MINERU_API_KEY: str | None = None - MINERU_API_TIMEOUT: str | None = None + MINERU_API_TIMEOUT: int | None = None MINERU_PARAMS: dict | None = None MINERU_FILE_EXTENSIONS: list[str] | None = None @@ -694,6 +905,7 @@ class ConfigForm(BaseModel): # Chunking settings TEXT_SPLITTER: str | None = None + RAG_TOKENIZER_MODEL: str | None = None ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER: bool | None = None CHUNK_SIZE: int | None = None CHUNK_MIN_SIZE_TARGET: int | None = None @@ -717,203 +929,184 @@ class ConfigForm(BaseModel): @router.post('/config/update') async def update_rag_config(request: Request, form_data: ConfigForm, user=Depends(get_admin_user)): # RAG settings - request.app.state.config.RAG_TEMPLATE = ( - form_data.RAG_TEMPLATE if form_data.RAG_TEMPLATE is not None else request.app.state.config.RAG_TEMPLATE - ) - request.app.state.config.TOP_K = form_data.TOP_K if form_data.TOP_K is not None else request.app.state.config.TOP_K - request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = ( + config = await get_retrieval_config() + config.RAG_TEMPLATE = form_data.RAG_TEMPLATE if form_data.RAG_TEMPLATE is not None else config.RAG_TEMPLATE + config.TOP_K = form_data.TOP_K if form_data.TOP_K is not None else config.TOP_K + config.BYPASS_EMBEDDING_AND_RETRIEVAL = ( form_data.BYPASS_EMBEDDING_AND_RETRIEVAL if form_data.BYPASS_EMBEDDING_AND_RETRIEVAL is not None - else request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL + else config.BYPASS_EMBEDDING_AND_RETRIEVAL ) - request.app.state.config.RAG_FULL_CONTEXT = ( - form_data.RAG_FULL_CONTEXT - if form_data.RAG_FULL_CONTEXT is not None - else request.app.state.config.RAG_FULL_CONTEXT + config.RAG_FULL_CONTEXT = ( + form_data.RAG_FULL_CONTEXT if form_data.RAG_FULL_CONTEXT is not None else config.RAG_FULL_CONTEXT ) # Hybrid search settings - request.app.state.config.ENABLE_RAG_HYBRID_SEARCH = ( + config.ENABLE_RAG_HYBRID_SEARCH = ( form_data.ENABLE_RAG_HYBRID_SEARCH if form_data.ENABLE_RAG_HYBRID_SEARCH is not None - else request.app.state.config.ENABLE_RAG_HYBRID_SEARCH + else config.ENABLE_RAG_HYBRID_SEARCH ) - request.app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ( + config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS = ( form_data.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS if form_data.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS is not None - else request.app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS + else config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS ) - request.app.state.config.TOP_K_RERANKER = ( - form_data.TOP_K_RERANKER if form_data.TOP_K_RERANKER is not None else request.app.state.config.TOP_K_RERANKER + config.TOP_K_RERANKER = form_data.TOP_K_RERANKER if form_data.TOP_K_RERANKER is not None else config.TOP_K_RERANKER + config.RELEVANCE_THRESHOLD = ( + form_data.RELEVANCE_THRESHOLD if form_data.RELEVANCE_THRESHOLD is not None else config.RELEVANCE_THRESHOLD ) - request.app.state.config.RELEVANCE_THRESHOLD = ( - form_data.RELEVANCE_THRESHOLD - if form_data.RELEVANCE_THRESHOLD is not None - else request.app.state.config.RELEVANCE_THRESHOLD - ) - request.app.state.config.HYBRID_BM25_WEIGHT = ( - form_data.HYBRID_BM25_WEIGHT - if form_data.HYBRID_BM25_WEIGHT is not None - else request.app.state.config.HYBRID_BM25_WEIGHT + config.HYBRID_BM25_WEIGHT = ( + form_data.HYBRID_BM25_WEIGHT if form_data.HYBRID_BM25_WEIGHT is not None else config.HYBRID_BM25_WEIGHT ) # Content extraction settings - request.app.state.config.CONTENT_EXTRACTION_ENGINE = ( + config.CONTENT_EXTRACTION_ENGINE = ( form_data.CONTENT_EXTRACTION_ENGINE if form_data.CONTENT_EXTRACTION_ENGINE is not None - else request.app.state.config.CONTENT_EXTRACTION_ENGINE + else config.CONTENT_EXTRACTION_ENGINE ) - request.app.state.config.PDF_EXTRACT_IMAGES = ( - form_data.PDF_EXTRACT_IMAGES - if form_data.PDF_EXTRACT_IMAGES is not None - else request.app.state.config.PDF_EXTRACT_IMAGES + config.PDF_EXTRACT_IMAGES = ( + form_data.PDF_EXTRACT_IMAGES if form_data.PDF_EXTRACT_IMAGES is not None else config.PDF_EXTRACT_IMAGES ) - request.app.state.config.PDF_LOADER_MODE = ( - form_data.PDF_LOADER_MODE if form_data.PDF_LOADER_MODE is not None else request.app.state.config.PDF_LOADER_MODE + config.PDF_LOADER_MODE = ( + form_data.PDF_LOADER_MODE if form_data.PDF_LOADER_MODE is not None else config.PDF_LOADER_MODE ) - request.app.state.config.DATALAB_MARKER_API_KEY = ( + config.DATALAB_MARKER_API_KEY = ( form_data.DATALAB_MARKER_API_KEY if form_data.DATALAB_MARKER_API_KEY is not None - else request.app.state.config.DATALAB_MARKER_API_KEY + else config.DATALAB_MARKER_API_KEY ) - request.app.state.config.DATALAB_MARKER_API_BASE_URL = ( + config.DATALAB_MARKER_API_BASE_URL = ( form_data.DATALAB_MARKER_API_BASE_URL if form_data.DATALAB_MARKER_API_BASE_URL is not None - else request.app.state.config.DATALAB_MARKER_API_BASE_URL + else config.DATALAB_MARKER_API_BASE_URL ) - request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG = ( + config.DATALAB_MARKER_ADDITIONAL_CONFIG = ( form_data.DATALAB_MARKER_ADDITIONAL_CONFIG if form_data.DATALAB_MARKER_ADDITIONAL_CONFIG is not None - else request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG + else config.DATALAB_MARKER_ADDITIONAL_CONFIG ) - request.app.state.config.DATALAB_MARKER_SKIP_CACHE = ( + config.DATALAB_MARKER_SKIP_CACHE = ( form_data.DATALAB_MARKER_SKIP_CACHE if form_data.DATALAB_MARKER_SKIP_CACHE is not None - else request.app.state.config.DATALAB_MARKER_SKIP_CACHE + else config.DATALAB_MARKER_SKIP_CACHE ) - request.app.state.config.DATALAB_MARKER_FORCE_OCR = ( + config.DATALAB_MARKER_FORCE_OCR = ( form_data.DATALAB_MARKER_FORCE_OCR if form_data.DATALAB_MARKER_FORCE_OCR is not None - else request.app.state.config.DATALAB_MARKER_FORCE_OCR + else config.DATALAB_MARKER_FORCE_OCR ) - request.app.state.config.DATALAB_MARKER_PAGINATE = ( + config.DATALAB_MARKER_PAGINATE = ( form_data.DATALAB_MARKER_PAGINATE if form_data.DATALAB_MARKER_PAGINATE is not None - else request.app.state.config.DATALAB_MARKER_PAGINATE + else config.DATALAB_MARKER_PAGINATE ) - request.app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR = ( + config.DATALAB_MARKER_STRIP_EXISTING_OCR = ( form_data.DATALAB_MARKER_STRIP_EXISTING_OCR if form_data.DATALAB_MARKER_STRIP_EXISTING_OCR is not None - else request.app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR + else config.DATALAB_MARKER_STRIP_EXISTING_OCR ) - request.app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = ( + config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION = ( form_data.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION if form_data.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION is not None - else request.app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION + else config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION ) - request.app.state.config.DATALAB_MARKER_FORMAT_LINES = ( + config.DATALAB_MARKER_FORMAT_LINES = ( form_data.DATALAB_MARKER_FORMAT_LINES if form_data.DATALAB_MARKER_FORMAT_LINES is not None - else request.app.state.config.DATALAB_MARKER_FORMAT_LINES + else config.DATALAB_MARKER_FORMAT_LINES ) - request.app.state.config.DATALAB_MARKER_OUTPUT_FORMAT = ( + config.DATALAB_MARKER_OUTPUT_FORMAT = ( form_data.DATALAB_MARKER_OUTPUT_FORMAT if form_data.DATALAB_MARKER_OUTPUT_FORMAT is not None - else request.app.state.config.DATALAB_MARKER_OUTPUT_FORMAT + else config.DATALAB_MARKER_OUTPUT_FORMAT ) - request.app.state.config.DATALAB_MARKER_USE_LLM = ( + config.DATALAB_MARKER_USE_LLM = ( form_data.DATALAB_MARKER_USE_LLM if form_data.DATALAB_MARKER_USE_LLM is not None - else request.app.state.config.DATALAB_MARKER_USE_LLM + else config.DATALAB_MARKER_USE_LLM ) - request.app.state.config.EXTERNAL_DOCUMENT_LOADER_URL = ( + config.EXTERNAL_DOCUMENT_LOADER_URL = ( form_data.EXTERNAL_DOCUMENT_LOADER_URL if form_data.EXTERNAL_DOCUMENT_LOADER_URL is not None - else request.app.state.config.EXTERNAL_DOCUMENT_LOADER_URL + else config.EXTERNAL_DOCUMENT_LOADER_URL ) - request.app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY = ( + config.EXTERNAL_DOCUMENT_LOADER_API_KEY = ( form_data.EXTERNAL_DOCUMENT_LOADER_API_KEY if form_data.EXTERNAL_DOCUMENT_LOADER_API_KEY is not None - else request.app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY + else config.EXTERNAL_DOCUMENT_LOADER_API_KEY ) - request.app.state.config.TIKA_SERVER_URL = ( - form_data.TIKA_SERVER_URL if form_data.TIKA_SERVER_URL is not None else request.app.state.config.TIKA_SERVER_URL + config.EXTERNAL_DOCUMENT_LOADER_HEADERS = ( + form_data.EXTERNAL_DOCUMENT_LOADER_HEADERS + if form_data.EXTERNAL_DOCUMENT_LOADER_HEADERS is not None + else config.EXTERNAL_DOCUMENT_LOADER_HEADERS ) - request.app.state.config.DOCLING_SERVER_URL = ( - form_data.DOCLING_SERVER_URL - if form_data.DOCLING_SERVER_URL is not None - else request.app.state.config.DOCLING_SERVER_URL + config.TIKA_SERVER_URL = ( + form_data.TIKA_SERVER_URL if form_data.TIKA_SERVER_URL is not None else config.TIKA_SERVER_URL ) - request.app.state.config.DOCLING_API_KEY = ( - form_data.DOCLING_API_KEY if form_data.DOCLING_API_KEY is not None else request.app.state.config.DOCLING_API_KEY + config.DOCLING_SERVER_URL = ( + form_data.DOCLING_SERVER_URL if form_data.DOCLING_SERVER_URL is not None else config.DOCLING_SERVER_URL ) - request.app.state.config.DOCLING_PARAMS = ( - form_data.DOCLING_PARAMS if form_data.DOCLING_PARAMS is not None else request.app.state.config.DOCLING_PARAMS + config.DOCLING_API_KEY = ( + form_data.DOCLING_API_KEY if form_data.DOCLING_API_KEY is not None else config.DOCLING_API_KEY ) - request.app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT = ( + config.DOCLING_PARAMS = form_data.DOCLING_PARAMS if form_data.DOCLING_PARAMS is not None else config.DOCLING_PARAMS + config.DOCUMENT_INTELLIGENCE_ENDPOINT = ( form_data.DOCUMENT_INTELLIGENCE_ENDPOINT if form_data.DOCUMENT_INTELLIGENCE_ENDPOINT is not None - else request.app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT + else config.DOCUMENT_INTELLIGENCE_ENDPOINT ) - request.app.state.config.DOCUMENT_INTELLIGENCE_KEY = ( + config.DOCUMENT_INTELLIGENCE_KEY = ( form_data.DOCUMENT_INTELLIGENCE_KEY if form_data.DOCUMENT_INTELLIGENCE_KEY is not None - else request.app.state.config.DOCUMENT_INTELLIGENCE_KEY + else config.DOCUMENT_INTELLIGENCE_KEY ) - request.app.state.config.DOCUMENT_INTELLIGENCE_MODEL = ( + config.DOCUMENT_INTELLIGENCE_MODEL = ( form_data.DOCUMENT_INTELLIGENCE_MODEL if form_data.DOCUMENT_INTELLIGENCE_MODEL is not None - else request.app.state.config.DOCUMENT_INTELLIGENCE_MODEL + else config.DOCUMENT_INTELLIGENCE_MODEL ) - request.app.state.config.MISTRAL_OCR_API_BASE_URL = ( + config.MISTRAL_OCR_API_BASE_URL = ( form_data.MISTRAL_OCR_API_BASE_URL if form_data.MISTRAL_OCR_API_BASE_URL is not None - else request.app.state.config.MISTRAL_OCR_API_BASE_URL + else config.MISTRAL_OCR_API_BASE_URL ) - request.app.state.config.MISTRAL_OCR_API_KEY = ( - form_data.MISTRAL_OCR_API_KEY - if form_data.MISTRAL_OCR_API_KEY is not None - else request.app.state.config.MISTRAL_OCR_API_KEY + config.MISTRAL_OCR_API_KEY = ( + form_data.MISTRAL_OCR_API_KEY if form_data.MISTRAL_OCR_API_KEY is not None else config.MISTRAL_OCR_API_KEY ) - request.app.state.config.PADDLEOCR_VL_BASE_URL = ( - form_data.PADDLEOCR_VL_BASE_URL - if form_data.PADDLEOCR_VL_BASE_URL is not None - else request.app.state.config.PADDLEOCR_VL_BASE_URL + config.MISTRAL_OCR_USE_BASE64 = ( + form_data.MISTRAL_OCR_USE_BASE64 + if form_data.MISTRAL_OCR_USE_BASE64 is not None + else config.MISTRAL_OCR_USE_BASE64 ) - request.app.state.config.PADDLEOCR_VL_TOKEN = ( - form_data.PADDLEOCR_VL_TOKEN - if form_data.PADDLEOCR_VL_TOKEN is not None - else request.app.state.config.PADDLEOCR_VL_TOKEN + config.PADDLEOCR_VL_BASE_URL = ( + form_data.PADDLEOCR_VL_BASE_URL if form_data.PADDLEOCR_VL_BASE_URL is not None else config.PADDLEOCR_VL_BASE_URL + ) + config.PADDLEOCR_VL_TOKEN = ( + form_data.PADDLEOCR_VL_TOKEN if form_data.PADDLEOCR_VL_TOKEN is not None else config.PADDLEOCR_VL_TOKEN ) # MinerU settings - request.app.state.config.MINERU_API_MODE = ( - form_data.MINERU_API_MODE if form_data.MINERU_API_MODE is not None else request.app.state.config.MINERU_API_MODE + config.MINERU_API_MODE = ( + form_data.MINERU_API_MODE if form_data.MINERU_API_MODE is not None else config.MINERU_API_MODE ) - request.app.state.config.MINERU_API_URL = ( - form_data.MINERU_API_URL if form_data.MINERU_API_URL is not None else request.app.state.config.MINERU_API_URL + config.MINERU_API_URL = form_data.MINERU_API_URL if form_data.MINERU_API_URL is not None else config.MINERU_API_URL + config.MINERU_API_KEY = form_data.MINERU_API_KEY if form_data.MINERU_API_KEY is not None else config.MINERU_API_KEY + config.MINERU_API_TIMEOUT = ( + form_data.MINERU_API_TIMEOUT if form_data.MINERU_API_TIMEOUT is not None else config.MINERU_API_TIMEOUT ) - request.app.state.config.MINERU_API_KEY = ( - form_data.MINERU_API_KEY if form_data.MINERU_API_KEY is not None else request.app.state.config.MINERU_API_KEY - ) - request.app.state.config.MINERU_API_TIMEOUT = ( - form_data.MINERU_API_TIMEOUT - if form_data.MINERU_API_TIMEOUT is not None - else request.app.state.config.MINERU_API_TIMEOUT - ) - request.app.state.config.MINERU_PARAMS = ( - form_data.MINERU_PARAMS if form_data.MINERU_PARAMS is not None else request.app.state.config.MINERU_PARAMS - ) - request.app.state.config.MINERU_FILE_EXTENSIONS = ( + config.MINERU_PARAMS = form_data.MINERU_PARAMS if form_data.MINERU_PARAMS is not None else config.MINERU_PARAMS + config.MINERU_FILE_EXTENSIONS = ( form_data.MINERU_FILE_EXTENSIONS if form_data.MINERU_FILE_EXTENSIONS is not None - else request.app.state.config.MINERU_FILE_EXTENSIONS + else config.MINERU_FILE_EXTENSIONS ) # Reranking settings - if request.app.state.config.RAG_RERANKING_ENGINE == '': + if config.RAG_RERANKING_ENGINE == '': # Unloading the internal reranker and clear VRAM memory request.app.state.rf = None request.app.state.RERANKING_FUNCTION = None @@ -925,338 +1118,343 @@ async def update_rag_config(request: Request, form_data: ConfigForm, user=Depend if torch.cuda.is_available(): torch.cuda.empty_cache() - request.app.state.config.RAG_RERANKING_ENGINE = ( - form_data.RAG_RERANKING_ENGINE - if form_data.RAG_RERANKING_ENGINE is not None - else request.app.state.config.RAG_RERANKING_ENGINE + config.RAG_RERANKING_ENGINE = ( + form_data.RAG_RERANKING_ENGINE if form_data.RAG_RERANKING_ENGINE is not None else config.RAG_RERANKING_ENGINE ) - request.app.state.config.RAG_EXTERNAL_RERANKER_URL = ( + config.RAG_EXTERNAL_RERANKER_URL = ( form_data.RAG_EXTERNAL_RERANKER_URL if form_data.RAG_EXTERNAL_RERANKER_URL is not None - else request.app.state.config.RAG_EXTERNAL_RERANKER_URL + else config.RAG_EXTERNAL_RERANKER_URL ) - request.app.state.config.RAG_EXTERNAL_RERANKER_API_KEY = ( + config.RAG_EXTERNAL_RERANKER_API_KEY = ( form_data.RAG_EXTERNAL_RERANKER_API_KEY if form_data.RAG_EXTERNAL_RERANKER_API_KEY is not None - else request.app.state.config.RAG_EXTERNAL_RERANKER_API_KEY + else config.RAG_EXTERNAL_RERANKER_API_KEY ) - request.app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT = ( + config.RAG_EXTERNAL_RERANKER_TIMEOUT = ( form_data.RAG_EXTERNAL_RERANKER_TIMEOUT if form_data.RAG_EXTERNAL_RERANKER_TIMEOUT is not None - else request.app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT + else config.RAG_EXTERNAL_RERANKER_TIMEOUT ) - request.app.state.config.RAG_RERANKING_BATCH_SIZE = ( + config.RAG_RERANKING_BATCH_SIZE = ( form_data.RAG_RERANKING_BATCH_SIZE if form_data.RAG_RERANKING_BATCH_SIZE is not None - else request.app.state.config.RAG_RERANKING_BATCH_SIZE + else config.RAG_RERANKING_BATCH_SIZE ) - log.info( - f'Updating reranking model: {request.app.state.config.RAG_RERANKING_MODEL} to {form_data.RAG_RERANKING_MODEL}' - ) + log.info(f'Updating reranking model: {config.RAG_RERANKING_MODEL} to {form_data.RAG_RERANKING_MODEL}') try: - request.app.state.config.RAG_RERANKING_MODEL = ( - form_data.RAG_RERANKING_MODEL - if form_data.RAG_RERANKING_MODEL is not None - else request.app.state.config.RAG_RERANKING_MODEL + config.RAG_RERANKING_MODEL = ( + form_data.RAG_RERANKING_MODEL if form_data.RAG_RERANKING_MODEL is not None else config.RAG_RERANKING_MODEL ) try: - if ( - request.app.state.config.ENABLE_RAG_HYBRID_SEARCH - and not request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL - ): + if config.ENABLE_RAG_HYBRID_SEARCH and not config.BYPASS_EMBEDDING_AND_RETRIEVAL: request.app.state.rf = get_rf( - request.app.state.config.RAG_RERANKING_ENGINE, - request.app.state.config.RAG_RERANKING_MODEL, - request.app.state.config.RAG_EXTERNAL_RERANKER_URL, - request.app.state.config.RAG_EXTERNAL_RERANKER_API_KEY, - request.app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT, + config.RAG_RERANKING_ENGINE, + config.RAG_RERANKING_MODEL, + config.RAG_EXTERNAL_RERANKER_URL, + config.RAG_EXTERNAL_RERANKER_API_KEY, + config.RAG_EXTERNAL_RERANKER_TIMEOUT, ) request.app.state.RERANKING_FUNCTION = get_reranking_function( - request.app.state.config.RAG_RERANKING_ENGINE, - request.app.state.config.RAG_RERANKING_MODEL, + config.RAG_RERANKING_ENGINE, + config.RAG_RERANKING_MODEL, request.app.state.rf, - reranking_batch_size=request.app.state.config.RAG_RERANKING_BATCH_SIZE, + reranking_batch_size=config.RAG_RERANKING_BATCH_SIZE, ) except Exception as e: log.error(f'Error loading reranking model: {e}') - request.app.state.config.ENABLE_RAG_HYBRID_SEARCH = False + config.ENABLE_RAG_HYBRID_SEARCH = False except Exception as e: log.exception(f'Problem updating reranking model: {e}') raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating reranking configuration'), ) # Chunking settings - request.app.state.config.TEXT_SPLITTER = ( - form_data.TEXT_SPLITTER if form_data.TEXT_SPLITTER is not None else request.app.state.config.TEXT_SPLITTER - ) - request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = ( + config.TEXT_SPLITTER = form_data.TEXT_SPLITTER if form_data.TEXT_SPLITTER is not None else config.TEXT_SPLITTER + config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER = ( form_data.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER if form_data.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER is not None - else request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER + else config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER ) - request.app.state.config.CHUNK_SIZE = ( - form_data.CHUNK_SIZE if form_data.CHUNK_SIZE is not None else request.app.state.config.CHUNK_SIZE + config.CHUNK_SIZE = form_data.CHUNK_SIZE if form_data.CHUNK_SIZE is not None else config.CHUNK_SIZE + config.CHUNK_MIN_SIZE_TARGET = ( + form_data.CHUNK_MIN_SIZE_TARGET if form_data.CHUNK_MIN_SIZE_TARGET is not None else config.CHUNK_MIN_SIZE_TARGET ) - request.app.state.config.CHUNK_MIN_SIZE_TARGET = ( - form_data.CHUNK_MIN_SIZE_TARGET - if form_data.CHUNK_MIN_SIZE_TARGET is not None - else request.app.state.config.CHUNK_MIN_SIZE_TARGET - ) - request.app.state.config.CHUNK_OVERLAP = ( - form_data.CHUNK_OVERLAP if form_data.CHUNK_OVERLAP is not None else request.app.state.config.CHUNK_OVERLAP + config.CHUNK_OVERLAP = form_data.CHUNK_OVERLAP if form_data.CHUNK_OVERLAP is not None else config.CHUNK_OVERLAP + config.RAG_TOKENIZER_MODEL = ( + form_data.RAG_TOKENIZER_MODEL.strip() + if form_data.RAG_TOKENIZER_MODEL is not None + else config.RAG_TOKENIZER_MODEL ) # File upload settings # Empty string means "clear to None" (unlimited/no compression), # None means "don't change", int means "set to this value" if form_data.FILE_MAX_SIZE is not None: - request.app.state.config.FILE_MAX_SIZE = None if form_data.FILE_MAX_SIZE == '' else form_data.FILE_MAX_SIZE + config.FILE_MAX_SIZE = None if form_data.FILE_MAX_SIZE == '' else form_data.FILE_MAX_SIZE if form_data.FILE_MAX_COUNT is not None: - request.app.state.config.FILE_MAX_COUNT = None if form_data.FILE_MAX_COUNT == '' else form_data.FILE_MAX_COUNT + config.FILE_MAX_COUNT = None if form_data.FILE_MAX_COUNT == '' else form_data.FILE_MAX_COUNT if form_data.FILE_IMAGE_COMPRESSION_WIDTH is not None: - request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = ( + config.FILE_IMAGE_COMPRESSION_WIDTH = ( None if form_data.FILE_IMAGE_COMPRESSION_WIDTH == '' else form_data.FILE_IMAGE_COMPRESSION_WIDTH ) if form_data.FILE_IMAGE_COMPRESSION_HEIGHT is not None: - request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = ( + config.FILE_IMAGE_COMPRESSION_HEIGHT = ( None if form_data.FILE_IMAGE_COMPRESSION_HEIGHT == '' else form_data.FILE_IMAGE_COMPRESSION_HEIGHT ) - request.app.state.config.ALLOWED_FILE_EXTENSIONS = ( + config.ALLOWED_FILE_EXTENSIONS = ( form_data.ALLOWED_FILE_EXTENSIONS if form_data.ALLOWED_FILE_EXTENSIONS is not None - else request.app.state.config.ALLOWED_FILE_EXTENSIONS + else config.ALLOWED_FILE_EXTENSIONS ) # Integration settings - request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ( + config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ( form_data.ENABLE_GOOGLE_DRIVE_INTEGRATION if form_data.ENABLE_GOOGLE_DRIVE_INTEGRATION is not None - else request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION + else config.ENABLE_GOOGLE_DRIVE_INTEGRATION ) - request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION = ( + config.ENABLE_ONEDRIVE_INTEGRATION = ( form_data.ENABLE_ONEDRIVE_INTEGRATION if form_data.ENABLE_ONEDRIVE_INTEGRATION is not None - else request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION + else config.ENABLE_ONEDRIVE_INTEGRATION ) if form_data.web is not None: # Web search settings - request.app.state.config.ENABLE_WEB_SEARCH = form_data.web.ENABLE_WEB_SEARCH - request.app.state.config.WEB_SEARCH_ENGINE = form_data.web.WEB_SEARCH_ENGINE - request.app.state.config.WEB_SEARCH_TRUST_ENV = form_data.web.WEB_SEARCH_TRUST_ENV - request.app.state.config.WEB_SEARCH_RESULT_COUNT = form_data.web.WEB_SEARCH_RESULT_COUNT - request.app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS = form_data.web.WEB_SEARCH_CONCURRENT_REQUESTS - request.app.state.config.WEB_FETCH_MAX_CONTENT_LENGTH = form_data.web.WEB_FETCH_MAX_CONTENT_LENGTH - request.app.state.config.WEB_LOADER_CONCURRENT_REQUESTS = form_data.web.WEB_LOADER_CONCURRENT_REQUESTS - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST = form_data.web.WEB_SEARCH_DOMAIN_FILTER_LIST - request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = ( - form_data.web.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL - ) - request.app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER = form_data.web.BYPASS_WEB_SEARCH_WEB_LOADER - request.app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY = form_data.web.OLLAMA_CLOUD_WEB_SEARCH_API_KEY - request.app.state.config.SEARXNG_QUERY_URL = form_data.web.SEARXNG_QUERY_URL - request.app.state.config.SEARXNG_LANGUAGE = form_data.web.SEARXNG_LANGUAGE - request.app.state.config.YACY_QUERY_URL = form_data.web.YACY_QUERY_URL - request.app.state.config.YACY_USERNAME = form_data.web.YACY_USERNAME - request.app.state.config.YACY_PASSWORD = form_data.web.YACY_PASSWORD - request.app.state.config.GOOGLE_PSE_API_KEY = form_data.web.GOOGLE_PSE_API_KEY - request.app.state.config.GOOGLE_PSE_ENGINE_ID = form_data.web.GOOGLE_PSE_ENGINE_ID - request.app.state.config.BRAVE_SEARCH_API_KEY = form_data.web.BRAVE_SEARCH_API_KEY + config.ENABLE_WEB_SEARCH = form_data.web.ENABLE_WEB_SEARCH + config.ENABLE_WEB_SEARCH_CONFIRMATION = form_data.web.ENABLE_WEB_SEARCH_CONFIRMATION + config.WEB_SEARCH_CONFIRMATION_CONTENT = form_data.web.WEB_SEARCH_CONFIRMATION_CONTENT + config.WEB_SEARCH_ENGINE = form_data.web.WEB_SEARCH_ENGINE + config.WEB_SEARCH_TRUST_ENV = form_data.web.WEB_SEARCH_TRUST_ENV + config.WEB_SEARCH_RESULT_COUNT = form_data.web.WEB_SEARCH_RESULT_COUNT + config.WEB_SEARCH_CONCURRENT_REQUESTS = form_data.web.WEB_SEARCH_CONCURRENT_REQUESTS + config.WEB_FETCH_MAX_CONTENT_LENGTH = form_data.web.WEB_FETCH_MAX_CONTENT_LENGTH + config.WEB_LOADER_CONCURRENT_REQUESTS = form_data.web.WEB_LOADER_CONCURRENT_REQUESTS + config.WEB_SEARCH_DOMAIN_FILTER_LIST = form_data.web.WEB_SEARCH_DOMAIN_FILTER_LIST + config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = form_data.web.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL + config.BYPASS_WEB_SEARCH_WEB_LOADER = form_data.web.BYPASS_WEB_SEARCH_WEB_LOADER + config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY = form_data.web.OLLAMA_CLOUD_WEB_SEARCH_API_KEY + config.SEARXNG_QUERY_URL = form_data.web.SEARXNG_QUERY_URL + config.SEARXNG_LANGUAGE = form_data.web.SEARXNG_LANGUAGE + config.YACY_QUERY_URL = form_data.web.YACY_QUERY_URL + config.YACY_USERNAME = form_data.web.YACY_USERNAME + config.YACY_PASSWORD = form_data.web.YACY_PASSWORD + config.GOOGLE_PSE_API_KEY = form_data.web.GOOGLE_PSE_API_KEY + config.GOOGLE_PSE_ENGINE_ID = form_data.web.GOOGLE_PSE_ENGINE_ID + config.BRAVE_SEARCH_API_KEY = form_data.web.BRAVE_SEARCH_API_KEY if form_data.web.BRAVE_SEARCH_CONTEXT_TOKENS is not None: - request.app.state.config.BRAVE_SEARCH_CONTEXT_TOKENS = form_data.web.BRAVE_SEARCH_CONTEXT_TOKENS - request.app.state.config.KAGI_SEARCH_API_KEY = form_data.web.KAGI_SEARCH_API_KEY - request.app.state.config.MOJEEK_SEARCH_API_KEY = form_data.web.MOJEEK_SEARCH_API_KEY - request.app.state.config.BOCHA_SEARCH_API_KEY = form_data.web.BOCHA_SEARCH_API_KEY - request.app.state.config.SERPSTACK_API_KEY = form_data.web.SERPSTACK_API_KEY - request.app.state.config.SERPSTACK_HTTPS = form_data.web.SERPSTACK_HTTPS - request.app.state.config.SERPER_API_KEY = form_data.web.SERPER_API_KEY - request.app.state.config.SERPLY_API_KEY = form_data.web.SERPLY_API_KEY - request.app.state.config.DDGS_BACKEND = form_data.web.DDGS_BACKEND - request.app.state.config.TAVILY_API_KEY = form_data.web.TAVILY_API_KEY - request.app.state.config.SEARCHAPI_API_KEY = form_data.web.SEARCHAPI_API_KEY - request.app.state.config.SEARCHAPI_ENGINE = form_data.web.SEARCHAPI_ENGINE - request.app.state.config.SERPAPI_API_KEY = form_data.web.SERPAPI_API_KEY - request.app.state.config.SERPAPI_ENGINE = form_data.web.SERPAPI_ENGINE - request.app.state.config.JINA_API_KEY = form_data.web.JINA_API_KEY - request.app.state.config.JINA_API_BASE_URL = form_data.web.JINA_API_BASE_URL - request.app.state.config.BING_SEARCH_V7_ENDPOINT = form_data.web.BING_SEARCH_V7_ENDPOINT - request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY = form_data.web.BING_SEARCH_V7_SUBSCRIPTION_KEY - request.app.state.config.EXA_API_KEY = form_data.web.EXA_API_KEY - request.app.state.config.PERPLEXITY_API_KEY = form_data.web.PERPLEXITY_API_KEY - request.app.state.config.PERPLEXITY_MODEL = form_data.web.PERPLEXITY_MODEL - request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE = form_data.web.PERPLEXITY_SEARCH_CONTEXT_USAGE - request.app.state.config.PERPLEXITY_SEARCH_API_URL = form_data.web.PERPLEXITY_SEARCH_API_URL - request.app.state.config.SOUGOU_API_SID = form_data.web.SOUGOU_API_SID - request.app.state.config.SOUGOU_API_SK = form_data.web.SOUGOU_API_SK + config.BRAVE_SEARCH_CONTEXT_TOKENS = form_data.web.BRAVE_SEARCH_CONTEXT_TOKENS + config.KAGI_SEARCH_API_KEY = form_data.web.KAGI_SEARCH_API_KEY + config.MOJEEK_SEARCH_API_KEY = form_data.web.MOJEEK_SEARCH_API_KEY + config.BOCHA_SEARCH_API_KEY = form_data.web.BOCHA_SEARCH_API_KEY + config.SERPSTACK_API_KEY = form_data.web.SERPSTACK_API_KEY + config.SERPSTACK_HTTPS = form_data.web.SERPSTACK_HTTPS + config.SERPER_API_KEY = form_data.web.SERPER_API_KEY + config.SERPHOUSE_API_KEY = form_data.web.SERPHOUSE_API_KEY + config.SERPHOUSE_DOMAIN = form_data.web.SERPHOUSE_DOMAIN + config.SERPLY_API_KEY = form_data.web.SERPLY_API_KEY + config.DDGS_BACKEND = form_data.web.DDGS_BACKEND + config.TAVILY_API_KEY = form_data.web.TAVILY_API_KEY + config.SEARCHAPI_API_KEY = form_data.web.SEARCHAPI_API_KEY + config.SEARCHAPI_ENGINE = form_data.web.SEARCHAPI_ENGINE + config.SERPAPI_API_KEY = form_data.web.SERPAPI_API_KEY + config.SERPAPI_ENGINE = form_data.web.SERPAPI_ENGINE + config.JINA_API_KEY = form_data.web.JINA_API_KEY + config.JINA_API_BASE_URL = form_data.web.JINA_API_BASE_URL + config.BING_SEARCH_V7_ENDPOINT = form_data.web.BING_SEARCH_V7_ENDPOINT + config.BING_SEARCH_V7_SUBSCRIPTION_KEY = form_data.web.BING_SEARCH_V7_SUBSCRIPTION_KEY + config.EXA_API_KEY = form_data.web.EXA_API_KEY + config.PERPLEXITY_API_KEY = form_data.web.PERPLEXITY_API_KEY + config.PERPLEXITY_MODEL = form_data.web.PERPLEXITY_MODEL + config.PERPLEXITY_SEARCH_CONTEXT_USAGE = form_data.web.PERPLEXITY_SEARCH_CONTEXT_USAGE + config.PERPLEXITY_SEARCH_API_URL = form_data.web.PERPLEXITY_SEARCH_API_URL + config.MICROSOFT_WEB_IQ_API_BASE_URL = form_data.web.MICROSOFT_WEB_IQ_API_BASE_URL + config.MICROSOFT_WEB_IQ_API_KEY = form_data.web.MICROSOFT_WEB_IQ_API_KEY + config.MICROSOFT_WEB_IQ_LANGUAGE = form_data.web.MICROSOFT_WEB_IQ_LANGUAGE + config.SOUGOU_API_SID = form_data.web.SOUGOU_API_SID + config.SOUGOU_API_SK = form_data.web.SOUGOU_API_SK # Web loader settings - request.app.state.config.WEB_LOADER_ENGINE = form_data.web.WEB_LOADER_ENGINE - request.app.state.config.WEB_LOADER_TIMEOUT = form_data.web.WEB_LOADER_TIMEOUT + config.WEB_LOADER_ENGINE = form_data.web.WEB_LOADER_ENGINE + config.WEB_LOADER_TIMEOUT = form_data.web.WEB_LOADER_TIMEOUT - request.app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION = form_data.web.ENABLE_WEB_LOADER_SSL_VERIFICATION - request.app.state.config.PLAYWRIGHT_WS_URL = form_data.web.PLAYWRIGHT_WS_URL - request.app.state.config.PLAYWRIGHT_TIMEOUT = form_data.web.PLAYWRIGHT_TIMEOUT - request.app.state.config.FIRECRAWL_API_KEY = form_data.web.FIRECRAWL_API_KEY - request.app.state.config.FIRECRAWL_API_BASE_URL = form_data.web.FIRECRAWL_API_BASE_URL - request.app.state.config.FIRECRAWL_TIMEOUT = form_data.web.FIRECRAWL_TIMEOUT - request.app.state.config.EXTERNAL_WEB_SEARCH_URL = form_data.web.EXTERNAL_WEB_SEARCH_URL - request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY = form_data.web.EXTERNAL_WEB_SEARCH_API_KEY - request.app.state.config.EXTERNAL_WEB_LOADER_URL = form_data.web.EXTERNAL_WEB_LOADER_URL - request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY = form_data.web.EXTERNAL_WEB_LOADER_API_KEY - request.app.state.config.TAVILY_EXTRACT_DEPTH = form_data.web.TAVILY_EXTRACT_DEPTH - request.app.state.config.YOUTUBE_LOADER_LANGUAGE = form_data.web.YOUTUBE_LOADER_LANGUAGE - request.app.state.config.YOUTUBE_LOADER_PROXY_URL = form_data.web.YOUTUBE_LOADER_PROXY_URL + config.ENABLE_WEB_LOADER_SSL_VERIFICATION = form_data.web.ENABLE_WEB_LOADER_SSL_VERIFICATION + config.PLAYWRIGHT_WS_URL = form_data.web.PLAYWRIGHT_WS_URL + config.PLAYWRIGHT_TIMEOUT = form_data.web.PLAYWRIGHT_TIMEOUT + config.FIRECRAWL_API_KEY = form_data.web.FIRECRAWL_API_KEY + config.FIRECRAWL_API_BASE_URL = form_data.web.FIRECRAWL_API_BASE_URL + config.FIRECRAWL_TIMEOUT = form_data.web.FIRECRAWL_TIMEOUT + config.EXTERNAL_WEB_SEARCH_URL = form_data.web.EXTERNAL_WEB_SEARCH_URL + config.EXTERNAL_WEB_SEARCH_API_KEY = form_data.web.EXTERNAL_WEB_SEARCH_API_KEY + config.EXTERNAL_WEB_LOADER_URL = form_data.web.EXTERNAL_WEB_LOADER_URL + config.EXTERNAL_WEB_LOADER_API_KEY = form_data.web.EXTERNAL_WEB_LOADER_API_KEY + config.TAVILY_EXTRACT_DEPTH = form_data.web.TAVILY_EXTRACT_DEPTH + config.YOUTUBE_LOADER_LANGUAGE = form_data.web.YOUTUBE_LOADER_LANGUAGE + config.YOUTUBE_LOADER_PROXY_URL = form_data.web.YOUTUBE_LOADER_PROXY_URL request.app.state.YOUTUBE_LOADER_TRANSLATION = form_data.web.YOUTUBE_LOADER_TRANSLATION - request.app.state.config.YANDEX_WEB_SEARCH_URL = form_data.web.YANDEX_WEB_SEARCH_URL - request.app.state.config.YANDEX_WEB_SEARCH_API_KEY = form_data.web.YANDEX_WEB_SEARCH_API_KEY - request.app.state.config.YANDEX_WEB_SEARCH_CONFIG = form_data.web.YANDEX_WEB_SEARCH_CONFIG - request.app.state.config.YOUCOM_API_KEY = form_data.web.YOUCOM_API_KEY - request.app.state.config.LINKUP_API_KEY = form_data.web.LINKUP_API_KEY - request.app.state.config.LINKUP_SEARCH_PARAMS = form_data.web.LINKUP_SEARCH_PARAMS + config.YANDEX_WEB_SEARCH_URL = form_data.web.YANDEX_WEB_SEARCH_URL + config.YANDEX_WEB_SEARCH_API_KEY = form_data.web.YANDEX_WEB_SEARCH_API_KEY + config.YANDEX_WEB_SEARCH_CONFIG = form_data.web.YANDEX_WEB_SEARCH_CONFIG + config.YOUCOM_API_KEY = form_data.web.YOUCOM_API_KEY + config.LINKUP_API_KEY = form_data.web.LINKUP_API_KEY + config.LINKUP_SEARCH_PARAMS = form_data.web.LINKUP_SEARCH_PARAMS + + await config.save() return { 'status': True, # RAG settings - 'RAG_TEMPLATE': request.app.state.config.RAG_TEMPLATE, - 'TOP_K': request.app.state.config.TOP_K, - 'BYPASS_EMBEDDING_AND_RETRIEVAL': request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL, - 'RAG_FULL_CONTEXT': request.app.state.config.RAG_FULL_CONTEXT, + 'RAG_TEMPLATE': config.RAG_TEMPLATE, + 'TOP_K': config.TOP_K, + 'BYPASS_EMBEDDING_AND_RETRIEVAL': config.BYPASS_EMBEDDING_AND_RETRIEVAL, + 'RAG_FULL_CONTEXT': config.RAG_FULL_CONTEXT, # Hybrid search settings - 'ENABLE_RAG_HYBRID_SEARCH': request.app.state.config.ENABLE_RAG_HYBRID_SEARCH, - 'TOP_K_RERANKER': request.app.state.config.TOP_K_RERANKER, - 'RELEVANCE_THRESHOLD': request.app.state.config.RELEVANCE_THRESHOLD, - 'HYBRID_BM25_WEIGHT': request.app.state.config.HYBRID_BM25_WEIGHT, + 'ENABLE_RAG_HYBRID_SEARCH': config.ENABLE_RAG_HYBRID_SEARCH, + 'TOP_K_RERANKER': config.TOP_K_RERANKER, + 'RELEVANCE_THRESHOLD': config.RELEVANCE_THRESHOLD, + 'HYBRID_BM25_WEIGHT': config.HYBRID_BM25_WEIGHT, # Content extraction settings - 'CONTENT_EXTRACTION_ENGINE': request.app.state.config.CONTENT_EXTRACTION_ENGINE, - 'PDF_EXTRACT_IMAGES': request.app.state.config.PDF_EXTRACT_IMAGES, - 'PDF_LOADER_MODE': request.app.state.config.PDF_LOADER_MODE, - 'DATALAB_MARKER_API_KEY': request.app.state.config.DATALAB_MARKER_API_KEY, - 'DATALAB_MARKER_API_BASE_URL': request.app.state.config.DATALAB_MARKER_API_BASE_URL, - 'DATALAB_MARKER_ADDITIONAL_CONFIG': request.app.state.config.DATALAB_MARKER_ADDITIONAL_CONFIG, - 'DATALAB_MARKER_SKIP_CACHE': request.app.state.config.DATALAB_MARKER_SKIP_CACHE, - 'DATALAB_MARKER_FORCE_OCR': request.app.state.config.DATALAB_MARKER_FORCE_OCR, - 'DATALAB_MARKER_PAGINATE': request.app.state.config.DATALAB_MARKER_PAGINATE, - 'DATALAB_MARKER_STRIP_EXISTING_OCR': request.app.state.config.DATALAB_MARKER_STRIP_EXISTING_OCR, - 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': request.app.state.config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, - 'DATALAB_MARKER_USE_LLM': request.app.state.config.DATALAB_MARKER_USE_LLM, - 'DATALAB_MARKER_OUTPUT_FORMAT': request.app.state.config.DATALAB_MARKER_OUTPUT_FORMAT, - 'EXTERNAL_DOCUMENT_LOADER_URL': request.app.state.config.EXTERNAL_DOCUMENT_LOADER_URL, - 'EXTERNAL_DOCUMENT_LOADER_API_KEY': request.app.state.config.EXTERNAL_DOCUMENT_LOADER_API_KEY, - 'TIKA_SERVER_URL': request.app.state.config.TIKA_SERVER_URL, - 'DOCLING_SERVER_URL': request.app.state.config.DOCLING_SERVER_URL, - 'DOCLING_API_KEY': request.app.state.config.DOCLING_API_KEY, - 'DOCLING_PARAMS': request.app.state.config.DOCLING_PARAMS, - 'DOCUMENT_INTELLIGENCE_ENDPOINT': request.app.state.config.DOCUMENT_INTELLIGENCE_ENDPOINT, - 'DOCUMENT_INTELLIGENCE_KEY': request.app.state.config.DOCUMENT_INTELLIGENCE_KEY, - 'DOCUMENT_INTELLIGENCE_MODEL': request.app.state.config.DOCUMENT_INTELLIGENCE_MODEL, - 'MISTRAL_OCR_API_BASE_URL': request.app.state.config.MISTRAL_OCR_API_BASE_URL, - 'MISTRAL_OCR_API_KEY': request.app.state.config.MISTRAL_OCR_API_KEY, - 'PADDLEOCR_VL_BASE_URL': request.app.state.config.PADDLEOCR_VL_BASE_URL, - 'PADDLEOCR_VL_TOKEN': request.app.state.config.PADDLEOCR_VL_TOKEN, + 'CONTENT_EXTRACTION_ENGINE': config.CONTENT_EXTRACTION_ENGINE, + 'PDF_EXTRACT_IMAGES': config.PDF_EXTRACT_IMAGES, + 'PDF_LOADER_MODE': config.PDF_LOADER_MODE, + 'DATALAB_MARKER_API_KEY': config.DATALAB_MARKER_API_KEY, + 'DATALAB_MARKER_API_BASE_URL': config.DATALAB_MARKER_API_BASE_URL, + 'DATALAB_MARKER_ADDITIONAL_CONFIG': config.DATALAB_MARKER_ADDITIONAL_CONFIG, + 'DATALAB_MARKER_SKIP_CACHE': config.DATALAB_MARKER_SKIP_CACHE, + 'DATALAB_MARKER_FORCE_OCR': config.DATALAB_MARKER_FORCE_OCR, + 'DATALAB_MARKER_PAGINATE': config.DATALAB_MARKER_PAGINATE, + 'DATALAB_MARKER_STRIP_EXISTING_OCR': config.DATALAB_MARKER_STRIP_EXISTING_OCR, + 'DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION': config.DATALAB_MARKER_DISABLE_IMAGE_EXTRACTION, + 'DATALAB_MARKER_USE_LLM': config.DATALAB_MARKER_USE_LLM, + 'DATALAB_MARKER_OUTPUT_FORMAT': config.DATALAB_MARKER_OUTPUT_FORMAT, + 'EXTERNAL_DOCUMENT_LOADER_URL': config.EXTERNAL_DOCUMENT_LOADER_URL, + 'EXTERNAL_DOCUMENT_LOADER_API_KEY': config.EXTERNAL_DOCUMENT_LOADER_API_KEY, + 'EXTERNAL_DOCUMENT_LOADER_HEADERS': config.EXTERNAL_DOCUMENT_LOADER_HEADERS, + 'TIKA_SERVER_URL': config.TIKA_SERVER_URL, + 'DOCLING_SERVER_URL': config.DOCLING_SERVER_URL, + 'DOCLING_API_KEY': config.DOCLING_API_KEY, + 'DOCLING_PARAMS': config.DOCLING_PARAMS, + 'DOCUMENT_INTELLIGENCE_ENDPOINT': config.DOCUMENT_INTELLIGENCE_ENDPOINT, + 'DOCUMENT_INTELLIGENCE_KEY': config.DOCUMENT_INTELLIGENCE_KEY, + 'DOCUMENT_INTELLIGENCE_MODEL': config.DOCUMENT_INTELLIGENCE_MODEL, + 'MISTRAL_OCR_API_BASE_URL': config.MISTRAL_OCR_API_BASE_URL, + 'MISTRAL_OCR_API_KEY': config.MISTRAL_OCR_API_KEY, + 'MISTRAL_OCR_USE_BASE64': config.MISTRAL_OCR_USE_BASE64, + 'PADDLEOCR_VL_BASE_URL': config.PADDLEOCR_VL_BASE_URL, + 'PADDLEOCR_VL_TOKEN': config.PADDLEOCR_VL_TOKEN, # MinerU settings - 'MINERU_API_MODE': request.app.state.config.MINERU_API_MODE, - 'MINERU_API_URL': request.app.state.config.MINERU_API_URL, - 'MINERU_API_KEY': request.app.state.config.MINERU_API_KEY, - 'MINERU_API_TIMEOUT': request.app.state.config.MINERU_API_TIMEOUT, - 'MINERU_PARAMS': request.app.state.config.MINERU_PARAMS, + 'MINERU_API_MODE': config.MINERU_API_MODE, + 'MINERU_API_URL': config.MINERU_API_URL, + 'MINERU_API_KEY': config.MINERU_API_KEY, + 'MINERU_API_TIMEOUT': config.MINERU_API_TIMEOUT, + 'MINERU_PARAMS': config.MINERU_PARAMS, # Reranking settings - 'RAG_RERANKING_MODEL': request.app.state.config.RAG_RERANKING_MODEL, - 'RAG_RERANKING_ENGINE': request.app.state.config.RAG_RERANKING_ENGINE, - 'RAG_EXTERNAL_RERANKER_URL': request.app.state.config.RAG_EXTERNAL_RERANKER_URL, - 'RAG_EXTERNAL_RERANKER_API_KEY': request.app.state.config.RAG_EXTERNAL_RERANKER_API_KEY, - 'RAG_EXTERNAL_RERANKER_TIMEOUT': request.app.state.config.RAG_EXTERNAL_RERANKER_TIMEOUT, + 'RAG_RERANKING_MODEL': config.RAG_RERANKING_MODEL, + 'RAG_RERANKING_ENGINE': config.RAG_RERANKING_ENGINE, + 'RAG_EXTERNAL_RERANKER_URL': config.RAG_EXTERNAL_RERANKER_URL, + 'RAG_EXTERNAL_RERANKER_API_KEY': config.RAG_EXTERNAL_RERANKER_API_KEY, + 'RAG_EXTERNAL_RERANKER_TIMEOUT': config.RAG_EXTERNAL_RERANKER_TIMEOUT, # Chunking settings - 'TEXT_SPLITTER': request.app.state.config.TEXT_SPLITTER, - 'CHUNK_SIZE': request.app.state.config.CHUNK_SIZE, - 'CHUNK_MIN_SIZE_TARGET': request.app.state.config.CHUNK_MIN_SIZE_TARGET, - 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER': request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, - 'CHUNK_OVERLAP': request.app.state.config.CHUNK_OVERLAP, + 'TEXT_SPLITTER': config.TEXT_SPLITTER, + 'RAG_TOKENIZER_MODEL': config.RAG_TOKENIZER_MODEL, + 'CHUNK_SIZE': config.CHUNK_SIZE, + 'CHUNK_MIN_SIZE_TARGET': config.CHUNK_MIN_SIZE_TARGET, + 'ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER': config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER, + 'CHUNK_OVERLAP': config.CHUNK_OVERLAP, # File upload settings - 'FILE_MAX_SIZE': request.app.state.config.FILE_MAX_SIZE, - 'FILE_MAX_COUNT': request.app.state.config.FILE_MAX_COUNT, - 'FILE_IMAGE_COMPRESSION_WIDTH': request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH, - 'FILE_IMAGE_COMPRESSION_HEIGHT': request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT, - 'ALLOWED_FILE_EXTENSIONS': request.app.state.config.ALLOWED_FILE_EXTENSIONS, + 'FILE_MAX_SIZE': config.FILE_MAX_SIZE, + 'FILE_MAX_COUNT': config.FILE_MAX_COUNT, + 'FILE_IMAGE_COMPRESSION_WIDTH': config.FILE_IMAGE_COMPRESSION_WIDTH, + 'FILE_IMAGE_COMPRESSION_HEIGHT': config.FILE_IMAGE_COMPRESSION_HEIGHT, + 'ALLOWED_FILE_EXTENSIONS': config.ALLOWED_FILE_EXTENSIONS, # Integration settings - 'ENABLE_GOOGLE_DRIVE_INTEGRATION': request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION, - 'ENABLE_ONEDRIVE_INTEGRATION': request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION, + 'ENABLE_GOOGLE_DRIVE_INTEGRATION': config.ENABLE_GOOGLE_DRIVE_INTEGRATION, + 'ENABLE_ONEDRIVE_INTEGRATION': config.ENABLE_ONEDRIVE_INTEGRATION, # Web search settings 'web': { - 'ENABLE_WEB_SEARCH': request.app.state.config.ENABLE_WEB_SEARCH, - 'WEB_SEARCH_ENGINE': request.app.state.config.WEB_SEARCH_ENGINE, - 'WEB_SEARCH_TRUST_ENV': request.app.state.config.WEB_SEARCH_TRUST_ENV, - 'WEB_SEARCH_RESULT_COUNT': request.app.state.config.WEB_SEARCH_RESULT_COUNT, - 'WEB_SEARCH_CONCURRENT_REQUESTS': request.app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS, - 'WEB_FETCH_MAX_CONTENT_LENGTH': request.app.state.config.WEB_FETCH_MAX_CONTENT_LENGTH, - 'WEB_LOADER_CONCURRENT_REQUESTS': request.app.state.config.WEB_LOADER_CONCURRENT_REQUESTS, - 'WEB_SEARCH_DOMAIN_FILTER_LIST': request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL': request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, - 'BYPASS_WEB_SEARCH_WEB_LOADER': request.app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER, - 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY': request.app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, - 'SEARXNG_QUERY_URL': request.app.state.config.SEARXNG_QUERY_URL, - 'SEARXNG_LANGUAGE': request.app.state.config.SEARXNG_LANGUAGE, - 'YACY_QUERY_URL': request.app.state.config.YACY_QUERY_URL, - 'YACY_USERNAME': request.app.state.config.YACY_USERNAME, - 'YACY_PASSWORD': request.app.state.config.YACY_PASSWORD, - 'GOOGLE_PSE_API_KEY': request.app.state.config.GOOGLE_PSE_API_KEY, - 'GOOGLE_PSE_ENGINE_ID': request.app.state.config.GOOGLE_PSE_ENGINE_ID, - 'BRAVE_SEARCH_API_KEY': request.app.state.config.BRAVE_SEARCH_API_KEY, - 'BRAVE_SEARCH_CONTEXT_TOKENS': request.app.state.config.BRAVE_SEARCH_CONTEXT_TOKENS, - 'KAGI_SEARCH_API_KEY': request.app.state.config.KAGI_SEARCH_API_KEY, - 'MOJEEK_SEARCH_API_KEY': request.app.state.config.MOJEEK_SEARCH_API_KEY, - 'BOCHA_SEARCH_API_KEY': request.app.state.config.BOCHA_SEARCH_API_KEY, - 'SERPSTACK_API_KEY': request.app.state.config.SERPSTACK_API_KEY, - 'SERPSTACK_HTTPS': request.app.state.config.SERPSTACK_HTTPS, - 'SERPER_API_KEY': request.app.state.config.SERPER_API_KEY, - 'SERPLY_API_KEY': request.app.state.config.SERPLY_API_KEY, - 'TAVILY_API_KEY': request.app.state.config.TAVILY_API_KEY, - 'SEARCHAPI_API_KEY': request.app.state.config.SEARCHAPI_API_KEY, - 'SEARCHAPI_ENGINE': request.app.state.config.SEARCHAPI_ENGINE, - 'SERPAPI_API_KEY': request.app.state.config.SERPAPI_API_KEY, - 'SERPAPI_ENGINE': request.app.state.config.SERPAPI_ENGINE, - 'JINA_API_KEY': request.app.state.config.JINA_API_KEY, - 'JINA_API_BASE_URL': request.app.state.config.JINA_API_BASE_URL, - 'BING_SEARCH_V7_ENDPOINT': request.app.state.config.BING_SEARCH_V7_ENDPOINT, - 'BING_SEARCH_V7_SUBSCRIPTION_KEY': request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY, - 'EXA_API_KEY': request.app.state.config.EXA_API_KEY, - 'PERPLEXITY_API_KEY': request.app.state.config.PERPLEXITY_API_KEY, - 'PERPLEXITY_MODEL': request.app.state.config.PERPLEXITY_MODEL, - 'PERPLEXITY_SEARCH_CONTEXT_USAGE': request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE, - 'PERPLEXITY_SEARCH_API_URL': request.app.state.config.PERPLEXITY_SEARCH_API_URL, - 'SOUGOU_API_SID': request.app.state.config.SOUGOU_API_SID, - 'SOUGOU_API_SK': request.app.state.config.SOUGOU_API_SK, - 'WEB_LOADER_ENGINE': request.app.state.config.WEB_LOADER_ENGINE, - 'WEB_LOADER_TIMEOUT': request.app.state.config.WEB_LOADER_TIMEOUT, - 'ENABLE_WEB_LOADER_SSL_VERIFICATION': request.app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION, - 'PLAYWRIGHT_WS_URL': request.app.state.config.PLAYWRIGHT_WS_URL, - 'PLAYWRIGHT_TIMEOUT': request.app.state.config.PLAYWRIGHT_TIMEOUT, - 'FIRECRAWL_API_KEY': request.app.state.config.FIRECRAWL_API_KEY, - 'FIRECRAWL_API_BASE_URL': request.app.state.config.FIRECRAWL_API_BASE_URL, - 'FIRECRAWL_TIMEOUT': request.app.state.config.FIRECRAWL_TIMEOUT, - 'TAVILY_EXTRACT_DEPTH': request.app.state.config.TAVILY_EXTRACT_DEPTH, - 'EXTERNAL_WEB_SEARCH_URL': request.app.state.config.EXTERNAL_WEB_SEARCH_URL, - 'EXTERNAL_WEB_SEARCH_API_KEY': request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY, - 'EXTERNAL_WEB_LOADER_URL': request.app.state.config.EXTERNAL_WEB_LOADER_URL, - 'EXTERNAL_WEB_LOADER_API_KEY': request.app.state.config.EXTERNAL_WEB_LOADER_API_KEY, - 'YOUTUBE_LOADER_LANGUAGE': request.app.state.config.YOUTUBE_LOADER_LANGUAGE, - 'YOUTUBE_LOADER_PROXY_URL': request.app.state.config.YOUTUBE_LOADER_PROXY_URL, + 'ENABLE_WEB_SEARCH': config.ENABLE_WEB_SEARCH, + 'ENABLE_WEB_SEARCH_CONFIRMATION': config.ENABLE_WEB_SEARCH_CONFIRMATION, + 'WEB_SEARCH_CONFIRMATION_CONTENT': config.WEB_SEARCH_CONFIRMATION_CONTENT, + 'WEB_SEARCH_ENGINE': config.WEB_SEARCH_ENGINE, + 'WEB_SEARCH_TRUST_ENV': config.WEB_SEARCH_TRUST_ENV, + 'WEB_SEARCH_RESULT_COUNT': config.WEB_SEARCH_RESULT_COUNT, + 'WEB_SEARCH_CONCURRENT_REQUESTS': config.WEB_SEARCH_CONCURRENT_REQUESTS, + 'WEB_FETCH_MAX_CONTENT_LENGTH': config.WEB_FETCH_MAX_CONTENT_LENGTH, + 'WEB_LOADER_CONCURRENT_REQUESTS': config.WEB_LOADER_CONCURRENT_REQUESTS, + 'WEB_SEARCH_DOMAIN_FILTER_LIST': config.WEB_SEARCH_DOMAIN_FILTER_LIST, + 'BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL': config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL, + 'BYPASS_WEB_SEARCH_WEB_LOADER': config.BYPASS_WEB_SEARCH_WEB_LOADER, + 'OLLAMA_CLOUD_WEB_SEARCH_API_KEY': config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, + 'SEARXNG_QUERY_URL': config.SEARXNG_QUERY_URL, + 'SEARXNG_LANGUAGE': config.SEARXNG_LANGUAGE, + 'YACY_QUERY_URL': config.YACY_QUERY_URL, + 'YACY_USERNAME': config.YACY_USERNAME, + 'YACY_PASSWORD': config.YACY_PASSWORD, + 'GOOGLE_PSE_API_KEY': config.GOOGLE_PSE_API_KEY, + 'GOOGLE_PSE_ENGINE_ID': config.GOOGLE_PSE_ENGINE_ID, + 'BRAVE_SEARCH_API_KEY': config.BRAVE_SEARCH_API_KEY, + 'BRAVE_SEARCH_CONTEXT_TOKENS': config.BRAVE_SEARCH_CONTEXT_TOKENS, + 'KAGI_SEARCH_API_KEY': config.KAGI_SEARCH_API_KEY, + 'MOJEEK_SEARCH_API_KEY': config.MOJEEK_SEARCH_API_KEY, + 'BOCHA_SEARCH_API_KEY': config.BOCHA_SEARCH_API_KEY, + 'SERPSTACK_API_KEY': config.SERPSTACK_API_KEY, + 'SERPSTACK_HTTPS': config.SERPSTACK_HTTPS, + 'SERPER_API_KEY': config.SERPER_API_KEY, + 'SERPHOUSE_API_KEY': config.SERPHOUSE_API_KEY, + 'SERPHOUSE_DOMAIN': config.SERPHOUSE_DOMAIN, + 'SERPLY_API_KEY': config.SERPLY_API_KEY, + 'TAVILY_API_KEY': config.TAVILY_API_KEY, + 'SEARCHAPI_API_KEY': config.SEARCHAPI_API_KEY, + 'SEARCHAPI_ENGINE': config.SEARCHAPI_ENGINE, + 'SERPAPI_API_KEY': config.SERPAPI_API_KEY, + 'SERPAPI_ENGINE': config.SERPAPI_ENGINE, + 'JINA_API_KEY': config.JINA_API_KEY, + 'JINA_API_BASE_URL': config.JINA_API_BASE_URL, + 'BING_SEARCH_V7_ENDPOINT': config.BING_SEARCH_V7_ENDPOINT, + 'BING_SEARCH_V7_SUBSCRIPTION_KEY': config.BING_SEARCH_V7_SUBSCRIPTION_KEY, + 'EXA_API_KEY': config.EXA_API_KEY, + 'PERPLEXITY_API_KEY': config.PERPLEXITY_API_KEY, + 'PERPLEXITY_MODEL': config.PERPLEXITY_MODEL, + 'PERPLEXITY_SEARCH_CONTEXT_USAGE': config.PERPLEXITY_SEARCH_CONTEXT_USAGE, + 'PERPLEXITY_SEARCH_API_URL': config.PERPLEXITY_SEARCH_API_URL, + 'MICROSOFT_WEB_IQ_API_BASE_URL': config.MICROSOFT_WEB_IQ_API_BASE_URL, + 'MICROSOFT_WEB_IQ_API_KEY': config.MICROSOFT_WEB_IQ_API_KEY, + 'MICROSOFT_WEB_IQ_LANGUAGE': config.MICROSOFT_WEB_IQ_LANGUAGE, + 'SOUGOU_API_SID': config.SOUGOU_API_SID, + 'SOUGOU_API_SK': config.SOUGOU_API_SK, + 'WEB_LOADER_ENGINE': config.WEB_LOADER_ENGINE, + 'WEB_LOADER_TIMEOUT': config.WEB_LOADER_TIMEOUT, + 'ENABLE_WEB_LOADER_SSL_VERIFICATION': config.ENABLE_WEB_LOADER_SSL_VERIFICATION, + 'PLAYWRIGHT_WS_URL': config.PLAYWRIGHT_WS_URL, + 'PLAYWRIGHT_TIMEOUT': config.PLAYWRIGHT_TIMEOUT, + 'FIRECRAWL_API_KEY': config.FIRECRAWL_API_KEY, + 'FIRECRAWL_API_BASE_URL': config.FIRECRAWL_API_BASE_URL, + 'FIRECRAWL_TIMEOUT': config.FIRECRAWL_TIMEOUT, + 'TAVILY_EXTRACT_DEPTH': config.TAVILY_EXTRACT_DEPTH, + 'EXTERNAL_WEB_SEARCH_URL': config.EXTERNAL_WEB_SEARCH_URL, + 'EXTERNAL_WEB_SEARCH_API_KEY': config.EXTERNAL_WEB_SEARCH_API_KEY, + 'EXTERNAL_WEB_LOADER_URL': config.EXTERNAL_WEB_LOADER_URL, + 'EXTERNAL_WEB_LOADER_API_KEY': config.EXTERNAL_WEB_LOADER_API_KEY, + 'YOUTUBE_LOADER_LANGUAGE': config.YOUTUBE_LOADER_LANGUAGE, + 'YOUTUBE_LOADER_PROXY_URL': config.YOUTUBE_LOADER_PROXY_URL, 'YOUTUBE_LOADER_TRANSLATION': request.app.state.YOUTUBE_LOADER_TRANSLATION, - 'YANDEX_WEB_SEARCH_URL': request.app.state.config.YANDEX_WEB_SEARCH_URL, - 'YANDEX_WEB_SEARCH_API_KEY': request.app.state.config.YANDEX_WEB_SEARCH_API_KEY, - 'YANDEX_WEB_SEARCH_CONFIG': request.app.state.config.YANDEX_WEB_SEARCH_CONFIG, - 'YOUCOM_API_KEY': request.app.state.config.YOUCOM_API_KEY, - 'LINKUP_API_KEY': request.app.state.config.LINKUP_API_KEY, - 'LINKUP_SEARCH_PARAMS': request.app.state.config.LINKUP_SEARCH_PARAMS, + 'YANDEX_WEB_SEARCH_URL': config.YANDEX_WEB_SEARCH_URL, + 'YANDEX_WEB_SEARCH_API_KEY': config.YANDEX_WEB_SEARCH_API_KEY, + 'YANDEX_WEB_SEARCH_CONFIG': config.YANDEX_WEB_SEARCH_CONFIG, + 'YOUCOM_API_KEY': config.YOUCOM_API_KEY, + 'LINKUP_API_KEY': config.LINKUP_API_KEY, + 'LINKUP_SEARCH_PARAMS': config.LINKUP_SEARCH_PARAMS, }, } @@ -1284,6 +1482,7 @@ def can_merge_chunks(a: Document, b: Document) -> bool: def merge_docs_to_target_size( request: Request, chunks: list[Document], + config: RetrievalConfig, ) -> list[Document]: """ Best-effort normalization of chunk sizes. @@ -1296,16 +1495,13 @@ def merge_docs_to_target_size( backward merging (append into the previous emitted chunk) for undersized chunks that can't grow forward. """ - min_size = request.app.state.config.CHUNK_MIN_SIZE_TARGET - max_size = request.app.state.config.CHUNK_SIZE + min_size = config.CHUNK_MIN_SIZE_TARGET + max_size = config.CHUNK_SIZE if min_size <= 0: return chunks - measure: Callable[[str], int] = len - if request.app.state.config.TEXT_SPLITTER == 'token': - encoding = tiktoken.get_encoding(str(request.app.state.config.TIKTOKEN_ENCODING_NAME)) - measure = lambda text: len(encoding.encode(text)) + measure = get_splitter_length_function(request, config) def _merge_backward(result: list[Document], content: str, chunk: Document) -> bool: """Try to append content into the last emitted chunk. Returns True on success.""" @@ -1358,10 +1554,48 @@ def merge_docs_to_target_size( return result +def get_transformers_tokenizer(request: Request, config: RetrievalConfig): + if config.RAG_TOKENIZER_MODEL: + from transformers import AutoTokenizer + + tokenizer_model = config.RAG_TOKENIZER_MODEL + if not os.path.exists(tokenizer_model) and '/' not in tokenizer_model: + tokenizer_model = f'sentence-transformers/{tokenizer_model}' + + return AutoTokenizer.from_pretrained( + tokenizer_model, + cache_dir=os.getenv('SENTENCE_TRANSFORMERS_HOME') or os.getenv('HF_HUB_CACHE'), + trust_remote_code=RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE, + local_files_only=not RAG_EMBEDDING_MODEL_AUTO_UPDATE, + ) + + tokenizer = getattr(getattr(request.app.state, 'ef', None), 'tokenizer', None) + if tokenizer is not None: + return tokenizer + + raise ValueError('Tokenizer model required for Token (Transformers) text splitter') + + +def get_splitter_length_function( + request: Request, + config: RetrievalConfig, +) -> Callable[[str], int]: + if config.TEXT_SPLITTER == 'token': + encoding = tiktoken.get_encoding(str(config.TIKTOKEN_ENCODING_NAME)) + return lambda text: len(encoding.encode(text, disallowed_special=())) + + if config.TEXT_SPLITTER == 'token_transformers': + tokenizer = get_transformers_tokenizer(request, config) + return lambda text: len(tokenizer.encode(text)) + + return len + + def save_docs_to_vector_db( request: Request, docs, collection_name, + config: RetrievalConfig, metadata: dict | None = None, overwrite: bool = False, split: bool = True, @@ -1408,7 +1642,7 @@ def save_docs_to_vector_db( raise ValueError(ERROR_MESSAGES.DUPLICATE_CONTENT) if split: - if request.app.state.config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER: + if config.ENABLE_MARKDOWN_HEADER_TEXT_SPLITTER: log.info('Using markdown header text splitter') # Define headers to split on - covering most common markdown header levels markdown_splitter = MarkdownHeaderTextSplitter( @@ -1436,24 +1670,34 @@ def save_docs_to_vector_db( ) docs = split_docs - if request.app.state.config.CHUNK_MIN_SIZE_TARGET > 0: - docs = merge_docs_to_target_size(request, docs) + if config.CHUNK_MIN_SIZE_TARGET > 0: + docs = merge_docs_to_target_size(request, docs, config) - if request.app.state.config.TEXT_SPLITTER in ['', 'character']: + if config.TEXT_SPLITTER in ['', 'character']: text_splitter = RecursiveCharacterTextSplitter( - chunk_size=request.app.state.config.CHUNK_SIZE, - chunk_overlap=request.app.state.config.CHUNK_OVERLAP, + chunk_size=config.CHUNK_SIZE, + chunk_overlap=config.CHUNK_OVERLAP, add_start_index=True, ) docs = text_splitter.split_documents(docs) - elif request.app.state.config.TEXT_SPLITTER == 'token': - log.info(f'Using token text splitter: {request.app.state.config.TIKTOKEN_ENCODING_NAME}') + elif config.TEXT_SPLITTER == 'token': + log.info(f'Using token text splitter: {config.TIKTOKEN_ENCODING_NAME}') - tiktoken.get_encoding(str(request.app.state.config.TIKTOKEN_ENCODING_NAME)) + tiktoken.get_encoding(str(config.TIKTOKEN_ENCODING_NAME)) text_splitter = TokenTextSplitter( - encoding_name=str(request.app.state.config.TIKTOKEN_ENCODING_NAME), - chunk_size=request.app.state.config.CHUNK_SIZE, - chunk_overlap=request.app.state.config.CHUNK_OVERLAP, + encoding_name=str(config.TIKTOKEN_ENCODING_NAME), + chunk_size=config.CHUNK_SIZE, + chunk_overlap=config.CHUNK_OVERLAP, + add_start_index=True, + ) + docs = text_splitter.split_documents(docs) + elif config.TEXT_SPLITTER == 'token_transformers': + log.info('Using transformers token text splitter') + + text_splitter = RecursiveCharacterTextSplitter( + chunk_size=config.CHUNK_SIZE, + chunk_overlap=config.CHUNK_OVERLAP, + length_function=get_splitter_length_function(request, config), add_start_index=True, ) docs = text_splitter.split_documents(docs) @@ -1469,8 +1713,8 @@ def save_docs_to_vector_db( **doc.metadata, **(metadata if metadata else {}), 'embedding_config': { - 'engine': request.app.state.config.RAG_EMBEDDING_ENGINE, - 'model': request.app.state.config.RAG_EMBEDDING_MODEL, + 'engine': config.RAG_EMBEDDING_ENGINE, + 'model': config.RAG_EMBEDDING_MODEL, }, } for doc in docs @@ -1489,35 +1733,33 @@ def save_docs_to_vector_db( log.info(f'generating embeddings for {collection_name}') embedding_function = get_embedding_function( - request.app.state.config.RAG_EMBEDDING_ENGINE, - request.app.state.config.RAG_EMBEDDING_MODEL, + config.RAG_EMBEDDING_ENGINE, + config.RAG_EMBEDDING_MODEL, request.app.state.ef, ( - request.app.state.config.RAG_OPENAI_API_BASE_URL - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'openai' + config.RAG_OPENAI_API_BASE_URL + if config.RAG_EMBEDDING_ENGINE == 'openai' else ( - request.app.state.config.RAG_OLLAMA_BASE_URL - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else request.app.state.config.RAG_AZURE_OPENAI_BASE_URL + config.RAG_OLLAMA_BASE_URL + if config.RAG_EMBEDDING_ENGINE == 'ollama' + else config.RAG_AZURE_OPENAI_BASE_URL ) ), ( - request.app.state.config.RAG_OPENAI_API_KEY - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'openai' + config.RAG_OPENAI_API_KEY + if config.RAG_EMBEDDING_ENGINE == 'openai' else ( - request.app.state.config.RAG_OLLAMA_API_KEY - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'ollama' - else request.app.state.config.RAG_AZURE_OPENAI_API_KEY + config.RAG_OLLAMA_API_KEY + if config.RAG_EMBEDDING_ENGINE == 'ollama' + else config.RAG_AZURE_OPENAI_API_KEY ) ), - request.app.state.config.RAG_EMBEDDING_BATCH_SIZE, + config.RAG_EMBEDDING_BATCH_SIZE, azure_api_version=( - request.app.state.config.RAG_AZURE_OPENAI_API_VERSION - if request.app.state.config.RAG_EMBEDDING_ENGINE == 'azure_openai' - else None + config.RAG_AZURE_OPENAI_API_VERSION if config.RAG_EMBEDDING_ENGINE == 'azure_openai' else None ), - enable_async=request.app.state.config.ENABLE_ASYNC_EMBEDDING, - concurrent_requests=request.app.state.config.RAG_EMBEDDING_CONCURRENT_REQUESTS, + enable_async=config.ENABLE_ASYNC_EMBEDDING, + concurrent_requests=config.RAG_EMBEDDING_CONCURRENT_REQUESTS, ) # Run async embedding in sync context using the main event loop @@ -1577,6 +1819,7 @@ async def process_file( Note: granular session management is used to prevent connection pool exhaustion. The session is committed before external API calls, and updates use a fresh session. """ + config = await get_retrieval_config() if user.role == 'admin': file = await Files.get_file_by_id(form_data.file_id, db=db) else: @@ -1653,8 +1896,14 @@ async def process_file( file_path = file.path if file_path: file_path = await asyncio.to_thread(Storage.get_file, file_path) - loader = build_loader_from_config(request) + loader_config = await get_loader_config() + loader = build_loader_from_config(request, loader_config) loader.user = user + loader.metadata = { + 'file_id': file.id, + 'file_name': file.filename, + 'file_content_type': file.meta.get('content_type'), + } docs = await loader.aload(file.filename, file.meta.get('content_type'), file_path) docs = [ @@ -1693,9 +1942,17 @@ async def process_file( ) hash = calculate_sha256_string(text_content) - if request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL: + if config.BYPASS_EMBEDDING_AND_RETRIEVAL: await Files.update_file_data_by_id(file.id, {'status': 'completed'}, db=db) await Files.update_file_hash_by_id(file.id, hash, db=db) + await publish_event( + request, + EVENTS.RETRIEVAL_CONTENT_PROCESSED, + actor=user, + subject_id=file.id, + subject_type='file', + data={'collection_name': None, 'filename': file.filename}, + ) return { 'status': True, 'collection_name': None, @@ -1719,6 +1976,7 @@ async def process_file( request, docs=docs, collection_name=collection_name, + config=config, metadata={ 'file_id': file.id, 'name': file.filename, @@ -1747,6 +2005,14 @@ async def process_file( ) await Files.update_file_hash_by_id(file.id, hash, db=session) + await publish_event( + request, + EVENTS.RETRIEVAL_CONTENT_PROCESSED, + actor=user, + subject_id=file.id, + subject_type='file', + data={'collection_name': collection_name, 'filename': file.filename}, + ) return { 'status': True, 'collection_name': collection_name, @@ -1812,8 +2078,17 @@ async def process_text( text_content = form_data.content log.debug(f'text_content: {text_content}') - result = await run_in_threadpool(save_docs_to_vector_db, request, docs, collection_name, user=user) + config = await get_retrieval_config() + result = await run_in_threadpool(save_docs_to_vector_db, request, docs, collection_name, config, user=user) if result: + await publish_event( + request, + EVENTS.RETRIEVAL_CONTENT_PROCESSED, + actor=user, + subject_id=collection_name, + subject_type='retrieval.collection', + data={'name': form_data.name, 'content_preview': text_content[:300]}, + ) return { 'status': True, 'collection_name': collection_name, @@ -1835,8 +2110,9 @@ async def process_web( overwrite: bool = Query(True, description='Whether to overwrite existing collection'), user=Depends(get_verified_user), ): + config = await get_retrieval_config() try: - content, docs = await run_in_threadpool(get_content_from_url, request, form_data.url) + content, docs = await get_content_from_url(request, form_data.url) log.debug(f'text_content: {content}') if process: @@ -1846,12 +2122,13 @@ async def process_web( else: await _validate_collection_access([collection_name], user, access_type='write') - if not request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL: + if not config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL: await run_in_threadpool( save_docs_to_vector_db, request, docs, collection_name, + config, overwrite=overwrite, add=(not overwrite), user=user, @@ -1878,11 +2155,13 @@ async def process_web( 'status': True, 'content': content, } + except HTTPException: + raise except Exception as e: log.exception(e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error querying knowledge base'), ) @@ -1895,149 +2174,161 @@ async def search_web(request: Request, engine: str, query: str, user=None) -> li """ # TODO: add playwright to search the web + config = await get_retrieval_config() if engine == 'ollama_cloud': return await asyncio.to_thread( search_ollama_cloud, 'https://ollama.com', - request.app.state.config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, + config.OLLAMA_CLOUD_WEB_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) elif engine == 'perplexity_search': - if request.app.state.config.PERPLEXITY_API_KEY: + if config.PERPLEXITY_API_KEY: return await asyncio.to_thread( search_perplexity_search, - request.app.state.config.PERPLEXITY_API_KEY, + config.PERPLEXITY_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - request.app.state.config.PERPLEXITY_SEARCH_API_URL, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.PERPLEXITY_SEARCH_API_URL, user, ) else: raise Exception('No PERPLEXITY_API_KEY found in environment variables') elif engine == 'searxng': - if request.app.state.config.SEARXNG_QUERY_URL: - searxng_kwargs = {'language': request.app.state.config.SEARXNG_LANGUAGE} + if config.SEARXNG_QUERY_URL: + searxng_kwargs = {'language': config.SEARXNG_LANGUAGE} return await search_searxng( - request.app.state.config.SEARXNG_QUERY_URL, + config.SEARXNG_QUERY_URL, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, **searxng_kwargs, ) else: raise Exception('No SEARXNG_QUERY_URL found in environment variables') elif engine == 'yacy': - if request.app.state.config.YACY_QUERY_URL: + if config.YACY_QUERY_URL: return await asyncio.to_thread( search_yacy, - request.app.state.config.YACY_QUERY_URL, - request.app.state.config.YACY_USERNAME, - request.app.state.config.YACY_PASSWORD, + config.YACY_QUERY_URL, + config.YACY_USERNAME, + config.YACY_PASSWORD, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No YACY_QUERY_URL found in environment variables') elif engine == 'google_pse': - if request.app.state.config.GOOGLE_PSE_API_KEY and request.app.state.config.GOOGLE_PSE_ENGINE_ID: + if config.GOOGLE_PSE_API_KEY and config.GOOGLE_PSE_ENGINE_ID: return await search_google_pse( - request.app.state.config.GOOGLE_PSE_API_KEY, - request.app.state.config.GOOGLE_PSE_ENGINE_ID, + config.GOOGLE_PSE_API_KEY, + config.GOOGLE_PSE_ENGINE_ID, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - referer=request.app.state.config.WEBUI_URL, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + referer=config.WEBUI_URL, ) else: raise Exception('No GOOGLE_PSE_API_KEY or GOOGLE_PSE_ENGINE_ID found in environment variables') elif engine == 'brave': - if request.app.state.config.BRAVE_SEARCH_API_KEY: + if config.BRAVE_SEARCH_API_KEY: return await search_brave( - request.app.state.config.BRAVE_SEARCH_API_KEY, + config.BRAVE_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No BRAVE_SEARCH_API_KEY found in environment variables') elif engine == 'brave_llm_context': - if request.app.state.config.BRAVE_SEARCH_API_KEY: + if config.BRAVE_SEARCH_API_KEY: return await asyncio.to_thread( search_brave_llm_context, - request.app.state.config.BRAVE_SEARCH_API_KEY, + config.BRAVE_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - request.app.state.config.BRAVE_SEARCH_CONTEXT_TOKENS, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.BRAVE_SEARCH_CONTEXT_TOKENS, ) else: raise Exception('No BRAVE_SEARCH_API_KEY found in environment variables') elif engine == 'kagi': - if request.app.state.config.KAGI_SEARCH_API_KEY: + if config.KAGI_SEARCH_API_KEY: return await asyncio.to_thread( search_kagi, - request.app.state.config.KAGI_SEARCH_API_KEY, + config.KAGI_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No KAGI_SEARCH_API_KEY found in environment variables') elif engine == 'mojeek': - if request.app.state.config.MOJEEK_SEARCH_API_KEY: + if config.MOJEEK_SEARCH_API_KEY: return await asyncio.to_thread( search_mojeek, - request.app.state.config.MOJEEK_SEARCH_API_KEY, + config.MOJEEK_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No MOJEEK_SEARCH_API_KEY found in environment variables') elif engine == 'bocha': - if request.app.state.config.BOCHA_SEARCH_API_KEY: + if config.BOCHA_SEARCH_API_KEY: return await asyncio.to_thread( search_bocha, - request.app.state.config.BOCHA_SEARCH_API_KEY, + config.BOCHA_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No BOCHA_SEARCH_API_KEY found in environment variables') elif engine == 'serpstack': - if request.app.state.config.SERPSTACK_API_KEY: + if config.SERPSTACK_API_KEY: return await search_serpstack( - request.app.state.config.SERPSTACK_API_KEY, + config.SERPSTACK_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - https_enabled=request.app.state.config.SERPSTACK_HTTPS, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + https_enabled=config.SERPSTACK_HTTPS, ) else: raise Exception('No SERPSTACK_API_KEY found in environment variables') elif engine == 'serper': - if request.app.state.config.SERPER_API_KEY: + if config.SERPER_API_KEY: return await search_serper( - request.app.state.config.SERPER_API_KEY, + config.SERPER_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No SERPER_API_KEY found in environment variables') + elif engine == 'serphouse': + if config.SERPHOUSE_API_KEY: + return await search_serphouse( + config.SERPHOUSE_API_KEY, + config.SERPHOUSE_DOMAIN, + query, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + ) + else: + raise Exception('No SERPHOUSE_API_KEY found in environment variables') elif engine == 'serply': - if request.app.state.config.SERPLY_API_KEY: + if config.SERPLY_API_KEY: return await asyncio.to_thread( search_serply, - request.app.state.config.SERPLY_API_KEY, + config.SERPLY_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - filter_list=request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + filter_list=config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No SERPLY_API_KEY found in environment variables') @@ -2045,89 +2336,85 @@ async def search_web(request: Request, engine: str, query: str, user=None) -> li return await asyncio.to_thread( search_duckduckgo, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - concurrent_requests=request.app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS, - backend=request.app.state.config.DDGS_BACKEND, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + concurrent_requests=config.WEB_SEARCH_CONCURRENT_REQUESTS, + backend=config.DDGS_BACKEND, ) elif engine == 'tavily': - if request.app.state.config.TAVILY_API_KEY: + if config.TAVILY_API_KEY: return await asyncio.to_thread( search_tavily, - request.app.state.config.TAVILY_API_KEY, + config.TAVILY_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No TAVILY_API_KEY found in environment variables') elif engine == 'exa': - if request.app.state.config.EXA_API_KEY: + if config.EXA_API_KEY: return await asyncio.to_thread( search_exa, - request.app.state.config.EXA_API_KEY, + config.EXA_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No EXA_API_KEY found in environment variables') elif engine == 'searchapi': - if request.app.state.config.SEARCHAPI_API_KEY: + if config.SEARCHAPI_API_KEY: return await asyncio.to_thread( search_searchapi, - request.app.state.config.SEARCHAPI_API_KEY, - request.app.state.config.SEARCHAPI_ENGINE, + config.SEARCHAPI_API_KEY, + config.SEARCHAPI_ENGINE, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No SEARCHAPI_API_KEY found in environment variables') elif engine == 'serpapi': - if request.app.state.config.SERPAPI_API_KEY: + if config.SERPAPI_API_KEY: return await asyncio.to_thread( search_serpapi, - request.app.state.config.SERPAPI_API_KEY, - request.app.state.config.SERPAPI_ENGINE, + config.SERPAPI_API_KEY, + config.SERPAPI_ENGINE, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No SERPAPI_API_KEY found in environment variables') elif engine == 'jina': return await asyncio.to_thread( search_jina, - request.app.state.config.JINA_API_KEY, + config.JINA_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.JINA_API_BASE_URL, + config.WEB_SEARCH_RESULT_COUNT, + config.JINA_API_BASE_URL, ) elif engine == 'bing': return await asyncio.to_thread( search_bing, - request.app.state.config.BING_SEARCH_V7_SUBSCRIPTION_KEY, - request.app.state.config.BING_SEARCH_V7_ENDPOINT, + config.BING_SEARCH_V7_SUBSCRIPTION_KEY, + config.BING_SEARCH_V7_ENDPOINT, str(DEFAULT_LOCALE), query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) elif engine == 'azure': - if ( - request.app.state.config.AZURE_AI_SEARCH_API_KEY - and request.app.state.config.AZURE_AI_SEARCH_ENDPOINT - and request.app.state.config.AZURE_AI_SEARCH_INDEX_NAME - ): + if config.AZURE_AI_SEARCH_API_KEY and config.AZURE_AI_SEARCH_ENDPOINT and config.AZURE_AI_SEARCH_INDEX_NAME: return await asyncio.to_thread( search_azure, - request.app.state.config.AZURE_AI_SEARCH_API_KEY, - request.app.state.config.AZURE_AI_SEARCH_ENDPOINT, - request.app.state.config.AZURE_AI_SEARCH_INDEX_NAME, + config.AZURE_AI_SEARCH_API_KEY, + config.AZURE_AI_SEARCH_ENDPOINT, + config.AZURE_AI_SEARCH_INDEX_NAME, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception( @@ -2136,74 +2423,88 @@ async def search_web(request: Request, engine: str, query: str, user=None) -> li elif engine == 'perplexity': return await asyncio.to_thread( search_perplexity, - request.app.state.config.PERPLEXITY_API_KEY, + config.PERPLEXITY_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - model=request.app.state.config.PERPLEXITY_MODEL, - search_context_usage=request.app.state.config.PERPLEXITY_SEARCH_CONTEXT_USAGE, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + model=config.PERPLEXITY_MODEL, + search_context_usage=config.PERPLEXITY_SEARCH_CONTEXT_USAGE, ) + elif engine == 'microsoft_web_iq': + if config.MICROSOFT_WEB_IQ_API_KEY: + return await asyncio.to_thread( + search_microsoft_web_iq, + config.MICROSOFT_WEB_IQ_API_BASE_URL, + config.MICROSOFT_WEB_IQ_API_KEY, + query, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.MICROSOFT_WEB_IQ_LANGUAGE, + user, + ) + else: + raise Exception('No MICROSOFT_WEB_IQ_API_KEY found in environment variables') elif engine == 'sougou': - if request.app.state.config.SOUGOU_API_SID and request.app.state.config.SOUGOU_API_SK: + if config.SOUGOU_API_SID and config.SOUGOU_API_SK: return await asyncio.to_thread( search_sougou, - request.app.state.config.SOUGOU_API_SID, - request.app.state.config.SOUGOU_API_SK, + config.SOUGOU_API_SID, + config.SOUGOU_API_SK, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) else: raise Exception('No SOUGOU_API_SID or SOUGOU_API_SK found in environment variables') elif engine == 'firecrawl': return await asyncio.to_thread( search_firecrawl, - request.app.state.config.FIRECRAWL_API_BASE_URL, - request.app.state.config.FIRECRAWL_API_KEY, + config.FIRECRAWL_API_BASE_URL, + config.FIRECRAWL_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) elif engine == 'external': return await asyncio.to_thread( search_external, request, - request.app.state.config.EXTERNAL_WEB_SEARCH_URL, - request.app.state.config.EXTERNAL_WEB_SEARCH_API_KEY, + config.EXTERNAL_WEB_SEARCH_URL, + config.EXTERNAL_WEB_SEARCH_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, user=user, ) elif engine == 'yandex': return await asyncio.to_thread( search_yandex, request, - request.app.state.config.YANDEX_WEB_SEARCH_URL, - request.app.state.config.YANDEX_WEB_SEARCH_API_KEY, - request.app.state.config.YANDEX_WEB_SEARCH_CONFIG, + config.YANDEX_WEB_SEARCH_URL, + config.YANDEX_WEB_SEARCH_API_KEY, + config.YANDEX_WEB_SEARCH_CONFIG, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, user=user, ) elif engine == 'youcom': return await asyncio.to_thread( search_youcom, - request.app.state.config.YOUCOM_API_KEY, + config.YOUCOM_API_KEY, query, - request.app.state.config.WEB_SEARCH_RESULT_COUNT, - request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, + config.WEB_SEARCH_RESULT_COUNT, + config.WEB_SEARCH_DOMAIN_FILTER_LIST, ) elif engine == 'linkup': - if request.app.state.config.LINKUP_API_KEY: + if config.LINKUP_API_KEY: return await asyncio.to_thread( search_linkup, - api_key=request.app.state.config.LINKUP_API_KEY, + api_key=config.LINKUP_API_KEY, query=query, - count=request.app.state.config.WEB_SEARCH_RESULT_COUNT, - filter_list=request.app.state.config.WEB_SEARCH_DOMAIN_FILTER_LIST, - params=request.app.state.config.LINKUP_SEARCH_PARAMS, + count=config.WEB_SEARCH_RESULT_COUNT, + filter_list=config.WEB_SEARCH_DOMAIN_FILTER_LIST, + params=config.LINKUP_SEARCH_PARAMS, ) else: raise Exception('No LINKUP_API_KEY found in environment variables') @@ -2213,15 +2514,14 @@ async def search_web(request: Request, engine: str, query: str, user=None) -> li @router.post('/process/web/search') async def process_web_search(request: Request, form_data: SearchForm, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_WEB_SEARCH: + config = await get_retrieval_config() + if not config.ENABLE_WEB_SEARCH: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - if user.role != 'admin' and not await has_permission( - user.id, 'features.web_search', request.app.state.config.USER_PERMISSIONS - ): + if user.role != 'admin' and not await has_permission(user.id, 'features.web_search', config.USER_PERMISSIONS): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, @@ -2231,12 +2531,12 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen result_items = [] try: - logging.debug(f'trying to web search with {request.app.state.config.WEB_SEARCH_ENGINE, form_data.queries}') + logging.debug(f'trying to web search with {config.WEB_SEARCH_ENGINE, form_data.queries}') # Use semaphore to limit concurrent requests based on WEB_SEARCH_CONCURRENT_REQUESTS # 0 or None = unlimited (previous behavior), positive number = limited concurrency # Set to 1 for sequential execution (rate-limited APIs like Brave free tier) - concurrent_limit = request.app.state.config.WEB_SEARCH_CONCURRENT_REQUESTS + concurrent_limit = config.WEB_SEARCH_CONCURRENT_REQUESTS if concurrent_limit: # Limited concurrency with semaphore @@ -2246,7 +2546,7 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen async with semaphore: return await search_web( request, - request.app.state.config.WEB_SEARCH_ENGINE, + config.WEB_SEARCH_ENGINE, query, user, ) @@ -2257,7 +2557,7 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen search_tasks = [ search_web( request, - request.app.state.config.WEB_SEARCH_ENGINE, + config.WEB_SEARCH_ENGINE, query, user, ) @@ -2287,7 +2587,7 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen ) try: - if request.app.state.config.BYPASS_WEB_SEARCH_WEB_LOADER: + if config.BYPASS_WEB_SEARCH_WEB_LOADER: search_results = [item for result in search_results for item in result if result] docs = [ @@ -2306,9 +2606,9 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen else: loader = get_web_loader( urls, - verify_ssl=request.app.state.config.ENABLE_WEB_LOADER_SSL_VERIFICATION, - requests_per_second=request.app.state.config.WEB_LOADER_CONCURRENT_REQUESTS, - trust_env=request.app.state.config.WEB_SEARCH_TRUST_ENV, + verify_ssl=config.ENABLE_WEB_LOADER_SSL_VERIFICATION, + requests_per_second=config.WEB_LOADER_CONCURRENT_REQUESTS, + trust_env=config.WEB_SEARCH_TRUST_ENV, ) docs = await loader.aload() @@ -2319,7 +2619,7 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen dict(item) for item in result_items if item.link in urls ] # only keep the search results that have been loaded - if request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL: + if config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL: return { 'status': True, 'collection_name': None, @@ -2344,6 +2644,7 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen request, docs, collection_name, + config, overwrite=True, user=user, ) @@ -2357,9 +2658,14 @@ async def process_web_search(request: Request, form_data: SearchForm, user=Depen 'filenames': urls, 'loaded_count': len(docs), } + except HTTPException: + raise except Exception as e: log.exception('Web search content loading failed') - raise HTTPException(status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT(e)) + raise HTTPException( + status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e, ERROR_MESSAGES.WEB_SEARCH_ERROR()), + ) async def _validate_collection_access(collection_names: list[str], user, access_type: str = 'read') -> None: @@ -2385,6 +2691,7 @@ class QueryDocForm(BaseModel): k_reranker: int | None = None r: float | None = None hybrid: bool | None = None + hybrid_bm25_weight: float | None = None @router.post('/query/doc') @@ -2393,35 +2700,31 @@ async def query_doc_handler( form_data: QueryDocForm, user=Depends(get_verified_user), ): + config = await get_retrieval_config() await _validate_collection_access([form_data.collection_name], user) try: - if request.app.state.config.ENABLE_RAG_HYBRID_SEARCH and (form_data.hybrid is None or form_data.hybrid): - collection_results = {} - collection_results[form_data.collection_name] = await ASYNC_VECTOR_DB_CLIENT.get( - collection_name=form_data.collection_name - ) + if config.ENABLE_RAG_HYBRID_SEARCH and (form_data.hybrid is None or form_data.hybrid): return await query_doc_with_hybrid_search( collection_name=form_data.collection_name, - collection_result=collection_results[form_data.collection_name], + collection_result=None, query=form_data.query, embedding_function=lambda query, prefix: request.app.state.EMBEDDING_FUNCTION( query, prefix=prefix, user=user ), - k=form_data.k if form_data.k else request.app.state.config.TOP_K, + k=form_data.k if form_data.k else config.TOP_K, reranking_function=( (lambda query, documents: request.app.state.RERANKING_FUNCTION(query, documents, user=user)) if request.app.state.RERANKING_FUNCTION else None ), - k_reranker=form_data.k_reranker or request.app.state.config.TOP_K_RERANKER, - r=(form_data.r if form_data.r else request.app.state.config.RELEVANCE_THRESHOLD), + k_reranker=form_data.k_reranker or config.TOP_K_RERANKER, + r=(form_data.r if form_data.r else config.RELEVANCE_THRESHOLD), hybrid_bm25_weight=( form_data.hybrid_bm25_weight - if form_data.hybrid_bm25_weight - else request.app.state.config.HYBRID_BM25_WEIGHT + if form_data.hybrid_bm25_weight is not None + else config.HYBRID_BM25_WEIGHT ), - user=user, ) else: query_embedding = await request.app.state.EMBEDDING_FUNCTION( @@ -2433,14 +2736,16 @@ async def query_doc_handler( query_doc, collection_name=form_data.collection_name, query_embedding=query_embedding, - k=form_data.k if form_data.k else request.app.state.config.TOP_K, + k=form_data.k if form_data.k else config.TOP_K, user=user, ) + except HTTPException: + raise except Exception as e: log.exception(e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error querying knowledge base'), ) @@ -2461,33 +2766,34 @@ async def query_collection_handler( form_data: QueryCollectionsForm, user=Depends(get_verified_user), ): + config = await get_retrieval_config() await _validate_collection_access(form_data.collection_names, user) try: - if request.app.state.config.ENABLE_RAG_HYBRID_SEARCH and (form_data.hybrid is None or form_data.hybrid): + if config.ENABLE_RAG_HYBRID_SEARCH and (form_data.hybrid is None or form_data.hybrid): return await query_collection_with_hybrid_search( collection_names=form_data.collection_names, queries=[form_data.query], embedding_function=lambda query, prefix: request.app.state.EMBEDDING_FUNCTION( query, prefix=prefix, user=user ), - k=form_data.k if form_data.k else request.app.state.config.TOP_K, + k=form_data.k if form_data.k else config.TOP_K, reranking_function=( (lambda query, documents: request.app.state.RERANKING_FUNCTION(query, documents, user=user)) if request.app.state.RERANKING_FUNCTION else None ), - k_reranker=form_data.k_reranker or request.app.state.config.TOP_K_RERANKER, - r=(form_data.r if form_data.r else request.app.state.config.RELEVANCE_THRESHOLD), + k_reranker=form_data.k_reranker or config.TOP_K_RERANKER, + r=(form_data.r if form_data.r else config.RELEVANCE_THRESHOLD), hybrid_bm25_weight=( form_data.hybrid_bm25_weight - if form_data.hybrid_bm25_weight - else request.app.state.config.HYBRID_BM25_WEIGHT + if form_data.hybrid_bm25_weight is not None + else config.HYBRID_BM25_WEIGHT ), enable_enriched_texts=( form_data.enable_enriched_texts if form_data.enable_enriched_texts is not None - else request.app.state.config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS + else config.ENABLE_RAG_HYBRID_SEARCH_ENRICHED_TEXTS ), ) else: @@ -2498,14 +2804,16 @@ async def query_collection_handler( embedding_function=lambda query, prefix: request.app.state.EMBEDDING_FUNCTION( query, prefix=prefix, user=user ), - k=form_data.k if form_data.k else request.app.state.config.TOP_K, + k=form_data.k if form_data.k else config.TOP_K, ) + except HTTPException: + raise except Exception as e: log.exception(e) raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error querying knowledge base'), ) @@ -2523,6 +2831,7 @@ class DeleteForm(BaseModel): @router.post('/delete') async def delete_entries_from_collection( + request: Request, form_data: DeleteForm, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session), @@ -2561,6 +2870,13 @@ async def delete_entries_from_collection( collection_name=form_data.collection_name, filter={'hash': hash}, ) + await publish_event( + request, + EVENTS.RETRIEVAL_COLLECTION_DELETED, + actor=user, + subject_id=form_data.collection_name, + data={'file_id': form_data.file_id}, + ) return {'status': True} else: return {'status': False} @@ -2574,13 +2890,23 @@ async def delete_entries_from_collection( @router.post('/reset/db') -async def reset_vector_db(user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def reset_vector_db( + request: Request, + user=Depends(get_admin_user), + db: AsyncSession = Depends(get_async_session), +): await ASYNC_VECTOR_DB_CLIENT.reset() await Knowledges.delete_all_knowledge(db=db) + await publish_event( + request, + EVENTS.RETRIEVAL_VECTOR_DB_RESET, + actor=user, + subject_id='default', + ) @router.post('/reset/uploads') -async def reset_upload_dir(user=Depends(get_admin_user)) -> bool: +async def reset_upload_dir(request: Request, user=Depends(get_admin_user)) -> bool: folder = f'{UPLOAD_DIR}' try: # Check if the directory exists @@ -2599,6 +2925,13 @@ async def reset_upload_dir(user=Depends(get_admin_user)) -> bool: log.warning(f'The directory {folder} does not exist') except Exception as e: log.exception(f'Failed to process the directory {folder}. Reason: {e}') + await publish_event( + request, + EVENTS.RETRIEVAL_UPLOADS_RESET, + actor=user, + subject_id='all', + subject_type='file.uploads', + ) return True @@ -2641,6 +2974,7 @@ async def process_files_batch( embedding (Files.update_file_by_id) manage their own short-lived sessions. """ + config = await get_retrieval_config() collection_name = form_data.collection_name if collection_name: @@ -2712,6 +3046,7 @@ async def process_files_batch( request, all_docs, collection_name, + config, add=True, user=user, ) @@ -2727,4 +3062,16 @@ async def process_files_batch( file_result.status = 'failed' file_errors.append(BatchProcessFilesResult(file_id=file_result.file_id, status='failed', error=str(e))) - return BatchProcessFilesResponse(results=file_results, errors=file_errors) + response = BatchProcessFilesResponse(results=file_results, errors=file_errors) + await publish_event( + request, + EVENTS.RETRIEVAL_CONTENT_PROCESSED, + actor=user, + subject_id=collection_name, + subject_type='retrieval.collection', + data={ + 'count': len([item for item in file_results if item.status == 'completed']), + 'errors': len(file_errors), + }, + ) + return response diff --git a/backend/open_webui/routers/scim.py b/backend/open_webui/routers/scim.py index 9292523adc..42d24a4a53 100644 --- a/backend/open_webui/routers/scim.py +++ b/backend/open_webui/routers/scim.py @@ -16,6 +16,7 @@ from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request, s from fastapi.responses import JSONResponse from open_webui.config import OAUTH_PROVIDERS from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import SCIM_AUTH_PROVIDER from open_webui.internal.db import get_async_session from open_webui.models.groups import GroupModel, Groups @@ -259,10 +260,6 @@ def get_scim_auth(request: Request, authorization: Optional[str] = Header(None)) enable_scim = getattr(request.app.state, 'ENABLE_SCIM', False) log.info(f'SCIM auth check - raw ENABLE_SCIM: {enable_scim}, type: {type(enable_scim)}') - # Handle both ConfigVar and direct value - if hasattr(enable_scim, 'value'): - enable_scim = enable_scim.value - if not enable_scim: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, @@ -271,9 +268,6 @@ def get_scim_auth(request: Request, authorization: Optional[str] = Header(None)) # Verify the SCIM token scim_token = getattr(request.app.state, 'SCIM_TOKEN', None) - # Handle both ConfigVar and direct value - if hasattr(scim_token, 'value'): - scim_token = scim_token.value log.debug(f'SCIM token configured: {bool(scim_token)}') if not scim_token or not hmac.compare_digest(token, scim_token): raise HTTPException( @@ -636,6 +630,18 @@ async def create_user( await Users.update_user_scim_by_id(user_id, provider, user_data.externalId, db=db) new_user = await Users.get_user_by_id(user_id, db=db) + await publish_event( + request, + EVENTS.USER_CREATED, + subject_id=new_user.id, + source='scim', + data={ + 'email': new_user.email, + 'role': new_user.role, + 'external_id': user_data.externalId, + }, + ) + return await user_to_scim(new_user, request, db=db) @@ -672,7 +678,10 @@ async def update_user( if user_data.emails and len(user_data.emails) > 0: update_data['email'] = user_data.emails[0].value - if user_data.active is not None: + # Do not let SCIM's active flag demote an existing admin: a routine IdP sync or misconfiguration + # must not silently strip a locally-provisioned admin's role and lock the instance out. Admin + # role changes go through the dedicated admin endpoints, not SCIM provisioning. + if user_data.active is not None and user.role != 'admin': update_data['role'] = 'user' if user_data.active else 'pending' if user_data.photos and len(user_data.photos) > 0: @@ -691,6 +700,16 @@ async def update_user( await Users.update_user_scim_by_id(user_id, provider, user_data.externalId, db=db) updated_user = await Users.get_user_by_id(user_id, db=db) + await publish_event( + request, + EVENTS.USER_UPDATED, + subject_id=user_id, + source='scim', + data={ + 'updated_fields': list(update_data.keys()) + (['externalId'] if user_data.externalId else []), + }, + ) + return await user_to_scim(updated_user, request, db=db) @@ -719,7 +738,9 @@ async def patch_user( if op == 'replace': if path == 'active': - update_data['role'] = 'user' if value else 'pending' + # Same guard as update_user: never demote an existing admin via SCIM. + if user.role != 'admin': + update_data['role'] = 'user' if value else 'pending' elif path == 'userName': update_data['email'] = value elif path == 'displayName': @@ -743,6 +764,14 @@ async def patch_user( else: updated_user = user + await publish_event( + request, + EVENTS.USER_UPDATED, + subject_id=user_id, + source='scim', + data={'updated_fields': list(update_data.keys())}, + ) + return await user_to_scim(updated_user, request, db=db) @@ -768,6 +797,14 @@ async def delete_user( detail='Failed to delete user', ) + await publish_event( + request, + EVENTS.USER_DELETED, + subject_id=user_id, + source='scim', + data={'email': user.email}, + ) + return None @@ -885,6 +922,22 @@ async def create_group( new_group = await Groups.get_group_by_id(new_group.id, db=db) + await publish_event( + request, + EVENTS.GROUP_CREATED, + subject_id=new_group.id, + source='scim', + data={'name': new_group.name, 'member_ids': member_ids, 'member_count': len(member_ids)}, + ) + if member_ids: + await publish_event( + request, + EVENTS.GROUP_MEMBER_ADDED, + subject_id=new_group.id, + source='scim', + data={'member_ids': member_ids, 'count': len(member_ids)}, + ) + return await group_to_scim(new_group, request, db=db) @@ -913,9 +966,15 @@ async def update_group( ) # Handle members if provided + added_member_ids = [] + removed_member_ids = [] if group_data.members is not None: + old_member_ids = set(await Groups.get_group_user_ids_by_id(group_id, db) or []) member_ids = [member.value for member in group_data.members] await Groups.set_group_user_ids_by_id(group_id, member_ids, db=db) + new_member_ids = set(member_ids) + added_member_ids = sorted(new_member_ids - old_member_ids) + removed_member_ids = sorted(old_member_ids - new_member_ids) # Update group updated_group = await Groups.update_group_by_id(group_id, update_form, db=db) @@ -925,6 +984,30 @@ async def update_group( detail='Failed to update group', ) + await publish_event( + request, + EVENTS.GROUP_UPDATED, + subject_id=group_id, + source='scim', + data={'updated_fields': ['name', 'members'] if group_data.members is not None else ['name']}, + ) + if added_member_ids: + await publish_event( + request, + EVENTS.GROUP_MEMBER_ADDED, + subject_id=group_id, + source='scim', + data={'member_ids': added_member_ids, 'count': len(added_member_ids)}, + ) + if removed_member_ids: + await publish_event( + request, + EVENTS.GROUP_MEMBER_REMOVED, + subject_id=group_id, + source='scim', + data={'member_ids': removed_member_ids, 'count': len(removed_member_ids)}, + ) + return await group_to_scim(updated_group, request, db=db) @@ -950,6 +1033,8 @@ async def patch_group( name=group.name, description=group.description, ) + added_member_ids = [] + removed_member_ids = [] for operation in patch_data.Operations: op = operation.op.lower() @@ -961,7 +1046,12 @@ async def patch_group( update_form.name = value elif path == 'members': # Replace all members - await Groups.set_group_user_ids_by_id(group_id, [member['value'] for member in value], db=db) + old_member_ids = set(await Groups.get_group_user_ids_by_id(group_id, db) or []) + new_member_ids = [member['value'] for member in value] + await Groups.set_group_user_ids_by_id(group_id, new_member_ids, db=db) + new_member_ids_set = set(new_member_ids) + added_member_ids.extend(sorted(new_member_ids_set - old_member_ids)) + removed_member_ids.extend(sorted(old_member_ids - new_member_ids_set)) elif op == 'add': if path == 'members': @@ -970,11 +1060,13 @@ async def patch_group( for member in value: if isinstance(member, dict) and 'value' in member: await Groups.add_users_to_group(group_id, [member['value']], db=db) + added_member_ids.append(member['value']) elif op == 'remove': if path and path.startswith('members[value eq'): # Remove specific member member_id = path.split('"')[1] await Groups.remove_users_from_group(group_id, [member_id], db=db) + removed_member_ids.append(member_id) # Update group updated_group = await Groups.update_group_by_id(group_id, update_form, db=db) @@ -984,6 +1076,30 @@ async def patch_group( detail='Failed to update group', ) + await publish_event( + request, + EVENTS.GROUP_UPDATED, + subject_id=group_id, + source='scim', + data={'operation_count': len(patch_data.Operations)}, + ) + if added_member_ids: + await publish_event( + request, + EVENTS.GROUP_MEMBER_ADDED, + subject_id=group_id, + source='scim', + data={'member_ids': sorted(set(added_member_ids)), 'count': len(set(added_member_ids))}, + ) + if removed_member_ids: + await publish_event( + request, + EVENTS.GROUP_MEMBER_REMOVED, + subject_id=group_id, + source='scim', + data={'member_ids': sorted(set(removed_member_ids)), 'count': len(set(removed_member_ids))}, + ) + return await group_to_scim(updated_group, request, db=db) @@ -1009,4 +1125,12 @@ async def delete_group( detail='Failed to delete group', ) + await publish_event( + request, + EVENTS.GROUP_DELETED, + subject_id=group_id, + source='scim', + data={'name': group.name}, + ) + return None diff --git a/backend/open_webui/routers/skills.py b/backend/open_webui/routers/skills.py index 55aa351ff0..9af2d81573 100644 --- a/backend/open_webui/routers/skills.py +++ b/backend/open_webui/routers/skills.py @@ -4,8 +4,10 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.skills import ( SkillAccessListResponse, @@ -129,8 +131,8 @@ async def export_skills( ): if user.role != 'admin' and not await has_permission( user.id, - 'workspace.skills', - request.app.state.config.USER_PERMISSIONS, + 'workspace.skills_export', + await Config.get('user.permissions'), db=db, ): raise HTTPException( @@ -156,8 +158,9 @@ async def create_new_skill( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if user.role != 'admin' and not await has_permission( - user.id, 'workspace.skills', request.app.state.config.USER_PERMISSIONS, db=db + if user.role != 'admin' and not ( + await has_permission(user.id, 'workspace.skills', await Config.get('user.permissions'), db=db) + or await has_permission(user.id, 'workspace.skills_import', await Config.get('user.permissions'), db=db) ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -179,7 +182,7 @@ async def create_new_skill( # grants in the create payload, bypassing the sharing.public_skills gate # that the dedicated /access/update endpoint already enforces. form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -189,17 +192,26 @@ async def create_new_skill( try: skill = await Skills.insert_new_skill(user.id, form_data, db=db) if skill: + await publish_event( + request, + EVENTS.SKILL_CREATED, + actor=user, + subject_id=skill.id, + data={'name': skill.name}, + ) return skill else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error creating skill'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Failed to create skill: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error creating skill'), ) @@ -292,7 +304,7 @@ async def update_skill_by_id( # they may set, so a non-admin owner cannot make their own skill publicly # readable/writable without sharing.public_skills permission. form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -307,16 +319,25 @@ async def update_skill_by_id( skill = await Skills.update_skill_by_id(id, updated, db=db) if skill: + await publish_event( + request, + EVENTS.SKILL_UPDATED, + actor=user, + subject_id=skill.id, + data={'name': skill.name}, + ) return skill else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error updating skill'), ) + except HTTPException: + raise except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating skill'), ) @@ -361,7 +382,7 @@ async def update_skill_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -370,7 +391,15 @@ async def update_skill_access_by_id( await AccessGrants.set_access_grants('skill', id, form_data.access_grants, db=db) - return await Skills.get_skill_by_id(id, db=db) + skill = await Skills.get_skill_by_id(id, db=db) + await publish_event( + request, + EVENTS.SKILL_UPDATED, + actor=user, + subject_id=id, + data={'access_updated': True, 'name': skill.name if skill else None}, + ) + return skill ############################ @@ -379,7 +408,12 @@ async def update_skill_access_by_id( @router.post('/id/{id}/toggle', response_model=Optional[SkillModel]) -async def toggle_skill_by_id(id: str, user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session)): +async def toggle_skill_by_id( + request: Request, + id: str, + user=Depends(get_verified_user), + db: AsyncSession = Depends(get_async_session), +): skill = await Skills.get_skill_by_id(id, db=db) if skill: if ( @@ -396,6 +430,13 @@ async def toggle_skill_by_id(id: str, user=Depends(get_verified_user), db: Async skill = await Skills.toggle_skill_by_id(id, db=db) if skill: + await publish_event( + request, + EVENTS.SKILL_ENABLED if skill.is_active else EVENTS.SKILL_DISABLED, + actor=user, + subject_id=skill.id, + data={'name': skill.name}, + ) return skill else: raise HTTPException( @@ -450,4 +491,12 @@ async def delete_skill_by_id( ) result = await Skills.delete_skill_by_id(id, db=db) + if result: + await publish_event( + request, + EVENTS.SKILL_DELETED, + actor=user, + subject_id=id, + data={'name': skill.name}, + ) return result diff --git a/backend/open_webui/routers/tasks.py b/backend/open_webui/routers/tasks.py index 0e88f8594a..7cc7449b4b 100644 --- a/backend/open_webui/routers/tasks.py +++ b/backend/open_webui/routers/tasks.py @@ -16,6 +16,7 @@ from open_webui.config import ( DEFAULT_VOICE_MODE_PROMPT_TEMPLATE, ) from open_webui.constants import ERROR_MESSAGES, TASKS +from open_webui.models.config import Config from open_webui.routers.pipelines import process_pipeline_inlet_filter from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.chat import generate_chat_completion @@ -36,6 +37,36 @@ log = logging.getLogger(__name__) router = APIRouter() +TASK_CONFIG_KEYS = { + 'TASK_MODEL': 'task.model.default', + 'TASK_MODEL_EXTERNAL': 'task.model.external', + 'TITLE_GENERATION_PROMPT_TEMPLATE': 'task.title.prompt_template', + 'IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE': 'task.image.prompt_template', + 'ENABLE_AUTOCOMPLETE_GENERATION': 'task.autocomplete.enable', + 'AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH': 'task.autocomplete.input_max_length', + 'AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE': 'task.autocomplete.prompt_template', + 'TAGS_GENERATION_PROMPT_TEMPLATE': 'task.tags.prompt_template', + 'FOLLOW_UP_GENERATION_PROMPT_TEMPLATE': 'task.follow_up.prompt_template', + 'ENABLE_FOLLOW_UP_GENERATION': 'task.follow_up.enable', + 'ENABLE_TAGS_GENERATION': 'task.tags.enable', + 'ENABLE_TITLE_GENERATION': 'task.title.enable', + 'ENABLE_SEARCH_QUERY_GENERATION': 'task.query.search.enable', + 'ENABLE_RETRIEVAL_QUERY_GENERATION': 'task.query.retrieval.enable', + 'QUERY_GENERATION_PROMPT_TEMPLATE': 'task.query.prompt_template', + 'TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE': 'task.tools.prompt_template', + 'ENABLE_VOICE_MODE_PROMPT': 'task.voice.prompt.enable', + 'VOICE_MODE_PROMPT_TEMPLATE': 'task.voice.prompt_template', +} + + +async def get_config_values(key_map: dict[str, str]) -> dict: + values = await Config.get_many(*key_map.values()) + return {field: values[storage_key] for field, storage_key in key_map.items() if storage_key in values} + + +def config_updates(data: dict, key_map: dict[str, str]) -> dict: + return {key_map[field]: value for field, value in data.items() if field in key_map} + ################################## # @@ -59,25 +90,7 @@ async def check_active_chats(request: Request, form_data: ActiveChatsForm, user= @router.get('/config') async def get_task_config(request: Request, user=Depends(get_verified_user)): - return { - 'TASK_MODEL': request.app.state.config.TASK_MODEL, - 'TASK_MODEL_EXTERNAL': request.app.state.config.TASK_MODEL_EXTERNAL, - 'TITLE_GENERATION_PROMPT_TEMPLATE': request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE, - 'IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE': request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE, - 'ENABLE_AUTOCOMPLETE_GENERATION': request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION, - 'AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH': request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH, - 'TAGS_GENERATION_PROMPT_TEMPLATE': request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE, - 'FOLLOW_UP_GENERATION_PROMPT_TEMPLATE': request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE, - 'ENABLE_FOLLOW_UP_GENERATION': request.app.state.config.ENABLE_FOLLOW_UP_GENERATION, - 'ENABLE_TAGS_GENERATION': request.app.state.config.ENABLE_TAGS_GENERATION, - 'ENABLE_TITLE_GENERATION': request.app.state.config.ENABLE_TITLE_GENERATION, - 'ENABLE_SEARCH_QUERY_GENERATION': request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION, - 'ENABLE_RETRIEVAL_QUERY_GENERATION': request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION, - 'QUERY_GENERATION_PROMPT_TEMPLATE': request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE, - 'TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE': request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, - 'ENABLE_VOICE_MODE_PROMPT': request.app.state.config.ENABLE_VOICE_MODE_PROMPT, - 'VOICE_MODE_PROMPT_TEMPLATE': request.app.state.config.VOICE_MODE_PROMPT_TEMPLATE, - } + return await get_config_values(TASK_CONFIG_KEYS) class TaskConfigForm(BaseModel): @@ -88,6 +101,7 @@ class TaskConfigForm(BaseModel): IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE: str ENABLE_AUTOCOMPLETE_GENERATION: bool AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH: int + AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE: str TAGS_GENERATION_PROMPT_TEMPLATE: str FOLLOW_UP_GENERATION_PROMPT_TEMPLATE: str ENABLE_FOLLOW_UP_GENERATION: bool @@ -102,56 +116,13 @@ class TaskConfigForm(BaseModel): @router.post('/config/update') async def update_task_config(request: Request, form_data: TaskConfigForm, user=Depends(get_admin_user)): - request.app.state.config.TASK_MODEL = form_data.TASK_MODEL - request.app.state.config.TASK_MODEL_EXTERNAL = form_data.TASK_MODEL_EXTERNAL - request.app.state.config.ENABLE_TITLE_GENERATION = form_data.ENABLE_TITLE_GENERATION - request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE = form_data.TITLE_GENERATION_PROMPT_TEMPLATE - - request.app.state.config.ENABLE_FOLLOW_UP_GENERATION = form_data.ENABLE_FOLLOW_UP_GENERATION - request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE = form_data.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE - - request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE = form_data.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE - - request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION = form_data.ENABLE_AUTOCOMPLETE_GENERATION - request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH = ( - form_data.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH - ) - - request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE = form_data.TAGS_GENERATION_PROMPT_TEMPLATE - request.app.state.config.ENABLE_TAGS_GENERATION = form_data.ENABLE_TAGS_GENERATION - request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION = form_data.ENABLE_SEARCH_QUERY_GENERATION - request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION = form_data.ENABLE_RETRIEVAL_QUERY_GENERATION - - request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE = form_data.QUERY_GENERATION_PROMPT_TEMPLATE - request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE = form_data.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE - - request.app.state.config.ENABLE_VOICE_MODE_PROMPT = form_data.ENABLE_VOICE_MODE_PROMPT - request.app.state.config.VOICE_MODE_PROMPT_TEMPLATE = form_data.VOICE_MODE_PROMPT_TEMPLATE - - return { - 'TASK_MODEL': request.app.state.config.TASK_MODEL, - 'TASK_MODEL_EXTERNAL': request.app.state.config.TASK_MODEL_EXTERNAL, - 'ENABLE_TITLE_GENERATION': request.app.state.config.ENABLE_TITLE_GENERATION, - 'TITLE_GENERATION_PROMPT_TEMPLATE': request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE, - 'IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE': request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE, - 'ENABLE_AUTOCOMPLETE_GENERATION': request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION, - 'AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH': request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH, - 'TAGS_GENERATION_PROMPT_TEMPLATE': request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE, - 'ENABLE_TAGS_GENERATION': request.app.state.config.ENABLE_TAGS_GENERATION, - 'ENABLE_FOLLOW_UP_GENERATION': request.app.state.config.ENABLE_FOLLOW_UP_GENERATION, - 'FOLLOW_UP_GENERATION_PROMPT_TEMPLATE': request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE, - 'ENABLE_SEARCH_QUERY_GENERATION': request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION, - 'ENABLE_RETRIEVAL_QUERY_GENERATION': request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION, - 'QUERY_GENERATION_PROMPT_TEMPLATE': request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE, - 'TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE': request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, - 'ENABLE_VOICE_MODE_PROMPT': request.app.state.config.ENABLE_VOICE_MODE_PROMPT, - 'VOICE_MODE_PROMPT_TEMPLATE': request.app.state.config.VOICE_MODE_PROMPT_TEMPLATE, - } + await Config.upsert(config_updates(form_data.model_dump(), TASK_CONFIG_KEYS)) + return await get_config_values(TASK_CONFIG_KEYS) @router.post('/title/completions') async def generate_title(request: Request, form_data: dict, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_TITLE_GENERATION: + if not await Config.get('task.title.enable'): return JSONResponse( status_code=status.HTTP_200_OK, content={'detail': 'Title generation is disabled'}, @@ -181,15 +152,16 @@ async def generate_title(request: Request, form_data: dict, user=Depends(get_ver # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating chat title using model {task_model_id} for user {user.email} ') - if request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE != '': - template = request.app.state.config.TITLE_GENERATION_PROMPT_TEMPLATE + title_template = await Config.get('task.title.prompt_template') + if title_template != '': + template = title_template else: template = DEFAULT_TITLE_GENERATION_PROMPT_TEMPLATE @@ -234,7 +206,7 @@ async def generate_title(request: Request, form_data: dict, user=Depends(get_ver @router.post('/follow_up/completions') async def generate_follow_ups(request: Request, form_data: dict, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_FOLLOW_UP_GENERATION: + if not await Config.get('task.follow_up.enable'): return JSONResponse( status_code=status.HTTP_200_OK, content={'detail': 'Follow-up generation is disabled'}, @@ -259,15 +231,16 @@ async def generate_follow_ups(request: Request, form_data: dict, user=Depends(ge # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating chat title using model {task_model_id} for user {user.email} ') - if request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE != '': - template = request.app.state.config.FOLLOW_UP_GENERATION_PROMPT_TEMPLATE + follow_up_template = await Config.get('task.follow_up.prompt_template') + if follow_up_template != '': + template = follow_up_template else: template = DEFAULT_FOLLOW_UP_GENERATION_PROMPT_TEMPLATE @@ -303,7 +276,7 @@ async def generate_follow_ups(request: Request, form_data: dict, user=Depends(ge @router.post('/tags/completions') async def generate_chat_tags(request: Request, form_data: dict, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_TAGS_GENERATION: + if not await Config.get('task.tags.enable'): return JSONResponse( status_code=status.HTTP_200_OK, content={'detail': 'Tags generation is disabled'}, @@ -328,15 +301,16 @@ async def generate_chat_tags(request: Request, form_data: dict, user=Depends(get # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating chat tags using model {task_model_id} for user {user.email} ') - if request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE != '': - template = request.app.state.config.TAGS_GENERATION_PROMPT_TEMPLATE + tags_template = await Config.get('task.tags.prompt_template') + if tags_template != '': + template = tags_template else: template = DEFAULT_TAGS_GENERATION_PROMPT_TEMPLATE @@ -391,15 +365,16 @@ async def generate_image_prompt(request: Request, form_data: dict, user=Depends( # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating image prompt using model {task_model_id} for user {user.email} ') - if request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE != '': - template = request.app.state.config.IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE + image_prompt_template = await Config.get('task.image.prompt_template') + if image_prompt_template != '': + template = image_prompt_template else: template = DEFAULT_IMAGE_PROMPT_GENERATION_PROMPT_TEMPLATE @@ -437,13 +412,13 @@ async def generate_image_prompt(request: Request, form_data: dict, user=Depends( async def generate_queries(request: Request, form_data: dict, user=Depends(get_verified_user)): type = form_data.get('type') if type == 'web_search': - if not request.app.state.config.ENABLE_SEARCH_QUERY_GENERATION: + if not await Config.get('task.query.search.enable'): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FEATURE_DISABLED('Search query generation'), ) elif type == 'retrieval': - if not request.app.state.config.ENABLE_RETRIEVAL_QUERY_GENERATION: + if not await Config.get('task.query.retrieval.enable'): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FEATURE_DISABLED('Query generation'), @@ -472,15 +447,16 @@ async def generate_queries(request: Request, form_data: dict, user=Depends(get_v # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating {type} queries using model {task_model_id} for user {user.email}') - if (request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE).strip() != '': - template = request.app.state.config.QUERY_GENERATION_PROMPT_TEMPLATE + query_template = await Config.get('task.query.prompt_template') + if query_template.strip() != '': + template = query_template else: template = DEFAULT_QUERY_GENERATION_PROMPT_TEMPLATE @@ -515,7 +491,7 @@ async def generate_queries(request: Request, form_data: dict, user=Depends(get_v @router.post('/auto/completions') async def generate_autocompletion(request: Request, form_data: dict, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_AUTOCOMPLETE_GENERATION: + if not await Config.get('task.autocomplete.enable'): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.FEATURE_DISABLED('Autocompletion generation'), @@ -525,11 +501,12 @@ async def generate_autocompletion(request: Request, form_data: dict, user=Depend prompt = form_data.get('prompt') messages = form_data.get('messages') - if request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH > 0: - if len(prompt) > request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH: + autocomplete_input_max_length = await Config.get('task.autocomplete.input_max_length') + if autocomplete_input_max_length > 0: + if len(prompt) > autocomplete_input_max_length: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.INPUT_TOO_LONG(request.app.state.config.AUTOCOMPLETE_GENERATION_INPUT_MAX_LENGTH), + detail=ERROR_MESSAGES.INPUT_TOO_LONG(autocomplete_input_max_length), ) if getattr(request.state, 'direct', False) and hasattr(request.state, 'model'): @@ -551,15 +528,16 @@ async def generate_autocompletion(request: Request, form_data: dict, user=Depend # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) log.debug(f'generating autocompletion using model {task_model_id} for user {user.email}') - if (request.app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE).strip() != '': - template = request.app.state.config.AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE + autocomplete_template = await Config.get('task.autocomplete.prompt_template') + if autocomplete_template.strip() != '': + template = autocomplete_template else: template = DEFAULT_AUTOCOMPLETE_GENERATION_PROMPT_TEMPLATE @@ -614,8 +592,8 @@ async def generate_emoji(request: Request, form_data: dict, user=Depends(get_ver # If the user has a custom task model, use that model task_model_id = get_task_model_id( model_id, - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) diff --git a/backend/open_webui/routers/terminals.py b/backend/open_webui/routers/terminals.py index 6a942cf9b2..ce2efa7096 100644 --- a/backend/open_webui/routers/terminals.py +++ b/backend/open_webui/routers/terminals.py @@ -13,11 +13,14 @@ import aiohttp from fastapi import APIRouter, Depends, Request, Response, WebSocket from fastapi.responses import JSONResponse, StreamingResponse from open_webui.config import TERMINAL_PROXY_HEADERS +from open_webui.events import EVENTS, publish_event from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.users import Users from open_webui.utils.access_control import has_connection_access from open_webui.utils.auth import get_verified_user +from open_webui.utils.tools import bearer_auth_header, normalize_bearer_token from starlette.background import BackgroundTask log = logging.getLogger(__name__) @@ -43,6 +46,9 @@ def _sanitize_proxy_path(path: str) -> str | None: if once == decoded: break decoded = once + # Fail closed: still encoded after the cap means the upstream would decode further into traversal. + if unquote(decoded) != decoded: + return None had_trailing_slash = decoded.endswith('/') normalized = posixpath.normpath(decoded) # Remove any leading slashes that would reset the base @@ -59,7 +65,7 @@ def _sanitize_proxy_path(path: str) -> str | None: @router.get('/') async def list_terminal_servers(request: Request, user=Depends(get_verified_user)): """Return terminal servers the authenticated user has access to.""" - connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or [] + connections = await Config.get('terminal_server.connections', []) or [] user_group_ids = {group.id for group in await Groups.get_groups_by_member_id(user.id)} return [ @@ -84,7 +90,7 @@ async def proxy_terminal( user=Depends(get_verified_user), ): """Proxy a request to the admin terminal server identified by *server_id*.""" - connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or [] + connections = await Config.get('terminal_server.connections', []) or [] connection = next((c for c in connections if c.get('id') == server_id), None) if connection is None: @@ -121,15 +127,15 @@ async def proxy_terminal( auth_type = connection.get('auth_type', 'bearer') if auth_type == 'bearer': - headers['Authorization'] = f'Bearer {connection.get("key", "")}' + headers.update(bearer_auth_header(connection.get('key', ''))) elif auth_type == 'session': cookies = request.cookies - headers['Authorization'] = f'Bearer {request.state.token.credentials}' + headers.update(bearer_auth_header(request.state.token.credentials)) elif auth_type == 'system_oauth': cookies = request.cookies oauth_token = request.headers.get('x-oauth-access-token', '') if oauth_token: - headers['Authorization'] = f'Bearer {oauth_token}' + headers.update(bearer_auth_header(oauth_token)) # auth_type == "none": no Authorization header content_type = request.headers.get('content-type') @@ -206,7 +212,7 @@ async def _resolve_authenticated_connection(ws: WebSocket, server_id: str): import asyncio import json - from open_webui.utils.auth import decode_token + from open_webui.utils.auth import decode_token, is_valid_token # First-message authentication try: @@ -217,7 +223,7 @@ async def _resolve_authenticated_connection(ws: WebSocket, server_id: str): return None token = payload.get('token', '') data = decode_token(token) - if data is None or 'id' not in data: + if data is None or 'id' not in data or not await is_valid_token(data, getattr(ws.app.state, 'redis', None)): await ws.close(code=4001, reason='Invalid token') return None user = await Users.get_user_by_id(data['id']) @@ -232,7 +238,7 @@ async def _resolve_authenticated_connection(ws: WebSocket, server_id: str): return None # Resolve terminal server - connections = ws.app.state.config.TERMINAL_SERVER_CONNECTIONS or [] + connections = await Config.get('terminal_server.connections', []) or [] connection = next((c for c in connections if c.get('id') == server_id), None) if connection is None: @@ -282,13 +288,19 @@ async def ws_terminal( import urllib.parse + # Encode session_id as an opaque path segment so it cannot smuggle '?'/'#'/'&' (at any + # decode depth) and inject an attacker-chosen user_id ahead of the one appended below. + safe_session_id = urllib.parse.quote(session_id, safe='') + if policy_id: - upstream_url = f'{ws_base}/p/{policy_id}/api/terminals/{session_id}' + upstream_url = f'{ws_base}/p/{policy_id}/api/terminals/{safe_session_id}' else: - upstream_url = f'{ws_base}/api/terminals/{session_id}' + upstream_url = f'{ws_base}/api/terminals/{safe_session_id}' if upstream_params: upstream_url += f'?{urllib.parse.urlencode(upstream_params)}' + app = ws.scope.get('app') + opened = False session = aiohttp.ClientSession() try: async with session.ws_connect(upstream_url, ssl=AIOHTTP_CLIENT_SESSION_SSL) as upstream: @@ -298,9 +310,19 @@ async def ws_terminal( # First-message auth to upstream terminal server auth_type = connection.get('auth_type', 'bearer') if auth_type == 'bearer': - key = connection.get('key', '') + key = normalize_bearer_token(connection.get('key', '')) await upstream.send_str(_json.dumps({'type': 'auth', 'token': key})) + await publish_event( + app, + EVENTS.TERMINAL_SESSION_OPENED, + actor=user, + subject_id=session_id, + subject_type='terminal.session', + data={'server_id': server_id}, + ) + opened = True + async def _client_to_upstream(): """Forward client → upstream.""" try: @@ -349,6 +371,15 @@ async def ws_terminal( log.exception('Terminal WebSocket proxy error: %s', e) finally: await session.close() + if opened: + await publish_event( + app, + EVENTS.TERMINAL_SESSION_CLOSED, + actor=user, + subject_id=session_id, + subject_type='terminal.session', + data={'server_id': server_id}, + ) try: await ws.close() except Exception: diff --git a/backend/open_webui/routers/tools.py b/backend/open_webui/routers/tools.py index 963a727cde..c830753b5a 100644 --- a/backend/open_webui/routers/tools.py +++ b/backend/open_webui/routers/tools.py @@ -11,8 +11,10 @@ from fastapi import APIRouter, Depends, HTTPException, Request, status from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL, CACHE_DIR from open_webui.constants import ERROR_MESSAGES from open_webui.env import AIOHTTP_CLIENT_SESSION_SSL, AIOHTTP_CLIENT_TIMEOUT +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_session from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.tools import ( @@ -30,6 +32,7 @@ from open_webui.utils.access_control import ( ) from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.plugin import ( + get_tools_cache, get_tool_module_from_cache, load_tool_module_by_id, replace_imports, @@ -69,13 +72,17 @@ async def get_tools( tools = [] # Local Tools + tools_cache = get_tools_cache(request) for tool in await Tools.get_tools(defer_content=True, db=db): - tool_module = request.app.state.TOOLS.get(tool.id) if hasattr(request.app.state, 'TOOLS') else None + tool_module = tools_cache.get(tool.id) + has_user_valves = ( + hasattr(tool_module, 'UserValves') if tool_module else (tool.meta.has_user_valves if tool.meta else False) + ) tools.append( ToolUserResponse( **{ **tool.model_dump(), - 'has_user_valves': (hasattr(tool_module, 'UserValves') if tool_module else False), + 'has_user_valves': has_user_valves, } ) ) @@ -84,7 +91,7 @@ async def get_tools( server_access_grants = {} for server in await get_tool_servers(request): server_idx = server.get('idx', 0) - connections = request.app.state.config.TOOL_SERVER_CONNECTIONS + connections = await Config.get('tool_server.connections', []) if server_idx >= len(connections): log.warning( f'Tool server index {server_idx} out of range ' @@ -113,13 +120,14 @@ async def get_tools( ) # MCP Tool Servers - for server in request.app.state.config.TOOL_SERVER_CONNECTIONS: - if server.get('type', 'openapi') == 'mcp' and server.get('config', {}).get('enable'): - server_id = server.get('info', {}).get('id') + for server in await Config.get('tool_server.connections', []): + if server.get('type', 'openapi') == 'mcp' and (server.get('config') or {}).get('enable'): + info = server.get('info') or {} + server_id = info.get('id') auth_type = server.get('auth_type', 'none') session_token = None - if auth_type in ('oauth_2.1', 'oauth_2.1_static'): + if auth_type in ('oauth_2.1', 'oauth_2.1_static') and server_id: splits = server_id.split(':') server_id = splits[-1] if len(splits) > 1 else server_id @@ -127,9 +135,9 @@ async def get_tools( user.id, f'mcp:{server_id}' ) - server_config = server.get('config', {}) + server_config = server.get('config') or {} - tool_id = f'server:mcp:{server.get("info", {}).get("id")}' + tool_id = f'server:mcp:{info.get("id")}' server_access_grants[tool_id] = server_config.get('access_grants', []) tools.append( @@ -137,9 +145,9 @@ async def get_tools( **{ 'id': tool_id, 'user_id': tool_id, - 'name': server.get('info', {}).get('name', 'MCP Tool Server'), + 'name': info.get('name', 'MCP Tool Server'), 'meta': { - 'description': server.get('info', {}).get('description', ''), + 'description': info.get('description', ''), }, 'updated_at': int(time.time()), 'created_at': int(time.time()), @@ -285,8 +293,13 @@ async def load_tool_from_url(request: Request, form_data: LoadUrlForm, user=Depe 'name': tool_name, 'content': data, } + except HTTPException: + raise except Exception as e: - raise HTTPException(status_code=500, detail=ERROR_MESSAGES.DEFAULT(e)) + raise HTTPException( + status_code=500, + detail=ERROR_MESSAGES.DEFAULT(e, 'Error fetching tool'), + ) ############################ @@ -303,7 +316,7 @@ async def export_tools( if user.role != 'admin' and not await has_permission( user.id, 'workspace.tools_export', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ): raise HTTPException( @@ -331,11 +344,11 @@ async def create_new_tools( ): """Create a new tool from user-supplied Python source code.""" if user.role != 'admin' and not ( - await has_permission(user.id, 'workspace.tools', request.app.state.config.USER_PERMISSIONS, db=db) + await has_permission(user.id, 'workspace.tools', await Config.get('user.permissions'), db=db) or await has_permission( user.id, 'workspace.tools_import', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), db=db, ) ): @@ -356,7 +369,7 @@ async def create_new_tools( if tools is None: try: form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -366,8 +379,9 @@ async def create_new_tools( form_data.content = replace_imports(form_data.content) tool_module, frontmatter = await load_tool_module_by_id(form_data.id, content=form_data.content) form_data.meta.manifest = frontmatter + form_data.meta.has_user_valves = hasattr(tool_module, 'UserValves') - TOOLS = request.app.state.TOOLS + TOOLS = get_tools_cache(request) TOOLS[form_data.id] = tool_module specs = get_tool_specs(TOOLS[form_data.id]) @@ -377,17 +391,26 @@ async def create_new_tools( tool_cache_dir.mkdir(parents=True, exist_ok=True) if tools: + await publish_event( + request, + EVENTS.TOOL_CREATED, + actor=user, + subject_id=tools.id, + data={'name': tools.name}, + ) return tools else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT('Error creating tools'), ) + except HTTPException: + raise except Exception as e: log.exception(f'Failed to load the tool by id {form_data.id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error creating tool'), ) else: raise HTTPException( @@ -484,8 +507,8 @@ async def update_tools_by_id( # Content edits trigger exec on load — gate them behind workspace.tools (matches /create). if form_data.content != tools.content: if user.role != 'admin' and not ( - await has_permission(user.id, 'workspace.tools', request.app.state.config.USER_PERMISSIONS, db=db) - or await has_permission(user.id, 'workspace.tools_import', request.app.state.config.USER_PERMISSIONS, db=db) + await has_permission(user.id, 'workspace.tools', await Config.get('user.permissions'), db=db) + or await has_permission(user.id, 'workspace.tools_import', await Config.get('user.permissions'), db=db) ): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, @@ -496,14 +519,15 @@ async def update_tools_by_id( form_data.content = replace_imports(form_data.content) tool_module, frontmatter = await load_tool_module_by_id(id, content=form_data.content) form_data.meta.manifest = frontmatter + form_data.meta.has_user_valves = hasattr(tool_module, 'UserValves') - TOOLS = request.app.state.TOOLS + TOOLS = get_tools_cache(request) TOOLS[id] = tool_module specs = get_tool_specs(TOOLS[id]) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -519,6 +543,13 @@ async def update_tools_by_id( tools = await Tools.update_tool_by_id(id, updated, db=db) if tools: + await publish_event( + request, + EVENTS.TOOL_UPDATED, + actor=user, + subject_id=tools.id, + data={'name': tools.name}, + ) return tools else: raise HTTPException( @@ -526,10 +557,12 @@ async def update_tools_by_id( detail=ERROR_MESSAGES.DEFAULT('Error updating tools'), ) + except HTTPException: + raise except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating tool'), ) @@ -574,7 +607,7 @@ async def update_tool_access_by_id( ) form_data.access_grants = await filter_allowed_access_grants( - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), user.id, user.role, form_data.access_grants, @@ -583,7 +616,15 @@ async def update_tool_access_by_id( await AccessGrants.set_access_grants('tool', id, form_data.access_grants, db=db) - return await Tools.get_tool_by_id(id, db=db) + tools = await Tools.get_tool_by_id(id, db=db) + await publish_event( + request, + EVENTS.TOOL_ACCESS_UPDATED, + actor=user, + subject_id=id, + data={'name': tools.name if tools else None}, + ) + return tools ############################ @@ -623,9 +664,15 @@ async def delete_tools_by_id( result = await Tools.delete_tool_by_id(id, db=db) if result: - TOOLS = request.app.state.TOOLS - if id in TOOLS: - del TOOLS[id] + TOOLS = get_tools_cache(request) + TOOLS.pop(id, None) + await publish_event( + request, + EVENTS.TOOL_DELETED, + actor=user, + subject_id=id, + data={'name': tools.name}, + ) return result @@ -668,7 +715,7 @@ async def get_tools_valves_by_id( except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error getting tool valves'), ) @@ -707,11 +754,7 @@ async def get_tools_valves_spec_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - if id in request.app.state.TOOLS: - tools_module = request.app.state.TOOLS[id] - else: - tools_module, _ = await load_tool_module_by_id(id) - request.app.state.TOOLS[id] = tools_module + tools_module, _ = await get_tool_module_from_cache(request, id) if hasattr(tools_module, 'Valves'): Valves = tools_module.Valves @@ -758,11 +801,7 @@ async def update_tools_valves_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - if id in request.app.state.TOOLS: - tools_module = request.app.state.TOOLS[id] - else: - tools_module, _ = await load_tool_module_by_id(id) - request.app.state.TOOLS[id] = tools_module + tools_module, _ = await get_tool_module_from_cache(request, id) if not hasattr(tools_module, 'Valves'): raise HTTPException( @@ -776,12 +815,18 @@ async def update_tools_valves_by_id( valves = Valves(**form_data) valves_dict = valves.model_dump(exclude_unset=True) await Tools.update_tool_valves_by_id(id, valves_dict, db=db) + await publish_event( + request, + EVENTS.TOOL_VALVES_UPDATED, + actor=user, + subject_id=id, + ) return valves_dict except Exception as e: log.exception(f'Failed to update tool valves by id {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating tool valves'), ) @@ -823,7 +868,7 @@ async def get_tools_user_valves_by_id( except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error getting tool user valves'), ) @@ -857,11 +902,7 @@ async def get_tools_user_valves_spec_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - if id in request.app.state.TOOLS: - tools_module = request.app.state.TOOLS[id] - else: - tools_module, _ = await load_tool_module_by_id(id) - request.app.state.TOOLS[id] = tools_module + tools_module, _ = await get_tool_module_from_cache(request, id) if hasattr(tools_module, 'UserValves'): UserValves = tools_module.UserValves @@ -903,11 +944,7 @@ async def update_tools_user_valves_by_id( detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) - if id in request.app.state.TOOLS: - tools_module = request.app.state.TOOLS[id] - else: - tools_module, _ = await load_tool_module_by_id(id) - request.app.state.TOOLS[id] = tools_module + tools_module, _ = await get_tool_module_from_cache(request, id) if hasattr(tools_module, 'UserValves'): UserValves = tools_module.UserValves @@ -917,12 +954,19 @@ async def update_tools_user_valves_by_id( user_valves = UserValves(**form_data) user_valves_dict = user_valves.model_dump(exclude_unset=True) await Tools.update_user_valves_by_id_and_user_id(id, user.id, user_valves_dict, db=db) + await publish_event( + request, + EVENTS.TOOL_VALVES_UPDATED, + actor=user, + subject_id=id, + data={'scope': 'user'}, + ) return user_valves_dict except Exception as e: log.exception(f'Failed to update user valves by id {id}: {e}') raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(str(e)), + detail=ERROR_MESSAGES.DEFAULT(e, 'Error updating tool user valves'), ) else: raise HTTPException( diff --git a/backend/open_webui/routers/users.py b/backend/open_webui/routers/users.py index 0b8da713df..d15708941a 100644 --- a/backend/open_webui/routers/users.py +++ b/backend/open_webui/routers/users.py @@ -9,9 +9,11 @@ from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Request, status from fastapi.responses import FileResponse, Response, StreamingResponse from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ENABLE_PROFILE_IMAGE_URL_FORWARDING, PROFILE_IMAGE_ALLOWED_MIME_TYPES, STATIC_DIR from open_webui.internal.db import get_async_session from open_webui.models.auths import Auths +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.users import ( @@ -38,7 +40,7 @@ from open_webui.utils.auth import ( get_verified_user, validate_password, ) -from pydantic import BaseModel, ConfigDict +from pydantic import BaseModel, ConfigDict, Field from sqlalchemy.ext.asyncio import AsyncSession log = logging.getLogger(__name__) @@ -157,7 +159,7 @@ async def get_user_permissisions( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - user_permissions = await get_permissions(user.id, request.app.state.config.USER_PERMISSIONS, db=db) + user_permissions = await get_permissions(user.id, await Config.get('user.permissions'), db=db) return user_permissions @@ -177,6 +179,8 @@ class WorkspacePermissions(BaseModel): prompts_export: bool = False tools_import: bool = False tools_export: bool = False + skills_import: bool = False + skills_export: bool = False class SharingPermissions(BaseModel): @@ -201,6 +205,8 @@ class AccessGrantsPermissions(BaseModel): class ChatPermissions(BaseModel): + model_config = ConfigDict(populate_by_name=True) + controls: bool = True valves: bool = True system_prompt: bool = True @@ -215,6 +221,7 @@ class ChatPermissions(BaseModel): edit: bool = True share: bool = True export: bool = True + import_: bool = Field(default=True, alias='import') stt: bool = True tts: bool = True call: bool = True @@ -236,6 +243,7 @@ class FeaturesPermissions(BaseModel): memories: bool = True automations: bool = False calendar: bool = True + webhooks: bool = False class SettingsPermissions(BaseModel): @@ -253,20 +261,43 @@ class UserPermissions(BaseModel): @router.get('/default/permissions', response_model=UserPermissions) async def get_default_user_permissions(request: Request, user=Depends(get_admin_user)): + user_permissions = await Config.get('user.permissions') return { - 'workspace': WorkspacePermissions(**request.app.state.config.USER_PERMISSIONS.get('workspace', {})), - 'sharing': SharingPermissions(**request.app.state.config.USER_PERMISSIONS.get('sharing', {})), - 'access_grants': AccessGrantsPermissions(**request.app.state.config.USER_PERMISSIONS.get('access_grants', {})), - 'chat': ChatPermissions(**request.app.state.config.USER_PERMISSIONS.get('chat', {})), - 'features': FeaturesPermissions(**request.app.state.config.USER_PERMISSIONS.get('features', {})), - 'settings': SettingsPermissions(**request.app.state.config.USER_PERMISSIONS.get('settings', {})), + 'workspace': WorkspacePermissions(**user_permissions.get('workspace', {})), + 'sharing': SharingPermissions(**user_permissions.get('sharing', {})), + 'access_grants': AccessGrantsPermissions(**user_permissions.get('access_grants', {})), + 'chat': ChatPermissions(**user_permissions.get('chat', {})), + 'features': FeaturesPermissions(**user_permissions.get('features', {})), + 'settings': SettingsPermissions(**user_permissions.get('settings', {})), } @router.post('/default/permissions') async def update_default_user_permissions(request: Request, form_data: UserPermissions, user=Depends(get_admin_user)): - request.app.state.config.USER_PERMISSIONS = form_data.model_dump() - return request.app.state.config.USER_PERMISSIONS + user_permissions = form_data.model_dump(by_alias=True) + await Config.upsert({'user.permissions': user_permissions}) + await publish_event( + request, + EVENTS.USER_PERMISSIONS_UPDATED, + actor=user, + subject_id='user.permissions', + subject_type='config', + ) + return user_permissions + + +@router.get('/default/permissions/defaults', response_model=UserPermissions) +async def get_default_user_permissions_defaults(user=Depends(get_admin_user)): + from open_webui.config import DEFAULT_USER_PERMISSIONS + + return { + 'workspace': WorkspacePermissions(**DEFAULT_USER_PERMISSIONS.get('workspace', {})), + 'sharing': SharingPermissions(**DEFAULT_USER_PERMISSIONS.get('sharing', {})), + 'access_grants': AccessGrantsPermissions(**DEFAULT_USER_PERMISSIONS.get('access_grants', {})), + 'chat': ChatPermissions(**DEFAULT_USER_PERMISSIONS.get('chat', {})), + 'features': FeaturesPermissions(**DEFAULT_USER_PERMISSIONS.get('features', {})), + 'settings': SettingsPermissions(**DEFAULT_USER_PERMISSIONS.get('settings', {})), + } ############################ @@ -294,6 +325,14 @@ async def update_user_settings_by_session_user( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): + if user.role != 'admin' and not await has_permission( + user.id, 'settings.interface', request.app.state.config.USER_PERMISSIONS + ): + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) + updated_user_settings = form_data.model_dump() ui_settings = updated_user_settings.get('ui') if ( @@ -303,7 +342,7 @@ async def update_user_settings_by_session_user( and not await has_permission( user.id, 'features.direct_tool_servers', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), ) ): # If the user is not an admin and does not have permission to use tool servers, remove the key @@ -311,6 +350,12 @@ async def update_user_settings_by_session_user( user = await Users.update_user_settings_by_id(user.id, updated_user_settings, db=db) if user: + await publish_event( + request, + EVENTS.USER_SETTINGS_UPDATED, + actor=user, + subject_id=user.id, + ) return user.settings else: raise HTTPException( @@ -330,7 +375,7 @@ async def get_user_status_by_session_user( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if not request.app.state.config.ENABLE_USER_STATUS: + if not await Config.get('users.enable_status'): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACTION_PROHIBITED, @@ -351,7 +396,7 @@ async def update_user_status_by_session_user( user=Depends(get_verified_user), db: AsyncSession = Depends(get_async_session), ): - if not request.app.state.config.ENABLE_USER_STATUS: + if not await Config.get('users.enable_status'): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACTION_PROHIBITED, @@ -359,6 +404,12 @@ async def update_user_status_by_session_user( # user already fetched by get_verified_user — no need to refetch updated = await Users.update_user_status_by_id(user.id, form_data, db=db) if updated: + await publish_event( + request, + EVENTS.USER_STATUS_UPDATED, + actor=user, + subject_id=user.id, + ) return updated raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -541,6 +592,7 @@ async def get_user_active_status_by_id( @router.post('/{user_id}/update', response_model=UserModel | None) async def update_user_by_id( + request: Request, user_id: str, form_data: UserUpdateForm, session_user: UserModel = Depends(get_admin_user), @@ -591,7 +643,7 @@ async def update_user_by_id( except Exception as e: raise HTTPException(400, detail=str(e)) - hashed = get_password_hash(form_data.password) + hashed = await get_password_hash(form_data.password) await Auths.update_user_password_by_id(user_id, hashed, db=db) # Build update dict from only the provided fields @@ -620,6 +672,30 @@ async def update_user_by_id( # privileges cached in SESSION_POOL are invalidated. if updated_user.role != user.role: await disconnect_user_sessions(user_id) + await publish_event( + request, + EVENTS.USER_ROLE_UPDATED, + actor=session_user, + subject_id=user_id, + data={'role': updated_user.role}, + ) + else: + await publish_event( + request, + EVENTS.USER_UPDATED, + actor=session_user, + subject_id=user_id, + data={'updated_fields': list(update_data.keys())}, + ) + if form_data.password: + await publish_event( + request, + EVENTS.AUTH_PASSWORD_CHANGED, + actor=session_user, + subject_id=user_id, + subject_type='user', + source='admin', + ) return updated_user raise HTTPException( @@ -639,7 +715,9 @@ async def update_user_by_id( @router.delete('/{user_id}', response_model=bool) -async def delete_user_by_id(user_id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session)): +async def delete_user_by_id( + request: Request, user_id: str, user=Depends(get_admin_user), db: AsyncSession = Depends(get_async_session) +): # Prevent deletion of the primary admin user try: first_user = await Users.get_first_user(db=db) @@ -662,6 +740,12 @@ async def delete_user_by_id(user_id: str, user=Depends(get_admin_user), db: Asyn if result: await disconnect_user_sessions(user_id) + await publish_event( + request, + EVENTS.USER_DELETED, + actor=user, + subject_id=user_id, + ) return True raise HTTPException( diff --git a/backend/open_webui/routers/utils.py b/backend/open_webui/routers/utils.py index 4d0f679955..dcad54f4b1 100644 --- a/backend/open_webui/routers/utils.py +++ b/backend/open_webui/routers/utils.py @@ -7,6 +7,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request, Response, status from open_webui.config import DATA_DIR, ENABLE_ADMIN_EXPORT from open_webui.constants import ERROR_MESSAGES from open_webui.models.chats import ChatTitleMessagesForm +from open_webui.models.config import Config from open_webui.utils.auth import get_admin_user, get_verified_user from open_webui.utils.code_interpreter import execute_code_jupyter from open_webui.utils.misc import get_gravatar_url @@ -41,27 +42,27 @@ async def format_code(form_data: CodeForm, user=Depends(get_admin_user)): @router.post('/code/execute') async def execute_code(request: Request, form_data: CodeForm, user=Depends(get_verified_user)): - if not request.app.state.config.ENABLE_CODE_EXECUTION: + if not await Config.get('code_execution.enable'): raise HTTPException( status_code=403, detail=ERROR_MESSAGES.FEATURE_DISABLED('Code execution'), ) - if request.app.state.config.CODE_EXECUTION_ENGINE == 'jupyter': + if await Config.get('code_execution.engine') == 'jupyter': output = await execute_code_jupyter( - request.app.state.config.CODE_EXECUTION_JUPYTER_URL, + await Config.get('code_execution.jupyter.url'), form_data.code, ( - request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_TOKEN - if request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH == 'token' + await Config.get('code_execution.jupyter.auth_token') + if await Config.get('code_execution.jupyter.auth') == 'token' else None ), ( - request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH_PASSWORD - if request.app.state.config.CODE_EXECUTION_JUPYTER_AUTH == 'password' + await Config.get('code_execution.jupyter.auth_password') + if await Config.get('code_execution.jupyter.auth') == 'password' else None ), - request.app.state.config.CODE_EXECUTION_JUPYTER_TIMEOUT, + await Config.get('code_execution.jupyter.timeout'), ) return output diff --git a/backend/open_webui/socket/main.py b/backend/open_webui/socket/main.py index 2884847a0e..1cdd064b3a 100644 --- a/backend/open_webui/socket/main.py +++ b/backend/open_webui/socket/main.py @@ -38,7 +38,7 @@ from open_webui.models.users import UserNameResponse, Users from open_webui.socket.utils import RedisDict, RedisLock, YdocManager from open_webui.tasks import create_task, stop_item_tasks from open_webui.utils.access_control import has_permission -from open_webui.utils.auth import decode_token +from open_webui.utils.auth import decode_token, is_valid_token from open_webui.utils.redis import ( build_sentinel_url, get_redis_connection, @@ -342,9 +342,12 @@ async def usage(sid, data): async def connect(sid, environ, auth): user = None if auth and 'token' in auth: + scope = (environ or {}).get('asgi.scope') or {} + fastapi_app = scope.get('app') + redis = getattr(getattr(fastapi_app, 'state', None), 'redis', None) or REDIS data = decode_token(auth['token']) - if data is not None and 'id' in data: + if data is not None and 'id' in data and await is_valid_token(data, redis): user = await Users.get_user_by_id(data['id']) if user: @@ -369,8 +372,12 @@ async def user_join(sid, data): if not auth or 'token' not in auth: return + environ = sio.get_environ(sid) or {} + scope = environ.get('asgi.scope') or {} + fastapi_app = scope.get('app') + redis = getattr(getattr(fastapi_app, 'state', None), 'redis', None) or REDIS token_data = decode_token(auth['token']) - if token_data is None or 'id' not in token_data: + if token_data is None or 'id' not in token_data or not await is_valid_token(token_data, redis): return user = await Users.get_user_by_id(token_data['id']) @@ -416,8 +423,12 @@ async def join_channel(sid, data): if not auth or 'token' not in auth: return + environ = sio.get_environ(sid) or {} + scope = environ.get('asgi.scope') or {} + fastapi_app = scope.get('app') + redis = getattr(getattr(fastapi_app, 'state', None), 'redis', None) or REDIS data = decode_token(auth['token']) - if data is None or 'id' not in data: + if data is None or 'id' not in data or not await is_valid_token(data, redis): return user = await Users.get_user_by_id(data['id']) @@ -438,8 +449,12 @@ async def join_note(sid, data): if not auth or 'token' not in auth: return + environ = sio.get_environ(sid) or {} + scope = environ.get('asgi.scope') or {} + fastapi_app = scope.get('app') + redis = getattr(getattr(fastapi_app, 'state', None), 'redis', None) or REDIS token_data = decode_token(auth['token']) - if token_data is None or 'id' not in token_data: + if token_data is None or 'id' not in token_data or not await is_valid_token(token_data, redis): return user = await Users.get_user_by_id(token_data['id']) @@ -757,11 +772,13 @@ async def yjs_document_update(sid, data): @sio.on('ydoc:document:leave') async def yjs_document_leave(sid, data): """Handle user leaving a document""" + user = SESSION_POOL.get(sid) + if not user: # authenticated session required (parity with sibling handlers) + return try: document_id = normalize_document_id(data['document_id']) - user_id = data.get('user_id', sid) - log.info(f'User {user_id} leaving document {document_id}') + log.info(f'User {user["id"]} leaving document {document_id}') # Remove user from the document await YDOC_MANAGER.remove_user(document_id=document_id, user_id=sid) @@ -769,10 +786,10 @@ async def yjs_document_leave(sid, data): # Leave Socket.IO room await sio.leave_room(sid, f'doc_{document_id}') - # Notify other users + # Notify other users; user_id is the authenticated identity, not client-supplied await sio.emit( 'ydoc:user:left', - {'document_id': document_id, 'user_id': user_id}, + {'document_id': document_id, 'user_id': user['id']}, room=f'doc_{document_id}', ) @@ -787,16 +804,21 @@ async def yjs_document_leave(sid, data): @sio.on('ydoc:awareness:update') async def yjs_awareness_update(sid, data): """Handle awareness updates (cursors, selections, etc.)""" + user = SESSION_POOL.get(sid) + if not user: # authenticated session required (parity with sibling handlers) + return try: - document_id = data['document_id'] - user_id = data.get('user_id', sid) + document_id = normalize_document_id(data['document_id']) + room = f'doc_{document_id}' + if room not in sio.rooms(sid): # must have joined the document first + return update = data['update'] - # Broadcast awareness update to all other users in the document + # Broadcast to the room; user_id is the authenticated identity, not client-supplied await sio.emit( 'ydoc:awareness:update', - {'document_id': document_id, 'user_id': user_id, 'update': update}, - room=f'doc_{document_id}', + {'document_id': document_id, 'user_id': user['id'], 'update': update}, + room=room, skip_sid=sid, ) @@ -841,11 +863,14 @@ async def _make_channel_emitter(request_info): async def _emit_channel_update(content: str, done: bool = False): from open_webui.models.messages import MessageForm, Messages + msg = await Messages.get_message_by_id(message_id) + if not msg or msg.channel_id != channel_id: + return + update_form = MessageForm(content=content) if done: # Merge done flag into existing meta (preserve model_id etc.) - msg = await Messages.get_message_by_id(message_id) - existing_meta = (msg.meta or {}) if msg else {} + existing_meta = msg.meta or {} update_form = MessageForm( content=content, meta={**existing_meta, 'done': True}, @@ -1015,9 +1040,10 @@ async def get_event_call(request_info): async def __event_caller__(event_data): session_id = request_info['session_id'] - # Fast-fail if the client has disconnected. - if session_id not in SESSION_POOL: - log.warning(f'Event caller: session {session_id} no longer connected') + # session_id is client-supplied; only the requesting user's own live session may be targeted. + session = SESSION_POOL.get(session_id) + if session is None or session.get('id') != request_info.get('user_id'): + log.warning(f'Event caller: session {session_id} not owned by requesting user or disconnected') return {'error': 'Client session disconnected.'} try: diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index 965f333dfc..6193c10c53 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -18,6 +18,7 @@ from fastapi import Request from open_webui.models.channels import Channel, ChannelMember, Channels from open_webui.models.chats import Chats +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.memories import Memories from open_webui.models.messages import Message, Messages @@ -33,9 +34,15 @@ from open_webui.routers.images import ( ) from open_webui.routers.memories import ( AddMemoryForm, + ListMemoryPathsForm, MemoryUpdateModel, - QueryMemoryForm, - query_memory, + ReadMemoryPathForm, + SearchMemoriesForm, + UpdateMemoriesForm, + list_memory_paths as _list_memory_paths, + read_memory_path as _read_memory_path, + search_memories as _search_memories, + update_memories as _update_memories, update_memory_by_id, ) from open_webui.routers.memories import ( @@ -225,10 +232,10 @@ async def search_web( return json.dumps({'error': 'Request context not available'}) try: - engine = __request__.app.state.config.WEB_SEARCH_ENGINE + engine = await Config.get('web.search.engine') user = UserModel(**__user__) if __user__ else None - configured = __request__.app.state.config.WEB_SEARCH_RESULT_COUNT + configured = await Config.get('web.search.result_count') max_count = 5 if configured is None else configured count = max(1, min(count, max_count)) if count is not None else max_count @@ -261,12 +268,12 @@ async def fetch_url( return json.dumps({'error': 'Request context not available'}) try: - content, _ = await asyncio.to_thread(get_content_from_url, __request__, url) + content, _ = await get_content_from_url(__request__, url) # Truncate if configured (WEB_FETCH_MAX_CONTENT_LENGTH) # Guard: content may be None if the web loader silently failed if content is not None: - max_length = getattr(__request__.app.state.config, 'WEB_FETCH_MAX_CONTENT_LENGTH', None) + max_length = await Config.get('web.fetch.max_content_length') if max_length and max_length > 0 and len(content) > max_length: content = content[:max_length] + '\n\n[Content truncated...]' else: @@ -358,10 +365,11 @@ async def edit_image( __message_id__: str = None, ) -> str: """ - Edit existing images based on a text prompt. + Transform one or more existing images according to a text prompt. + Supports targeted edits such as adding, removing, replacing, inpainting, extending, or compositing image content. - :param prompt: A description of the changes to make to the images - :param image_urls: A list of URLs of the images to edit + :param prompt: A description of the transformation to apply to the provided images + :param image_urls: Source image URLs to modify or use as composition inputs :return: Confirmation that the images were edited, or an error message """ if __request__ is None: @@ -475,7 +483,7 @@ async def execute_code( ) code = blocking_code + '\n' + code - engine = getattr(__request__.app.state.config, 'CODE_INTERPRETER_ENGINE', 'pyodide') + engine = await Config.get('code_interpreter.engine', 'pyodide') if engine == 'pyodide': # Execute via frontend pyodide using bidirectional event call if __event_call__ is None: @@ -514,20 +522,14 @@ async def execute_code( elif engine == 'jupyter': from open_webui.utils.code_interpreter import execute_code_jupyter + jupyter_auth = await Config.get('code_interpreter.jupyter.auth') + output = await execute_code_jupyter( - __request__.app.state.config.CODE_INTERPRETER_JUPYTER_URL, + await Config.get('code_interpreter.jupyter.url'), code, - ( - __request__.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN - if __request__.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH == 'token' - else None - ), - ( - __request__.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD - if __request__.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH == 'password' - else None - ), - __request__.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT, + (await Config.get('code_interpreter.jupyter.auth_token') if jupyter_auth == 'token' else None), + (await Config.get('code_interpreter.jupyter.auth_password') if jupyter_auth == 'password' else None), + await Config.get('code_interpreter.jupyter.timeout'), ) stdout = output.get('stdout', '') @@ -593,17 +595,88 @@ async def execute_code( # ============================================================================= -async def search_memories( - query: str, - count: int = 5, +async def list_memory_paths( + query: str = '', + count: int = 100, + type: str = 'all', __request__: Request = None, __user__: dict = None, ) -> str: """ - Search the user's stored memories for relevant information. + List saved memory paths to find existing memory groups before writing or moving memories. - :param query: The search query to find relevant memories + :param query: Optional query to filter memory paths or contents + :param count: Maximum number of paths to return + :param type: "user", "context", or "all" + :return: JSON with memory paths, counts, children, and update times + """ + try: + user = UserModel(**__user__) if __user__ else None + result = await _list_memory_paths( + ListMemoryPathsForm( + query=query or None, + type=type if type in {'user', 'context', 'all'} else 'all', + limit=count, + ), + user, + ) + return json.dumps(result, ensure_ascii=False) + except Exception as e: + log.exception(f'list_memory_paths error: {e}') + return json.dumps({'error': str(e)}) + + +async def read_memory_path( + path: str, + count: int = 50, + type: str = 'all', + include_children: bool = True, + __request__: Request = None, + __user__: dict = None, +) -> str: + """ + Read saved memories at a memory path, including nearby parent and child paths. + + :param path: Memory path to read + :param count: Maximum number of memories to return + :param type: "user", "context", or "all" + :param include_children: Include memories under child paths + :return: JSON with parent paths, child paths, and memories at the path + """ + try: + user = UserModel(**__user__) if __user__ else None + result = await _read_memory_path( + ReadMemoryPathForm( + path=path, + type=type if type in {'user', 'context', 'all'} else 'all', + include_children=include_children, + limit=count, + ), + user, + ) + return json.dumps(result, ensure_ascii=False) + except Exception as e: + log.exception(f'read_memory_path error: {e}') + return json.dumps({'error': str(e)}) + + +async def search_memories( + query: str = '', + count: int = 5, + type: str = 'all', + path: Optional[str] = None, + memory_id: Optional[str] = None, + __request__: Request = None, + __user__: dict = None, +) -> str: + """ + Search or browse saved memories by content, path, type, or memory ID. + + :param query: Optional query to search memory content and path :param count: Number of memories to return (default 5) + :param type: "user", "context", or "all" + :param path: Optional memory path to search around + :param memory_id: Optional exact memory ID to read :return: JSON with matching memories and their dates """ if __request__ is None: @@ -612,28 +685,34 @@ async def search_memories( try: user = UserModel(**__user__) if __user__ else None - results = await query_memory( - __request__, - QueryMemoryForm(content=query, k=count), + memories = await _search_memories( + SearchMemoriesForm( + query=query or None, + type=type if type in {'user', 'context', 'all'} else 'all', + path=path, + memory_id=memory_id, + limit=count, + ), user, ) - if results and hasattr(results, 'documents') and results.documents: - memories = [] - for doc_idx, doc in enumerate(results.documents[0]): - memory_id = None - if results.ids and results.ids[0]: - memory_id = results.ids[0][doc_idx] - created_at = 'Unknown' - if results.metadatas and results.metadatas[0][doc_idx].get('created_at'): - created_at = time.strftime( - '%Y-%m-%d', - time.localtime(results.metadatas[0][doc_idx]['created_at']), - ) - memories.append({'id': memory_id, 'date': created_at, 'content': doc}) - return json.dumps(memories, ensure_ascii=False) - else: + if not memories: return json.dumps([]) + + return json.dumps( + [ + { + 'id': memory.id, + 'type': memory.type, + 'path': memory.path, + 'content': memory.content, + 'created_at': time.strftime('%Y-%m-%d', time.localtime(memory.created_at)), + 'updated_at': time.strftime('%Y-%m-%d', time.localtime(memory.updated_at)), + } + for memory in memories + ], + ensure_ascii=False, + ) except Exception as e: log.exception(f'search_memories error: {e}') return json.dumps({'error': str(e)}) @@ -641,13 +720,17 @@ async def search_memories( async def add_memory( content: str, + type: str = 'user', + path: Optional[str] = None, __request__: Request = None, __user__: dict = None, ) -> str: """ - Store a new memory for the user. + Save a user-provided preference, fact, or instruction as memory for future chats. :param content: The memory content to store + :param type: Use "user" for facts/preferences about the user, or "context" for other durable context + :param path: Optional stable memory address for grouping related memories :return: Confirmation that the memory was stored """ if __request__ is None: @@ -658,27 +741,73 @@ async def add_memory( memory = await _add_memory( __request__, - AddMemoryForm(content=content), + AddMemoryForm(content=content, type=Memories.normalize_memory_type(type), path=path), user, ) - return json.dumps({'status': 'success', 'id': memory.id}, ensure_ascii=False) + return json.dumps( + {'status': 'success', 'id': memory.id, 'type': memory.type, 'path': memory.path}, + ensure_ascii=False, + ) except Exception as e: log.exception(f'add_memory error: {e}') return json.dumps({'error': str(e)}) +async def update_memory( + operations: list[dict], + __request__: Request = None, + __user__: dict = None, +) -> str: + """ + Apply a batch of memory changes after learning durable information. + + Use type "user" for facts, preferences, or instructions about the user. + Use type "context" for other durable context that may help future chats. + Path is optional. Use it as a stable memory address to group related memories. + Prefer an existing path from list_memory_paths when one fits. + Leave path empty when no useful grouping is clear. + + Operation shapes: + - {"action": "add", "content": "...", "type": "user"|"context", "path": "..."} + - {"action": "replace", "id": "...", "content": "...", "type": "user"|"context", "path": "..."} + - {"action": "move", "id": "...", "path": "..."} + - {"action": "remove", "id": "..."} + + :param operations: Memory operations to apply in one request + :return: JSON with operation results + """ + if __request__ is None: + return json.dumps({'error': 'Request context not available'}) + + try: + user = UserModel(**__user__) if __user__ else None + operation_results = await _update_memories( + __request__, + UpdateMemoriesForm(operations=operations), + user, + ) + return json.dumps(operation_results, ensure_ascii=False) + except Exception as e: + log.exception(f'update_memory error: {e}') + return json.dumps({'error': str(e)}) + + async def replace_memory_content( memory_id: str, content: str, + type: Optional[str] = None, + path: Optional[str] = None, __request__: Request = None, __user__: dict = None, ) -> str: """ - Update the content of an existing memory by its ID. + Update an existing saved memory by its ID when its content needs correction. :param memory_id: The ID of the memory to update :param content: The new content for the memory + :param type: Optional "user" or "context" type for the updated memory + :param path: Optional stable memory address for grouping related memories :return: Confirmation that the memory was updated """ if __request__ is None: @@ -690,12 +819,22 @@ async def replace_memory_content( memory = await update_memory_by_id( memory_id=memory_id, request=__request__, - form_data=MemoryUpdateModel(content=content), + form_data=MemoryUpdateModel( + content=content, + type=Memories.normalize_memory_type(type) if type else None, + path=path, + ), user=user, ) return json.dumps( - {'status': 'success', 'id': memory.id, 'content': memory.content}, + { + 'status': 'success', + 'id': memory.id, + 'type': memory.type, + 'path': memory.path, + 'content': memory.content, + }, ensure_ascii=False, ) except Exception as e: @@ -709,7 +848,7 @@ async def delete_memory( __user__: dict = None, ) -> str: """ - Delete a memory by its ID. + Delete a saved memory by its ID. :param memory_id: The ID of the memory to delete :return: Confirmation that the memory was deleted @@ -740,7 +879,7 @@ async def list_memories( __user__: dict = None, ) -> str: """ - List all stored memories for the user. + List all stored memories for the user, including IDs and timestamps. :return: JSON list of all memories with id, content, and dates """ @@ -753,16 +892,18 @@ async def list_memories( memories = await Memories.get_memories_by_user_id(user.id) if memories: - result = [ + memory_rows = [ { 'id': m.id, + 'type': m.type, + 'path': m.path, 'content': m.content, 'created_at': time.strftime('%Y-%m-%d %H:%M', time.localtime(m.created_at)), 'updated_at': time.strftime('%Y-%m-%d %H:%M', time.localtime(m.updated_at)), } for m in memories ] - return json.dumps(result, ensure_ascii=False) + return json.dumps(memory_rows, ensure_ascii=False) else: return json.dumps([]) except Exception as e: @@ -784,7 +925,7 @@ async def search_notes( __user__: dict = None, ) -> str: """ - Search the user's notes by title and content. + Search the user's saved notes by title and content. :param query: The search query to find matching notes :param count: Maximum number of results to return (default: 5) @@ -987,7 +1128,7 @@ async def replace_note_content( __user__: dict = None, ) -> str: """ - Update the content of a note. Use this to modify task lists, add notes, or update content. + Update the markdown content, and optionally the title, of an existing note. :param note_id: The ID of the note to update :param content: The new markdown content for the note @@ -1064,6 +1205,7 @@ async def search_chats( ) -> str: """ Search the user's previous chat conversations by title and message content. + Helpful for finding details from earlier conversations. :param query: The search query to find matching chats :param count: Maximum number of results to return (default: 5) @@ -1102,7 +1244,7 @@ async def search_chats( # Find a matching message snippet snippet = '' - messages = chat.chat.get('history', {}).get('messages', {}) + messages = (getattr(chat, 'chat', None) or {}).get('history', {}).get('messages', {}) lower_query = query.lower() for msg_id, msg in messages.items(): @@ -1141,7 +1283,8 @@ async def view_chat( __user__: dict = None, ) -> str: """ - Get the full conversation history of a chat by its ID. + Get the full conversation history of a chat by its ID after a relevant + previous chat has been identified. :param chat_id: The ID of the chat to retrieve :return: JSON with the chat's id, title, and messages @@ -1211,7 +1354,7 @@ async def search_channels( __user__: dict = None, ) -> str: """ - Search for channels by name and description that the user has access to. + Search channels by name and description to find accessible team spaces. :param query: The search query to find matching channels :param count: Maximum number of results to return (default: 5) @@ -1265,7 +1408,8 @@ async def search_channel_messages( __user__: dict = None, ) -> str: """ - Search for messages in channels the user is a member of, including thread replies. + Search messages in channels the user is a member of, including thread replies. + Helpful for finding prior team/channel discussion. :param query: The search query to find matching messages :param count: Maximum number of results to return (default: 10) @@ -1493,7 +1637,8 @@ async def list_knowledge_bases( __user__: dict = None, ) -> str: """ - List the user's accessible knowledge bases. + List the user's accessible knowledge bases so a relevant internal source + can be chosen. :param count: Maximum number of KBs to return (default: 10) :param skip: Number of results to skip for pagination (default: 0) @@ -1551,7 +1696,8 @@ async def search_knowledge_bases( __user__: dict = None, ) -> str: """ - Search the user's accessible knowledge bases by name and description. + Search the user's accessible knowledge bases by name and description to find + a relevant internal source. :param query: The search query to find matching knowledge bases :param count: Maximum number of results to return (default: 5) @@ -1614,6 +1760,7 @@ async def search_knowledge_files( """ Search files by filename across knowledge bases the user has access to. When the model has attached knowledge, searches only within attached KBs and files. + Helpful when looking for a specific document or file name. :param query: The search query to find matching files by filename :param knowledge_id: Optional KB id to limit search to a specific knowledge base @@ -1785,6 +1932,7 @@ async def grep_knowledge_files( Search for exact text across knowledge files. Returns matching lines with line numbers. Unlike query_knowledge_files (semantic/vector search), this performs exact string matching. Automatically detects regex patterns (e.g. "error|warn", "version \\d+"). + Helpful for literal strings, identifiers, error messages, or regex-style searches. :param pattern: The text pattern to search for (regex auto-detected) :param file_id: Optional file ID to search within a single file only @@ -2347,6 +2495,7 @@ async def query_knowledge_files( """ Search knowledge base files using semantic/vector search. Searches across collections (KBs), individual files, and notes that the user has access to. + Helpful for internal documentation, uploaded knowledge, and attached model knowledge. :param query: The search query to find semantically relevant content :param knowledge_ids: Optional list of KB ids to limit search to specific knowledge bases @@ -2383,6 +2532,7 @@ async def query_knowledge_files( from open_webui.models.files import Files from open_webui.models.knowledge import Knowledges from open_webui.models.notes import Notes + from open_webui.retrieval.external import retrieve_external_knowledge from open_webui.retrieval.utils import query_collection user_id = __user__.get('id') @@ -2394,6 +2544,7 @@ async def query_knowledge_files( return json.dumps({'error': 'Embedding function not configured'}) collection_names = [] + external_knowledges = [] note_results = [] # Notes aren't vectorized, handle separately # If model has attached knowledge, use those @@ -2416,7 +2567,10 @@ async def query_knowledge_files( user_group_ids=set(user_group_ids), ) ): - collection_names.append(item_id) + if (knowledge.meta or {}).get('source') == 'external': + external_knowledges.append(knowledge) + else: + collection_names.append(item_id) elif item_type == 'file': # Individual file - use file-{id} as collection name @@ -2462,7 +2616,10 @@ async def query_knowledge_files( user_group_ids=set(user_group_ids), ) ): - collection_names.append(knowledge_id) + if (knowledge.meta or {}).get('source') == 'external': + external_knowledges.append(knowledge) + else: + collection_names.append(knowledge_id) else: # No model knowledge and no specific IDs - search all accessible KBs result = await Knowledges.search_knowledge_bases( @@ -2475,7 +2632,11 @@ async def query_knowledge_files( skip=0, limit=50, ) - collection_names = [knowledge_base.id for knowledge_base in result.items] + for knowledge_base in result.items: + if (knowledge_base.meta or {}).get('source') == 'external': + external_knowledges.append(knowledge_base) + else: + collection_names.append(knowledge_base.id) chunks = [] @@ -2507,6 +2668,31 @@ async def query_knowledge_files( chunk_info['distance'] = distances[idx] chunks.append(chunk_info) + for knowledge in external_knowledges: + query_results = await retrieve_external_knowledge( + __request__, + knowledge, + queries=[query], + count=count, + user=type('UserContext', (), {'id': user_id, 'role': user_role})(), + ) + documents = query_results.get('documents', [[]])[0] + metadatas = query_results.get('metadatas', [[]])[0] + distances = query_results.get('distances', [[]])[0] + + for idx, doc in enumerate(documents): + metadata = metadatas[idx] if idx < len(metadatas) else {} + chunk_info = { + 'content': doc, + 'source': metadata.get('source', metadata.get('name', knowledge.name)), + 'file_id': metadata.get('file_id', f'external-{knowledge.id}'), + 'type': 'external', + 'knowledge_id': knowledge.id, + } + if idx < len(distances): + chunk_info['distance'] = distances[idx] + chunks.append(chunk_info) + # Limit to requested count chunks = chunks[:count] @@ -2525,7 +2711,7 @@ async def query_knowledge_bases( """ Search knowledge bases by semantic similarity to query. Finds KBs whose name/description match the meaning of your query. - Use this to discover relevant knowledge bases before querying their files. + Helpful for discovering which knowledge base to query next. :param query: Natural language query describing what you're looking for :param count: Maximum results (default: 5) @@ -2731,9 +2917,7 @@ async def create_tasks( __user__: dict = None, ) -> str: """ - Create a task checklist to track progress on multi-step work. - Call this once at the start to define all steps, then use - update_task to mark each task as you complete it. + Create a visible task checklist for multi-step work so progress can be shown in chat. :param tasks: List of task items. Each item: content (string, required), status (pending|in_progress|completed|cancelled, default pending), id (optional, auto-generated). :return: JSON with the full task list and summary counts @@ -2784,9 +2968,7 @@ async def update_task( __user__: dict = None, ) -> str: """ - Mark a single task as completed, in_progress, pending, or cancelled. - Call this after finishing each step. You MUST call this for every - task, including the very last one. + Mark a single visible task item as completed, in_progress, pending, or cancelled. :param id: The task ID to update :param status: New status: completed, in_progress, pending, or cancelled (default: completed) @@ -3226,8 +3408,7 @@ async def search_calendar_events( ) -> str: """ Search calendar events, reminders, and scheduled items by text and/or date range. - Use this to check what's coming up, find a specific event or reminder, or list - the user's schedule for a time period. + Helpful for finding upcoming events, reminders, or schedule items. :param query: Search text to match against event title, description, or location (optional) :param start: Only return events starting at or after this datetime, e.g. "2026-04-20 00:00" (optional) diff --git a/backend/open_webui/tools/knowledge_fs.py b/backend/open_webui/tools/knowledge_fs.py index 512cb139ba..0ec1cc8983 100644 --- a/backend/open_webui/tools/knowledge_fs.py +++ b/backend/open_webui/tools/knowledge_fs.py @@ -482,6 +482,11 @@ async def _kb_ls(args: list[str], flags: set[str], user: dict, model_knowledge: path_arg = args[0] if args else None kb_ids = await _get_accessible_kb_ids(user, model_knowledge, knowledge_id=None) + direct_files = ( + [f for f in await _get_accessible_files(user, model_knowledge) if not f.get('knowledge_id')] + if model_knowledge + else [] + ) # If path_arg looks like a KB ID, scope to that KB target_kb_id = None @@ -497,7 +502,7 @@ async def _kb_ls(args: list[str], flags: set[str], user: dict, model_knowledge: if target_kb_id: kb_ids = [(kid, kn, kd) for kid, kn, kd in kb_ids if kid == target_kb_id] - if not kb_ids: + if not kb_ids and not direct_files: return 'No knowledge bases found.' lines = [] @@ -540,6 +545,12 @@ async def _kb_ls(args: list[str], flags: set[str], user: dict, model_knowledge: lines.append(' (empty)') lines.append('') + if direct_files and not target_kb_id and not dir_path: + lines.append('Attached Files:') + for f in direct_files: + lines.append(f' {f["id"]} {f["filename"]} {_fmt_size(f)} {_fmt_date(f)}') + lines.append('') + return '\n'.join(lines).rstrip() @@ -958,7 +969,12 @@ async def _kb_sed( async def _kb_tree(args: list[str], flags: set[str], user: dict, model_knowledge: list[dict] | None) -> str: """Show directory tree structure.""" kb_ids = await _get_accessible_kb_ids(user, model_knowledge) - if not kb_ids: + direct_files = ( + [f for f in await _get_accessible_files(user, model_knowledge) if not f.get('knowledge_id')] + if model_knowledge + else [] + ) + if not kb_ids and not direct_files: return 'No knowledge bases found.' dir_scope = args[0].strip('/') if args else None @@ -1007,6 +1023,14 @@ async def _kb_tree(args: list[str], flags: set[str], user: dict, model_knowledge output.append(f'\n {total_dirs} directories, {total_files} files') output.append('') + if direct_files and not dir_scope: + output.append('Attached Files:') + for idx, f in enumerate(direct_files): + connector = '└── ' if idx == len(direct_files) - 1 else '├── ' + output.append(f' {connector}{f["filename"]}') + output.append(f'\n 0 directories, {len(direct_files)} files') + output.append('') + return '\n'.join(output).rstrip() diff --git a/backend/open_webui/utils/access_control/__init__.py b/backend/open_webui/utils/access_control/__init__.py index 1cc2f086f5..a98f95f97e 100644 --- a/backend/open_webui/utils/access_control/__init__.py +++ b/backend/open_webui/utils/access_control/__init__.py @@ -114,7 +114,7 @@ async def has_access( Check if a user has the specified permission using an in-memory access_grants list. Used for config-driven resources (arena models, tool servers) that store - access control as JSON in ConfigVar rather than in the access_grant DB table. + access control as JSON config rather than in the access_grant DB table. Semantics: - None or [] → private (owner-only, deny all) @@ -321,7 +321,8 @@ async def check_model_access( return if model_info: - if user.role == 'user': + # Enforce for every non-admin role (including pending); never fail open. + if user.role != 'admin': from open_webui.models.access_grants import AccessGrants user_group_ids = {group.id for group in await Groups.get_groups_by_member_id(user.id)} diff --git a/backend/open_webui/utils/access_control/files.py b/backend/open_webui/utils/access_control/files.py index 3a4871aae3..ddb6acb066 100644 --- a/backend/open_webui/utils/access_control/files.py +++ b/backend/open_webui/utils/access_control/files.py @@ -38,25 +38,33 @@ async def has_access_to_file( if file.user_id == user.id: return True - # Check if the file is associated with any knowledge bases the user has access to + # Check if the file is associated with any knowledge bases the user has access to. + # An object (knowledge base or workspace model) confers write/delete on a file only when + # the object's OWNER owns that file; otherwise a read-only file laundered into an object + # the user controls would gain write/delete on it (CWE-863). Read access is unaffected. knowledge_bases = await Knowledges.get_knowledges_by_file_id(file_id, db=db) user_group_ids = {group.id for group in await Groups.get_groups_by_member_id(user.id, db=db)} for knowledge_base in knowledge_bases: - if knowledge_base.user_id == user.id or await AccessGrants.has_access( - user_id=user.id, - resource_type='knowledge', - resource_id=knowledge_base.id, - permission=access_type, - user_group_ids=user_group_ids, - db=db, - ): + if ( + knowledge_base.user_id == user.id + or await AccessGrants.has_access( + user_id=user.id, + resource_type='knowledge', + resource_id=knowledge_base.id, + permission=access_type, + user_group_ids=user_group_ids, + db=db, + ) + ) and (access_type == 'read' or knowledge_base.user_id == file.user_id): return True knowledge_base_id = file.meta.get('collection_name') if file.meta else None if knowledge_base_id: knowledge_bases = await Knowledges.get_knowledge_bases_by_user_id(user.id, access_type, db=db) for knowledge_base in knowledge_bases: - if knowledge_base.id == knowledge_base_id: + if knowledge_base.id == knowledge_base_id and ( + access_type == 'read' or knowledge_base.user_id == file.user_id + ): return True # Check if the file is associated with any channels the user has access to @@ -78,12 +86,14 @@ async def has_access_to_file( if accessible_ids: return True - # Check if the file is directly attached to a shared workspace model + # Check if the file is directly attached to a shared workspace model (per the ownership + # note above, model write is conferred only for files the model owner owns). for model in await Models.get_models_by_user_id(user.id, permission=access_type, db=db): knowledge_items = getattr(model.meta, 'knowledge', None) or [] for item in knowledge_items: if isinstance(item, dict) and item.get('type') == 'file' and item.get('id') == file.id: - return True + if access_type == 'read' or model.user_id == file.user_id: + return True return False diff --git a/backend/open_webui/utils/access_control/folders.py b/backend/open_webui/utils/access_control/folders.py new file mode 100644 index 0000000000..7dcc1a3395 --- /dev/null +++ b/backend/open_webui/utils/access_control/folders.py @@ -0,0 +1,24 @@ +from open_webui.models.access_grants import AccessGrants +from open_webui.models.folders import FolderModel, Folders +from sqlalchemy.ext.asyncio import AsyncSession + + +async def has_folder_access(user_id: str, folder: FolderModel, permission: str, db: AsyncSession) -> bool: + """Check if user has access to folder directly or via ancestor inheritance.""" + if folder.user_id == user_id: + return True + + if await AccessGrants.has_access( + user_id=user_id, + resource_type='folder', + resource_id=folder.id, + permission=permission, + db=db, + ): + return True + # Check ancestor chain for inherited access + if folder.parent_id: + parent = await Folders.get_folder_by_id(folder.parent_id, db=db) + if parent: + return await has_folder_access(user_id, parent, permission, db) + return False diff --git a/backend/open_webui/utils/anthropic.py b/backend/open_webui/utils/anthropic.py index 5feed2b8ef..9e8bc54cf0 100644 --- a/backend/open_webui/utils/anthropic.py +++ b/backend/open_webui/utils/anthropic.py @@ -89,6 +89,26 @@ async def get_anthropic_models(url: str, key: str, user: UserModel = None) -> di ############################## +def _copy_cache_control(source: dict, target: dict) -> dict: + if isinstance(source, dict) and 'cache_control' in source: + target['cache_control'] = source['cache_control'] + return target + + +def _has_cache_control(blocks: list) -> bool: + return any(isinstance(block, dict) and 'cache_control' in block for block in blocks) + + +def _finalize_openai_content(blocks: list) -> str | list: + if not blocks: + return '' + + if len(blocks) == 1 and blocks[0].get('type') == 'text' and not _has_cache_control(blocks): + return blocks[0].get('text', '') + + return blocks + + def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: """ Convert an Anthropic Messages API request to OpenAI Chat Completions format. @@ -112,14 +132,21 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: if isinstance(system, str): messages.append({'role': 'system', 'content': system}) elif isinstance(system, list): - # Anthropic supports system as list of content blocks - text_parts = [] + openai_content = [] for block in system: if isinstance(block, dict) and block.get('type') == 'text': - text_parts.append(block.get('text', '')) + openai_content.append( + _copy_cache_control( + block, + { + 'type': 'text', + 'text': block.get('text', ''), + }, + ) + ) elif isinstance(block, str): - text_parts.append(block) - messages.append({'role': 'system', 'content': '\n'.join(text_parts)}) + openai_content.append({'type': 'text', 'text': block}) + messages.append({'role': 'system', 'content': _finalize_openai_content(openai_content)}) # Convert messages for msg in anthropic_payload.get('messages', []): @@ -138,10 +165,13 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: if block_type == 'text': openai_content.append( - { - 'type': 'text', - 'text': block.get('text', ''), - } + _copy_cache_control( + block, + { + 'type': 'text', + 'text': block.get('text', ''), + }, + ) ) elif block_type == 'image': source = block.get('source', {}) @@ -149,19 +179,25 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: media_type = source.get('media_type', 'image/png') data = source.get('data', '') openai_content.append( - { - 'type': 'image_url', - 'image_url': { - 'url': f'data:{media_type};base64,{data}', + _copy_cache_control( + block, + { + 'type': 'image_url', + 'image_url': { + 'url': f'data:{media_type};base64,{data}', + }, }, - } + ) ) elif source.get('type') == 'url': openai_content.append( - { - 'type': 'image_url', - 'image_url': {'url': source.get('url', '')}, - } + _copy_cache_control( + block, + { + 'type': 'image_url', + 'image_url': {'url': source.get('url', '')}, + }, + ) ) elif block_type == 'tool_use': tool_calls.append( @@ -196,10 +232,13 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: if content_type == 'text': converted_parts.append( - { - 'type': 'text', - 'text': content_block.get('text', ''), - } + _copy_cache_control( + content_block, + { + 'type': 'text', + 'text': content_block.get('text', ''), + }, + ) ) elif content_type == 'image': source = content_block.get('source', {}) @@ -207,21 +246,27 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: media_type = source.get('media_type', 'image/png') data = source.get('data', '') converted_parts.append( - { - 'type': 'image_url', - 'image_url': { - 'url': f'data:{media_type};base64,{data}', + _copy_cache_control( + content_block, + { + 'type': 'image_url', + 'image_url': { + 'url': f'data:{media_type};base64,{data}', + }, }, - } + ) ) elif source.get('type') == 'url': converted_parts.append( - { - 'type': 'image_url', - 'image_url': { - 'url': source.get('url', ''), + _copy_cache_control( + content_block, + { + 'type': 'image_url', + 'image_url': { + 'url': source.get('url', ''), + }, }, - } + ) ) elif content_type == 'document': # Documents have no direct OpenAI equivalent; @@ -254,7 +299,9 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: converted_parts.append({'type': 'text', 'text': search_text}) # Flatten to string when only text parts are present - if all(part.get('type') == 'text' for part in converted_parts): + if all(part.get('type') == 'text' for part in converted_parts) and not _has_cache_control( + converted_parts + ): tool_content = '\n'.join(part.get('text', '') for part in converted_parts) elif converted_parts: tool_content = converted_parts @@ -287,21 +334,13 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: # Assistant message with tool calls msg_dict = {'role': role} if openai_content: - # If there's only text, flatten it - if len(openai_content) == 1 and openai_content[0]['type'] == 'text': - msg_dict['content'] = openai_content[0]['text'] - else: - msg_dict['content'] = openai_content + msg_dict['content'] = _finalize_openai_content(openai_content) else: msg_dict['content'] = '' msg_dict['tool_calls'] = tool_calls messages.append(msg_dict) elif openai_content: - # If there's only a single text block, flatten it to a string - if len(openai_content) == 1 and openai_content[0]['type'] == 'text': - messages.append({'role': role, 'content': openai_content[0]['text']}) - else: - messages.append({'role': role, 'content': openai_content}) + messages.append({'role': role, 'content': _finalize_openai_content(openai_content)}) else: messages.append({'role': role, 'content': str(content) if content else ''}) @@ -312,7 +351,7 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: openai_payload['max_tokens'] = anthropic_payload['max_tokens'] # Common parameters - for param in ('temperature', 'top_p', 'stop_sequences', 'stream'): + for param in ('temperature', 'top_p', 'top_k', 'stop_sequences', 'stream', 'metadata', 'service_tier'): if param in anthropic_payload: if param == 'stop_sequences': openai_payload['stop'] = anthropic_payload[param] @@ -324,30 +363,33 @@ def convert_anthropic_to_openai_payload(anthropic_payload: dict) -> dict: openai_tools = [] for tool in anthropic_payload['tools']: openai_tools.append( - { - 'type': 'function', - 'function': { - 'name': tool.get('name', ''), - 'description': tool.get('description', ''), - 'parameters': tool.get('input_schema', {}), + _copy_cache_control( + tool, + { + 'type': 'function', + 'function': { + 'name': tool.get('name', ''), + 'description': tool.get('description', ''), + 'parameters': tool.get('input_schema', {}), + }, }, - } + ) ) openai_payload['tools'] = openai_tools # tool_choice if 'tool_choice' in anthropic_payload: - tc = anthropic_payload['tool_choice'] - if isinstance(tc, dict): - tc_type = tc.get('type', 'auto') - if tc_type == 'auto': + tool_choice = anthropic_payload['tool_choice'] + if isinstance(tool_choice, dict): + tool_choice_type = tool_choice.get('type', 'auto') + if tool_choice_type == 'auto': openai_payload['tool_choice'] = 'auto' - elif tc_type == 'any': + elif tool_choice_type == 'any': openai_payload['tool_choice'] = 'required' - elif tc_type == 'tool': + elif tool_choice_type == 'tool': openai_payload['tool_choice'] = { 'type': 'function', - 'function': {'name': tc.get('name', '')}, + 'function': {'name': tool_choice.get('name', '')}, } return openai_payload @@ -377,23 +419,23 @@ def convert_openai_to_anthropic_response(openai_response: dict, model: str = '') # Build content blocks content = [] - msg_content = message.get('content') - if msg_content: - content.append({'type': 'text', 'text': msg_content}) + message_content = message.get('content') + if message_content: + content.append({'type': 'text', 'text': message_content}) - # Tool calls → tool_use blocks - tool_calls = message.get('tool_calls', []) - for tc in tool_calls: - func = tc.get('function', {}) + # Tool calls -> tool_use blocks + tool_calls = message.get('tool_calls') or [] + for tool_call in tool_calls: + function = tool_call.get('function', {}) try: - tool_input = json.loads(func.get('arguments', '{}')) + tool_input = json.loads(function.get('arguments', '{}')) except (json.JSONDecodeError, TypeError): tool_input = {} content.append( { 'type': 'tool_use', - 'id': tc.get('id', f'toolu_{_uuid.uuid4().hex[:24]}'), - 'name': func.get('name', ''), + 'id': tool_call.get('id', f'toolu_{_uuid.uuid4().hex[:24]}'), + 'name': function.get('name', ''), 'input': tool_input, } ) @@ -404,6 +446,10 @@ def convert_openai_to_anthropic_response(openai_response: dict, model: str = '') 'input_tokens': openai_usage.get('prompt_tokens', 0), 'output_tokens': openai_usage.get('completion_tokens', 0), } + if 'cache_creation_input_tokens' in openai_usage: + usage['cache_creation_input_tokens'] = openai_usage['cache_creation_input_tokens'] + if 'cache_read_input_tokens' in openai_usage: + usage['cache_read_input_tokens'] = openai_usage['cache_read_input_tokens'] return { 'id': openai_response.get('id', f'msg_{_uuid.uuid4().hex[:24]}'), @@ -426,10 +472,14 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str Handles text content, tool calls, and mixed content with proper multi-block indexing as required by Anthropic's streaming protocol. + + Tool calls are tracked by their unique id (not OpenAI index) so that + parallel calls sharing the same index get distinct Anthropic tool_use + blocks. Each block follows the Anthropic lifecycle: start -> delta -> stop. """ import uuid as _uuid - msg_id = f'msg_{_uuid.uuid4().hex[:24]}' + message_id = f'msg_{_uuid.uuid4().hex[:24]}' input_tokens = 0 output_tokens = 0 stop_reason = 'end_turn' @@ -439,16 +489,21 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str current_block_index = 0 text_block_open = False - # Track tool call state: maps OpenAI tool_call index -> Anthropic block index - # This allows handling multiple concurrent tool calls. - tool_call_blocks = {} # {openai_tc_index: anthropic_block_index} - tool_call_started = {} # {openai_tc_index: bool} + # Accumulated state for each tool call, keyed by tool call id. + # Parallel calls that share the same OpenAI index get distinct entries. + # Each entry: {id, name, arguments, block_index, started, stopped} + tracked_tool_calls = {} + # Map OpenAI tool call index -> tool call id for routing + # argument-only deltas (deltas that carry arguments but no id). + index_to_tool_id = {} + # Whether any tool call block has been emitted (suppresses further text) + has_tool_calls = False # Emit message_start message_start = { 'type': 'message_start', 'message': { - 'id': msg_id, + 'id': message_id, 'type': 'message', 'role': 'assistant', 'content': [], @@ -471,14 +526,14 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str if not line or not line.startswith('data:'): continue - data_str = line[5:].strip() - if data_str == '[DONE]': + data_string = line[5:].strip() + if data_string == '[DONE]': continue - if data_str == '{}': + if data_string == '{}': continue try: - data = json.loads(data_str) + data = json.loads(data_string) except (json.JSONDecodeError, TypeError): continue @@ -492,6 +547,7 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str delta = choices[0].get('delta', {}) finish_reason = choices[0].get('finish_reason') + message = choices[0].get('message') or {} # Update usage if present if data.get('usage'): @@ -499,10 +555,11 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str output_tokens = data['usage'].get('completion_tokens', output_tokens) # --- Handle text content --- + # Anthropic expects text blocks before tool blocks, so skip + # text deltas once any tool call has started. content = delta.get('content') - if content is not None: + if content and not has_tool_calls: if not text_block_open: - # Start a new text content block block_start = { 'type': 'content_block_start', 'index': current_block_index, @@ -511,7 +568,6 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str yield f'event: content_block_start\ndata: {json.dumps(block_start)}\n\n'.encode() text_block_open = True - # Send text delta block_delta = { 'type': 'content_block_delta', 'index': current_block_index, @@ -520,7 +576,12 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str yield f'event: content_block_delta\ndata: {json.dumps(block_delta)}\n\n'.encode() # --- Handle tool calls --- - tool_calls = delta.get('tool_calls') + # Some providers put tool_calls on the final message object + # instead of the delta; fall back to that when needed. + tool_calls = delta.get('tool_calls') or [] + if not tool_calls and message.get('tool_calls'): + tool_calls = message['tool_calls'] + if tool_calls: # Close text block if one is open (text comes before tools) if text_block_open: @@ -532,43 +593,95 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str text_block_open = False current_block_index += 1 - for tc in tool_calls: - tc_index = tc.get('index', 0) + for tool_call in tool_calls: + tool_call_index = tool_call.get('index', 0) + tool_call_id = tool_call.get('id', '') + tool_call_name = (tool_call.get('function') or {}).get('name', '') + arguments_chunk = (tool_call.get('function') or {}).get('arguments', '') - if tc_index not in tool_call_started: - # First time seeing this tool call — emit content_block_start - tool_call_blocks[tc_index] = current_block_index - tool_call_started[tc_index] = True + # Resolve which tracked tool call this delta belongs to. + # A delta with an id starts or identifies a specific tool. + # A delta without an id carries arguments for the most + # recent tool at this OpenAI index. + if tool_call_id: + if tool_call_id not in tracked_tool_calls: + tracked_tool_calls[tool_call_id] = { + 'id': tool_call_id, + 'name': tool_call_name, + 'arguments': '', + 'block_index': -1, + 'started': False, + 'stopped': False, + } + index_to_tool_id[tool_call_index] = tool_call_id + tool = tracked_tool_calls[tool_call_id] + elif tool_call_index in index_to_tool_id: + tool = tracked_tool_calls[index_to_tool_id[tool_call_index]] + else: + # First delta for this index with no id; create a + # provisional entry with a generated fallback id. + fallback_id = f'toolu_{_uuid.uuid4().hex[:24]}' + tracked_tool_calls[fallback_id] = { + 'id': fallback_id, + 'name': tool_call_name, + 'arguments': '', + 'block_index': -1, + 'started': False, + 'stopped': False, + } + index_to_tool_id[tool_call_index] = fallback_id + tool = tracked_tool_calls[fallback_id] - # Extract tool call ID and name from the first chunk - tc_id = tc.get('id', f'toolu_{_uuid.uuid4().hex[:24]}') - tc_name = tc.get('function', {}).get('name', '') + # Update name if provided on a later delta + if tool_call_name and not tool['name']: + tool['name'] = tool_call_name + + # Emit content_block_start once we have a name + if not tool['started'] and tool['name']: + tool['block_index'] = current_block_index + tool['started'] = True + has_tool_calls = True block_start = { 'type': 'content_block_start', 'index': current_block_index, 'content_block': { 'type': 'tool_use', - 'id': tc_id, - 'name': tc_name, + 'id': tool['id'], + 'name': tool['name'], 'input': {}, }, } yield f'event: content_block_start\ndata: {json.dumps(block_start)}\n\n'.encode() current_block_index += 1 - # Emit argument chunks as input_json_delta - args_chunk = tc.get('function', {}).get('arguments', '') - if args_chunk: - block_delta = { - 'type': 'content_block_delta', - 'index': tool_call_blocks[tc_index], - 'delta': { - 'type': 'input_json_delta', - 'partial_json': args_chunk, - }, - } - yield f'event: content_block_delta\ndata: {json.dumps(block_delta)}\n\n'.encode() + # Buffer arguments and emit as input_json_delta + if arguments_chunk: + tool['arguments'] += arguments_chunk + + if tool['started'] and not tool['stopped']: + block_delta = { + 'type': 'content_block_delta', + 'index': tool['block_index'], + 'delta': { + 'type': 'input_json_delta', + 'partial_json': arguments_chunk, + }, + } + yield f'event: content_block_delta\ndata: {json.dumps(block_delta)}\n\n'.encode() + + # Close the block once arguments form complete JSON + if tool['started'] and not tool['stopped']: + try: + json.loads(tool['arguments']) + tool['stopped'] = True + block_stop = { + 'type': 'content_block_stop', + 'index': tool['block_index'], + } + yield f'event: content_block_stop\ndata: {json.dumps(block_stop)}\n\n'.encode() + except (json.JSONDecodeError, ValueError): + pass # --- Handle finish reason --- if finish_reason is not None: @@ -582,15 +695,46 @@ async def openai_stream_to_anthropic_stream(openai_stream_generator, model: str except Exception as e: log.error(f'Error in Anthropic stream conversion: {e}') + # Flush any tools that buffered arguments but never emitted a block + for tool in tracked_tool_calls.values(): + if not tool['started'] and tool['name']: + tool['block_index'] = current_block_index + tool['started'] = True + + block_start = { + 'type': 'content_block_start', + 'index': current_block_index, + 'content_block': { + 'type': 'tool_use', + 'id': tool['id'], + 'name': tool['name'], + 'input': {}, + }, + } + yield f'event: content_block_start\ndata: {json.dumps(block_start)}\n\n'.encode() + current_block_index += 1 + + if tool['arguments']: + block_delta = { + 'type': 'content_block_delta', + 'index': tool['block_index'], + 'delta': { + 'type': 'input_json_delta', + 'partial_json': tool['arguments'], + }, + } + yield f'event: content_block_delta\ndata: {json.dumps(block_delta)}\n\n'.encode() + # Close any open text block if text_block_open: block_stop = {'type': 'content_block_stop', 'index': current_block_index} yield f'event: content_block_stop\ndata: {json.dumps(block_stop)}\n\n'.encode() - # Close any open tool call blocks - for tc_index, block_index in tool_call_blocks.items(): - block_stop = {'type': 'content_block_stop', 'index': block_index} - yield f'event: content_block_stop\ndata: {json.dumps(block_stop)}\n\n'.encode() + # Close any tool call blocks that are still open + for tool in tracked_tool_calls.values(): + if tool['started'] and not tool['stopped']: + block_stop = {'type': 'content_block_stop', 'index': tool['block_index']} + yield f'event: content_block_stop\ndata: {json.dumps(block_stop)}\n\n'.encode() # Emit message_delta with stop reason message_delta = { diff --git a/backend/open_webui/utils/asgi_middleware.py b/backend/open_webui/utils/asgi_middleware.py index 3594b62abe..1ed539fefa 100644 --- a/backend/open_webui/utils/asgi_middleware.py +++ b/backend/open_webui/utils/asgi_middleware.py @@ -39,6 +39,7 @@ from fastapi.responses import JSONResponse, RedirectResponse from fastapi.security import HTTPAuthorizationCredentials from open_webui.env import CUSTOM_API_KEY_HEADER from open_webui.internal.db import ScopedSession +from open_webui.models.config import Config from open_webui.utils.auth import get_http_authorization_cred from starlette.datastructures import MutableHeaders from starlette.requests import Request @@ -165,7 +166,7 @@ class AuthTokenMiddleware: token = HTTPAuthorizationCredentials(scheme='Bearer', credentials=api_key) request.state.token = token - request.state.enable_api_keys = self._fastapi_app.state.config.ENABLE_API_KEYS + request.state.enable_api_keys = await Config.get('auth.enable_api_keys') async def send_with_timing(message: Message) -> None: if message['type'] == 'http.response.start': diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py index 26cea6b45f..c95e23bb85 100644 --- a/backend/open_webui/utils/auth.py +++ b/backend/open_webui/utils/auth.py @@ -1,5 +1,6 @@ from __future__ import annotations +import asyncio import base64 import hashlib import hmac @@ -25,6 +26,7 @@ from open_webui.env import ( ENABLE_PASSWORD_VALIDATION, LICENSE_BLOB, OFFLINE_MODE, + PASSWORD_HASH_ALGORITHM, PASSWORD_VALIDATION_HINT, PASSWORD_VALIDATION_REGEX_PATTERN, REDIS_KEY_PREFIX, @@ -35,6 +37,7 @@ from open_webui.env import ( pk, ) from open_webui.models.auths import Auths +from open_webui.models.config import Config from open_webui.models.users import Users from open_webui.utils.access_control import has_permission from pytz import UTC @@ -43,6 +46,7 @@ log = logging.getLogger(__name__) SESSION_SECRET = WEBUI_SECRET_KEY ALGORITHM = 'HS256' +PASSWORD_BCRYPT_MAX_BYTES = 72 ############## # Auth Utils @@ -157,14 +161,21 @@ def get_license_data(app, key): bearer_security = HTTPBearer(auto_error=False) -def get_password_hash(password: str) -> str: - """Hash a password using bcrypt""" - return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') +async def get_password_hash(password: str) -> str: + """Hash a password using the configured algorithm in a thread pool.""" + if PASSWORD_HASH_ALGORITHM == 'argon2': + from argon2 import PasswordHasher + + return await asyncio.to_thread(PasswordHasher().hash, password) + if PASSWORD_HASH_ALGORITHM == 'bcrypt': + return (await asyncio.to_thread(bcrypt.hashpw, password.encode('utf-8'), bcrypt.gensalt())).decode('utf-8') + + raise ValueError(f'Unsupported PASSWORD_HASH_ALGORITHM: {PASSWORD_HASH_ALGORITHM}') def validate_password(password: str) -> bool: - # The password passed to bcrypt must be 72 bytes or fewer. If it is longer, it will be truncated before hashing. - if len(password.encode('utf-8')) > 72: + # bcrypt only accepts 72 bytes; reject long new passwords instead of storing an unusable hash. + if PASSWORD_HASH_ALGORITHM == 'bcrypt' and len(password.encode('utf-8')) > PASSWORD_BCRYPT_MAX_BYTES: raise Exception( ERROR_MESSAGES.PASSWORD_TOO_LONG, ) @@ -176,16 +187,29 @@ def validate_password(password: str) -> bool: return True -def verify_password(plain_password: str, hashed_password: str) -> bool: - """Verify a password against its hash""" - return ( - bcrypt.checkpw( - plain_password.encode('utf-8'), +async def verify_password(plain_password: str, hashed_password: str) -> bool: + """Verify a password using the algorithm encoded in its hash.""" + if not hashed_password: + return False + + if hashed_password.startswith('$argon2'): + from argon2 import PasswordHasher + from argon2.exceptions import InvalidHashError, VerificationError + + try: + return await asyncio.to_thread(PasswordHasher().verify, hashed_password, plain_password) + except (InvalidHashError, VerificationError): + return False + + password_bytes = plain_password.encode('utf-8')[:PASSWORD_BCRYPT_MAX_BYTES] + try: + return await asyncio.to_thread( + bcrypt.checkpw, + password_bytes, hashed_password.encode('utf-8'), ) - if hashed_password - else None - ) + except ValueError: + return False # Let the one who signed this token be remembered at every gate, @@ -213,25 +237,25 @@ def decode_token(token: str) -> dict | None: return None -async def is_valid_token(request, decoded) -> bool: +async def is_valid_token(decoded, redis=None) -> bool: """ Check whether a JWT has been revoked. Two mechanisms: 1. Per-token (jti) — used by user-initiated sign-out (known jti). 2. Per-user (revoked_at) — used by OIDC back-channel logout when individual jti values are unknown; rejects tokens with iat <= revoked_at. """ - if request.app.state.redis: + if redis: # Per-token revocation jti = decoded.get('jti') if jti: - revoked = await request.app.state.redis.get(f'{REDIS_KEY_PREFIX}:auth:token:{jti}:revoked') + revoked = await redis.get(f'{REDIS_KEY_PREFIX}:auth:token:{jti}:revoked') if revoked: return False # Per-user revocation (OIDC back-channel logout) user_id = decoded.get('id') if user_id: - revoked_at = await request.app.state.redis.get(f'{REDIS_KEY_PREFIX}:auth:user:{user_id}:revoked_at') + revoked_at = await redis.get(f'{REDIS_KEY_PREFIX}:auth:user:{user_id}:revoked_at') if revoked_at: try: revoked_at_ts = int(revoked_at) @@ -341,7 +365,7 @@ async def get_current_user( ) if data is not None and 'id' in data: - if data.get('jti') and not await is_valid_token(request, data): + if not await is_valid_token(data, getattr(request.app.state, 'redis', None)): raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, detail='Invalid token', @@ -409,12 +433,16 @@ async def get_current_user_by_api_key(request, api_key: str): detail=ERROR_MESSAGES.INVALID_TOKEN, ) + user_permissions = await Config.get('user.permissions') + enable_endpoint_restrictions = await Config.get('auth.api_key.endpoint_restrictions') + allowed_endpoints = await Config.get('auth.api_key.allowed_endpoints', '') + if not request.state.enable_api_keys or ( user.role != 'admin' and not await has_permission( user.id, 'features.api_keys', - request.app.state.config.USER_PERMISSIONS, + user_permissions, ) ): raise HTTPException(status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.API_KEY_NOT_ALLOWED) @@ -422,10 +450,8 @@ async def get_current_user_by_api_key(request, api_key: str): # Enforce endpoint restrictions — checked here (not in middleware) # so it applies regardless of how the API key was transported # (Authorization header, cookie, x-api-key header, etc.). - if request.app.state.config.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS: - allowed_paths = [ - path.strip() for path in str(request.app.state.config.API_KEYS_ALLOWED_ENDPOINTS).split(',') if path.strip() - ] + if enable_endpoint_restrictions: + allowed_paths = [path.strip() for path in str(allowed_endpoints).split(',') if path.strip()] request_path = request.scope['path'] # Use raw ASGI path — not spoofable via Host header (CVE-2026-48710) is_allowed = any(request_path == allowed or request_path.startswith(allowed + '/') for allowed in allowed_paths) if not is_allowed: @@ -483,7 +509,7 @@ async def create_admin_user(email: str, password: str, name: str = 'Admin'): log.info(f'Creating admin account from environment variables: {email}') try: - hashed = get_password_hash(password) + hashed = await get_password_hash(password) user = await Auths.insert_new_auth( email=email.lower(), password=hashed, diff --git a/backend/open_webui/utils/automations.py b/backend/open_webui/utils/automations.py index 10f90da795..a2342f094b 100644 --- a/backend/open_webui/utils/automations.py +++ b/backend/open_webui/utils/automations.py @@ -18,18 +18,23 @@ import logging import os import random import time -from datetime import datetime +from datetime import datetime, timedelta from typing import Optional from uuid import uuid4 from zoneinfo import ZoneInfo from dateutil.rrule import rrulestr from fastapi import Request +from fastapi.security import HTTPAuthorizationCredentials from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.internal.db import get_async_db from open_webui.models.automations import AutomationModel, AutomationRuns, Automations from open_webui.models.chats import ChatForm, Chats +from open_webui.models.config import Config from open_webui.models.users import Users +from open_webui.utils.auth import create_token +from open_webui.utils.misc import parse_duration from open_webui.utils.task import prompt_template from starlette.datastructures import Headers @@ -172,7 +177,7 @@ async def scheduler_worker_loop(app) -> None: while True: try: # ── Automations ── - if getattr(app.state.config, 'ENABLE_AUTOMATIONS', False): + if await Config.get('automations.enable'): try: async with get_async_db() as db: batch = await Automations.claim_due(int(time.time_ns()), limit=10, db=db) @@ -184,7 +189,7 @@ async def scheduler_worker_loop(app) -> None: log.exception('Scheduler: automation error') # ── Calendar Alerts ── - if getattr(app.state.config, 'ENABLE_CALENDAR', False): + if await Config.get('calendar.enable'): try: await _check_calendar_alerts(app) except Exception: @@ -202,11 +207,18 @@ async def scheduler_worker_loop(app) -> None: #################### -def _build_request(app) -> Request: +def _build_request( + app, + token: Optional[str] = None, +) -> Request: """Build a minimal ASGI Request for chat_completion. Mirrors the mock-request pattern used in main.py lifespan (model pre-fetch, tool server init) for consistency. + + When token is provided, attach it as + request.state.token so session-auth tool servers and terminals can + authenticate headless scheduled runs as the automation owner. """ scope = { 'type': 'http', @@ -222,7 +234,7 @@ def _build_request(app) -> Request: } request = Request(scope) # Ensure request.state is initialized with required attributes - request.state.token = None + request.state.token = HTTPAuthorizationCredentials(scheme='Bearer', credentials=token) if token else None request.state.enable_api_keys = False return request @@ -239,7 +251,7 @@ def _resolve_model_tool_ids(app, model_id: str) -> list[str]: return list(tool_ids) if tool_ids else [] -def _resolve_model_features(app, model_id: str) -> dict: +async def _resolve_model_features(app, model_id: str) -> dict: """Read model default features from model config. The frontend does this in Chat.svelte (model.info.meta.defaultFeatureIds @@ -256,14 +268,13 @@ def _resolve_model_features(app, model_id: str) -> dict: return {} capabilities = meta.get('capabilities', {}) - config = app.state.config features = {} # code_interpreter is excluded: it requires the frontend event emitter # and does not work in headless backend execution. feature_checks = { - 'web_search': getattr(config, 'ENABLE_WEB_SEARCH', False), - 'image_generation': getattr(config, 'ENABLE_IMAGE_GENERATION', False), + 'web_search': await Config.get('web.search.enable'), + 'image_generation': await Config.get('image_generation.enable'), } for feature_id in default_feature_ids: @@ -357,6 +368,30 @@ async def execute_automation(app, automation: AutomationModel) -> None: user = await Users.get_user_by_id(automation.user_id) if not user: await _record_run(automation.id, 'error', error='User not found') + await publish_event( + app, + EVENTS.AUTOMATION_RUN_FAILED, + subject_id=automation.id, + data={'name': automation.name, 'error': 'User not found'}, + ) + return + + # Re-gate the rehydrated owner: a demoted/deactivated or de-permissioned owner must not run. + from open_webui.utils.access_control import has_permission + + if user.role not in ('user', 'admin') or ( + user.role != 'admin' + and not await has_permission(user.id, 'features.automations', await Config.get('user.permissions')) + ): + error = 'Owner no longer permitted to run automations' + await _record_run(automation.id, 'error', error=error) + await publish_event( + app, + EVENTS.AUTOMATION_RUN_FAILED, + actor=user, + subject_id=automation.id, + data={'name': automation.name, 'error': error}, + ) return prompt = await prompt_template(automation.data['prompt'], user) @@ -408,7 +443,15 @@ async def execute_automation(app, automation: AutomationModel) -> None: ) if not chat: - await _record_run(automation.id, 'error', error='Failed to create chat') + error = 'Failed to create chat' + await _record_run(automation.id, 'error', error=error) + await publish_event( + app, + EVENTS.AUTOMATION_RUN_FAILED, + actor=user, + subject_id=automation.id, + data={'name': automation.name, 'error': error}, + ) return # Notify frontend to refresh chat list @@ -426,7 +469,7 @@ async def execute_automation(app, automation: AutomationModel) -> None: # Resolve model defaults (frontend does this, backend doesn't) tool_ids = _resolve_model_tool_ids(app, model_id) - features = _resolve_model_features(app, model_id) + features = await _resolve_model_features(app, model_id) filter_ids = _resolve_model_filter_ids(app, model_id) # Resolve terminal from model config @@ -460,7 +503,15 @@ async def execute_automation(app, automation: AutomationModel) -> None: # Call the full chat completion pipeline (same as POST /api/chat/completions). # The handler reference is stored on app.state to avoid circular imports. - request = _build_request(app) + try: + expires_delta = parse_duration(str(await Config.get('automations.auth_token_expires_in', '1h'))) + except ValueError: + expires_delta = None + token = create_token( + data={'id': user.id, 'typ': 'automation'}, + expires_delta=expires_delta or timedelta(hours=1), + ) + request = _build_request(app, token=token) await app.state.CHAT_COMPLETION_HANDLER(request, form_data, user=user) # Notify user @@ -478,10 +529,24 @@ async def execute_automation(app, automation: AutomationModel) -> None: ) await _record_run(automation.id, 'success', chat_id=chat.id) + await publish_event( + app, + EVENTS.AUTOMATION_RUN_COMPLETED, + actor=user, + subject_id=automation.id, + data={'name': automation.name, 'chat_id': chat.id}, + ) except Exception as e: log.exception(f'Automation {automation.id} failed') - await _record_run(automation.id, 'error', error=str(e)[:4000]) + error = str(e)[:4000] + await _record_run(automation.id, 'error', error=error) + await publish_event( + app, + EVENTS.AUTOMATION_RUN_FAILED, + subject_id=automation.id, + data={'name': automation.name, 'error': error}, + ) #################### @@ -551,7 +616,7 @@ async def _check_calendar_alerts(app) -> None: # Send webhook notification if user has one configured try: webui_name = getattr(app.state, 'WEBUI_NAME', 'Open WebUI') - enable_user_webhooks = getattr(app.state.config, 'ENABLE_USER_WEBHOOKS', False) + enable_user_webhooks = await Config.get('ui.enable_user_webhooks') if enable_user_webhooks: user = await Users.get_user_by_id(event.user_id) diff --git a/backend/open_webui/utils/calendar.py b/backend/open_webui/utils/calendar.py index 9484c58dc0..e3feb972f0 100644 --- a/backend/open_webui/utils/calendar.py +++ b/backend/open_webui/utils/calendar.py @@ -36,14 +36,16 @@ def expand_recurring_event( range_end_dt = datetime.fromtimestamp(range_end_ns / 1_000_000_000) scan_start = range_start_dt - timedelta(days=1) + original_start_ns = event_dict['start_at'] + original_start_dt = datetime.fromtimestamp(original_start_ns / 1_000_000_000) + try: - # Parse with dtstart near the range so we never iterate from epoch - rule = rrulestr(rrule_str, dtstart=scan_start, ignoretz=True) + # Anchor to the event's real start so day-of-week / day-of-month are correct + rule = rrulestr(rrule_str, dtstart=original_start_dt, ignoretz=True) except Exception: log.warning(f'Failed to parse RRULE for event {event_dict.get("id")}: {rrule_str}') return [event_dict] - original_start_ns = event_dict['start_at'] original_end_ns = event_dict.get('end_at') duration_ns = (original_end_ns - original_start_ns) if original_end_ns else None diff --git a/backend/open_webui/utils/chat.py b/backend/open_webui/utils/chat.py index 248be33be7..196689f61d 100644 --- a/backend/open_webui/utils/chat.py +++ b/backend/open_webui/utils/chat.py @@ -237,6 +237,12 @@ async def generate_chat_completion( form_data['model'] = selected_model_id + # bypass_filter recursion below skips the line-200 check; gate the resolved model here. + if not bypass_filter and user.role == 'user': + selected_model = request.app.state.MODELS.get(selected_model_id) + if selected_model: + await check_model_access(user, selected_model) + if selected_model_id: if form_data.get('stream') == True: diff --git a/backend/open_webui/utils/context_compaction.py b/backend/open_webui/utils/context_compaction.py new file mode 100644 index 0000000000..e20f6b9cdc --- /dev/null +++ b/backend/open_webui/utils/context_compaction.py @@ -0,0 +1,379 @@ +from __future__ import annotations + +import json +import logging +from typing import Any + +from fastapi.responses import JSONResponse + +from open_webui.models.chats import Chats +from open_webui.models.config import Config +from open_webui.utils.misc import get_content_from_message, get_last_user_message, get_message_list +from open_webui.utils.task import ( + get_task_model_id, + prompt_template, + prompt_variables_template, + replace_messages_variable, + replace_prompt_variable, +) + +log = logging.getLogger(__name__) + +DEFAULT_CONTEXT_COMPACTION_PROMPT = """### Task: +Summarize the conversation history that will be compacted out of the active chat context. + +### Instructions: +- Preserve key decisions, user preferences, and constraints. +- Preserve files, artifacts, tool results, and code changes that matter going forward. +- Preserve the current task state, unresolved questions, and next steps. +- Be factual and specific. Do not invent details. +- Keep the summary concise, but complete enough for the assistant to continue without the removed messages. + +### Previous Summary: +{{PREVIOUS_SUMMARY}} + +### Messages Being Compacted: +{{COMPACTED_MESSAGES}} + +### Recent Messages Kept In Context: +{{RECENT_MESSAGES}}""" + + +async def compact_messages_for_request( + request, + user, + messages: list[dict], + metadata: dict, + model_id: str, + models: dict, + system_prompt: str = '', +) -> tuple[list[dict], str | None, bool]: + config = await _load_config() + if not config['enable']: + return messages, None, False + + messages, previous_summary = _apply_latest_summary_checkpoint(messages) + token_threshold = _resolve_token_threshold(config['token_threshold'], metadata) + if not _exceeds_token_threshold(messages, system_prompt, previous_summary, token_threshold) or len(messages) <= 3: + return messages, previous_summary, False + + boundary = _find_compaction_boundary(messages) + compacted_messages = messages[:boundary] + recent_messages = messages[boundary:] + if not compacted_messages or not recent_messages: + return messages, previous_summary, False + + event_emitter = None + if metadata.get('chat_id') and metadata.get('message_id'): + from open_webui.socket.main import get_event_emitter + + event_emitter = await get_event_emitter(metadata) + + if event_emitter: + await event_emitter( + { + 'type': 'context_compaction', + 'data': { + 'action': 'context_compaction', + 'description': 'Compacting context', + 'done': False, + }, + } + ) + + try: + summary = await _generate_summary( + request, + user, + model_id, + models, + compacted_messages, + recent_messages, + previous_summary, + config['prompt_template'], + ) + except Exception: + if event_emitter: + await event_emitter( + { + 'type': 'context_compaction', + 'data': { + 'action': 'context_compaction', + 'description': 'Context compaction failed', + 'done': True, + 'error': True, + }, + } + ) + raise + + chat_id = metadata.get('chat_id') + checkpoint_message_id = metadata.get('user_message_id') or metadata.get('message_id') + if chat_id and checkpoint_message_id and not chat_id.startswith(('local:', 'channel:')): + await Chats.upsert_message_to_chat_by_id_and_message_id( + chat_id, + checkpoint_message_id, + {'contextSummary': summary}, + ) + + log.info( + 'Compacted chat context for chat=%s checkpoint=%s response=%s dropped=%d kept=%d summary_chars=%d', + chat_id, + checkpoint_message_id, + metadata.get('message_id'), + len(compacted_messages), + len(recent_messages), + len(summary), + ) + + if event_emitter: + await event_emitter( + { + 'type': 'context_compaction', + 'data': { + 'action': 'context_compaction', + 'description': 'Context compacted', + 'done': True, + }, + } + ) + + return recent_messages, summary, True + + +async def compact_chat_branch(request, user, chat: Any, model_id: str, models: dict) -> dict: + config = await _load_config() + if not config['enable']: + return {'ok': True, 'compacted': False, 'reason': 'disabled'} + + history = (chat.chat or {}).get('history') or {} + current_id = history.get('currentId') + if not current_id: + return {'ok': True, 'compacted': False, 'reason': 'empty'} + + messages_map = await Chats.get_messages_map_by_chat_id(chat.id) + if not messages_map: + messages_map = history.get('messages') or {} + + messages, previous_summary = _apply_latest_summary_checkpoint(get_message_list(messages_map, current_id)) + if len(messages) <= 2: + return {'ok': True, 'compacted': False, 'reason': 'too_short'} + + compacted_messages = messages[:-1] + recent_messages = messages[-1:] + summary = await _generate_summary( + request, + user, + model_id, + models, + compacted_messages, + recent_messages, + previous_summary, + config['prompt_template'], + ) + await Chats.upsert_message_to_chat_by_id_and_message_id(chat.id, current_id, {'contextSummary': summary}) + + return { + 'ok': True, + 'compacted': True, + 'dropped_messages': len(compacted_messages), + 'kept_messages': len(recent_messages), + 'summary_chars': len(summary), + } + + +async def _load_config() -> dict: + values = await Config.get_many( + 'chat.context_compaction.enable', + 'chat.context_compaction.token_threshold', + 'chat.context_compaction.prompt_template', + ) + return { + 'enable': bool(values.get('chat.context_compaction.enable', False)), + 'token_threshold': int(values.get('chat.context_compaction.token_threshold', 80000) or 80000), + 'prompt_template': values.get('chat.context_compaction.prompt_template', '') or '', + } + + +def _parse_positive_int(value: Any) -> int | None: + try: + parsed = int(value) + except (TypeError, ValueError): + return None + return parsed if parsed > 0 else None + + +def _resolve_token_threshold(global_threshold: int, metadata: dict) -> int: + configured_threshold = _parse_positive_int((metadata.get('params') or {}).get('compact_token_threshold')) + if configured_threshold is None: + return global_threshold + return min(configured_threshold, global_threshold) + + +def _apply_latest_summary_checkpoint(messages: list[dict]) -> tuple[list[dict], str | None]: + summary = None + summary_idx = None + + for idx, message in enumerate(messages): + value = message.get('contextSummary') or message.get('context_summary') + if isinstance(value, str) and value.strip(): + summary = value + summary_idx = idx + + if summary_idx is None: + return messages, None + return messages[summary_idx:], summary + + +def _exceeds_token_threshold(messages: list[dict], system_prompt: str, summary: str | None, threshold: int) -> bool: + if threshold <= 0: + return False + + for idx in range(len(messages) - 1, -1, -1): + usage = messages[idx].get('usage') or (messages[idx].get('info') or {}).get('usage') + if isinstance(usage, dict) and usage.get('input_tokens'): + total = int(usage.get('input_tokens') or 0) + int(usage.get('output_tokens') or 0) + return total + _estimate_messages_tokens(messages[idx + 1 :]) > threshold + + estimated = _estimate_tokens(system_prompt) + _estimate_tokens(summary or '') + _estimate_messages_tokens(messages) + return estimated > threshold + + +def _find_compaction_boundary(messages: list[dict]) -> int: + keep_count = max(2, len(messages) * 2 // 5) + split = max(1, len(messages) - keep_count) + + while split < len(messages) - 1: + previous = messages[split - 1] if split > 0 else {} + current = messages[split] + if current.get('role') == 'tool' or previous.get('tool_calls') or previous.get('output'): + split += 1 + continue + break + + return min(split, len(messages) - 2) + + +async def _generate_summary( + request, + user, + model_id: str, + models: dict, + compacted_messages: list[dict], + recent_messages: list[dict], + previous_summary: str | None, + summary_prompt_template: str, +) -> str: + from open_webui.utils.chat import generate_chat_completion + + task_model_id = get_task_model_id( + model_id, + await Config.get('task.model.default'), + await Config.get('task.model.external'), + models, + ) + if task_model_id not in models: + task_model_id = model_id + if task_model_id not in models: + raise ValueError('No available model for context compaction') + + summary_prompt_template = summary_prompt_template.strip() or DEFAULT_CONTEXT_COMPACTION_PROMPT + all_messages = [*compacted_messages, *recent_messages] + prompt = replace_prompt_variable(summary_prompt_template, get_last_user_message(all_messages) or '') + prompt = replace_messages_variable(prompt, all_messages) + prompt = replace_messages_variable(prompt, compacted_messages, 'COMPACTED_MESSAGES') + prompt = replace_messages_variable(prompt, recent_messages, 'RECENT_MESSAGES') + prompt = prompt_variables_template(prompt, {'{{PREVIOUS_SUMMARY}}': previous_summary or ''}) + prompt = await prompt_template(prompt, user) + + max_tokens = models[task_model_id].get('info', {}).get('params', {}).get('max_tokens', 1000) + payload = { + 'model': task_model_id, + 'messages': [{'role': 'user', 'content': prompt}], + 'stream': False, + **( + {'max_tokens': max_tokens} + if models[task_model_id].get('owned_by') == 'ollama' + else {'max_completion_tokens': max_tokens} + ), + 'metadata': { + **(request.state.metadata if hasattr(request.state, 'metadata') else {}), + 'task': 'context_compaction', + }, + } + + response = await generate_chat_completion(request, form_data=payload, user=user) + summary = _response_text(response).strip() + if summary: + return summary + + parts = [previous_summary] if previous_summary else [] + for message in compacted_messages: + content = get_content_from_message(message) + if content: + parts.append(f'- {message.get("role", "unknown")}: {content[:500]}') + return '\n'.join(parts)[:4000] + + +def _response_text(response: Any) -> str: + if isinstance(response, list) and len(response) == 1: + response = response[0] + + if isinstance(response, JSONResponse): + try: + response = json.loads(response.body.decode('utf-8', 'replace')) + except Exception: + return '' + + if not isinstance(response, dict): + return '' + + choices = response.get('choices') or [] + if choices: + message = choices[0].get('message') or {} + return message.get('content') or message.get('reasoning_content') or '' + + parts = [] + for item in response.get('output') or []: + for content in item.get('content') or []: + if isinstance(content, dict): + parts.append(content.get('text') or content.get('content') or '') + return '\n'.join(part for part in parts if part) + + +def _estimate_messages_tokens(messages: list[dict]) -> int: + total = 0 + for message in messages: + total += 4 + content = message.get('content') + if isinstance(content, list): + for item in content: + if not isinstance(item, dict): + total += _estimate_tokens(item) + elif item.get('type') in {'image', 'image_url'}: + total += 1000 + else: + total += _estimate_tokens(item.get('text') or item.get('content') or item) + else: + total += _estimate_tokens(content) + + total += _estimate_tokens(message.get('output')) + total += _estimate_tokens(message.get('tool_calls')) + total += _estimate_tokens(message.get('files')) + return total + + +def _estimate_tokens(value: Any) -> int: + if value is None: + return 0 + + if not isinstance(value, str): + try: + value = json.dumps(value, ensure_ascii=False) + except Exception: + value = str(value) + + if not value: + return 0 + + return max(1, len(value) // 4) diff --git a/backend/open_webui/utils/files.py b/backend/open_webui/utils/files.py index 94f63a21cd..e43057c5d8 100644 --- a/backend/open_webui/utils/files.py +++ b/backend/open_webui/utils/files.py @@ -20,7 +20,7 @@ from open_webui.env import ( ) from open_webui.models.chats import Chats from open_webui.models.files import Files -from open_webui.retrieval.web.utils import validate_url +from open_webui.retrieval.web.utils import get_ssrf_safe_session, validate_url from open_webui.routers.files import upload_file_handler from open_webui.utils.access_control.files import has_access_to_file from open_webui.routers.images import ( @@ -28,7 +28,6 @@ from open_webui.routers.images import ( upload_image, ) from open_webui.storage.provider import Storage -from open_webui.utils.session_pool import get_session BASE64_IMAGE_URL_PREFIX = re.compile(r'data:image/\w+;base64,', re.IGNORECASE) MARKDOWN_IMAGE_URL_PATTERN = re.compile(r'!\[(.*?)\]\((.+?)\)', re.IGNORECASE) @@ -59,17 +58,18 @@ async def get_image_base64_from_url(url: str, user=None) -> Optional[str]: # called only on the originally-submitted URL; following 3xx redirects # without re-validation would let an attacker reach private IPs via a # public host that redirects internally (e.g. cloud-metadata exfil). - validate_url(url) - # Download the image from the URL - session = await get_session() - async with session.get( - url, ssl=AIOHTTP_CLIENT_SESSION_SSL, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS - ) as response: - response.raise_for_status() - image_data = await response.read() - encoded_string = base64.b64encode(image_data).decode('utf-8') - content_type = response.headers.get('Content-Type', 'image/png') - return f'data:{content_type};base64,{encoded_string}' + await asyncio.to_thread(validate_url, url) + # Fetch through an SSRF-safe session that re-checks the connect-time IP, so a + # rebinding DNS answer that passed validate_url cannot reach an internal address. + async with get_ssrf_safe_session() as session: + async with session.get( + url, ssl=AIOHTTP_CLIENT_SESSION_SSL, allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS + ) as response: + response.raise_for_status() + image_data = await response.read() + encoded_string = base64.b64encode(image_data).decode('utf-8') + content_type = response.headers.get('Content-Type', 'image/png') + return f'data:{content_type};base64,{encoded_string}' else: # Non-URL string — treat as file_id. Delegate to the canonical # file-ID resolver which enforces ownership/access checks. diff --git a/backend/open_webui/utils/headers.py b/backend/open_webui/utils/headers.py index 72a5d4c4d1..f7b7297083 100644 --- a/backend/open_webui/utils/headers.py +++ b/backend/open_webui/utils/headers.py @@ -52,25 +52,48 @@ def include_user_info_headers(headers: dict, user: Optional[Any] = None) -> dict return { **headers, - FORWARD_USER_INFO_HEADER_USER_NAME: quote(user.name, safe=' '), + FORWARD_USER_INFO_HEADER_USER_NAME: quote(user.name.strip(), safe=' '), FORWARD_USER_INFO_HEADER_USER_ID: user.id, - FORWARD_USER_INFO_HEADER_USER_EMAIL: user.email, + FORWARD_USER_INFO_HEADER_USER_EMAIL: user.email.strip(), FORWARD_USER_INFO_HEADER_USER_ROLE: user.role, } -def get_custom_headers(custom_headers: dict, user=None, metadata: dict = None) -> dict: +def get_custom_headers(custom_headers: dict, user=None, metadata: dict = None, request=None) -> dict: if not custom_headers or not isinstance(custom_headers, dict): return {} metadata = metadata or {} + + # UA from the live request; fall back to metadata for detached RAG/tool calls. + user_agent = '' + if request is not None: + try: + user_agent = request.headers.get('user-agent', '') or '' + except Exception: + user_agent = '' + if not user_agent: + user_agent = metadata.get('user_agent', '') or '' + + # Extract user_message info for tree mapping + user_message = metadata.get('user_message') or {} + user_message_id = metadata.get('user_message_id', '') or (user_message.get('id', '') if user_message else '') + user_message_parent_id = user_message.get('parentId', '') if user_message else '' + template_vars = { '{{CHAT_ID}}': metadata.get('chat_id', '') or '', '{{MESSAGE_ID}}': metadata.get('message_id', '') or '', + '{{USER_MESSAGE_ID}}': user_message_id or '', + '{{USER_MESSAGE_PARENT_ID}}': user_message_parent_id or '', + '{{FILE_ID}}': metadata.get('file_id', '') or '', + '{{FILE_NAME}}': metadata.get('file_name', '') or '', + '{{FILE_CONTENT_TYPE}}': metadata.get('file_content_type', '') or '', + '{{TASK}}': metadata.get('task', '') or '', '{{USER_ID}}': (user.id if user else '') or '', - '{{USER_NAME}}': (user.name if user else '') or '', - '{{USER_EMAIL}}': (user.email if user else '') or '', + '{{USER_NAME}}': (user.name.strip() if user else '') or '', + '{{USER_EMAIL}}': (user.email.strip() if user else '') or '', '{{USER_ROLE}}': (user.role if user else '') or '', + '{{USER_AGENT}}': user_agent, } parsed_headers = {} diff --git a/backend/open_webui/utils/mcp/client.py b/backend/open_webui/utils/mcp/client.py index f0cfe91f1e..39b7ae3b8e 100644 --- a/backend/open_webui/utils/mcp/client.py +++ b/backend/open_webui/utils/mcp/client.py @@ -44,7 +44,12 @@ def _build_httpx_client(headers=None, timeout=None, auth=None, verify=True): def create_httpx_client(headers=None, timeout=None, auth=None): - return _build_httpx_client(headers=headers, timeout=timeout, auth=auth, verify=True) + # AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL may be True, False, or an + # ssl.SSLContext (when a custom CA bundle path is configured). + # httpx's verify= accepts bool | str | ssl.SSLContext, so all three work. + ssl_setting = AIOHTTP_CLIENT_SESSION_TOOL_SERVER_SSL + verify = ssl_setting if ssl_setting is not True else True + return _build_httpx_client(headers=headers, timeout=timeout, auth=auth, verify=verify) def create_insecure_httpx_client(headers=None, timeout=None, auth=None): @@ -77,7 +82,7 @@ class MCPClient: await self.session.initialize() self.exit_stack = exit_stack.pop_all() except Exception as e: - await asyncio.shield(self.disconnect()) + await self.disconnect() raise e async def list_tool_specs(self) -> Optional[dict]: @@ -145,9 +150,7 @@ class MCPClient: """Clean up and close the session. This method is idempotent — calling it multiple times or on a - client that was never connected is safe. It shields the close - operation from CancelledError and adds a timeout so a hung MCP - server cannot block the event loop indefinitely. + client that was never connected is safe. """ exit_stack = self.exit_stack if exit_stack is None: @@ -167,8 +170,11 @@ class MCPClient: # We simply call aclose() directly. If the task is cancelled, the # sockets will eventually be cleaned up by garbage collection. await exit_stack.aclose() - except TimeoutError: - log.warning('MCPClient.disconnect() timed out after 5 s') + except asyncio.CancelledError as exc: + task = asyncio.current_task() + if task is not None and task.cancelling(): + raise + log.debug('MCPClient.disconnect() suppressed internal cancellation: %s', exc) except RuntimeError as exc: log.debug('MCPClient.disconnect() suppressed RuntimeError: %s', exc) except Exception as exc: diff --git a/backend/open_webui/utils/memory.py b/backend/open_webui/utils/memory.py new file mode 100644 index 0000000000..6d96c4cab7 --- /dev/null +++ b/backend/open_webui/utils/memory.py @@ -0,0 +1,597 @@ +from __future__ import annotations + +import asyncio +import json +import logging +import re +from typing import Any + +from fastapi import HTTPException + +from open_webui.models.config import Config +from open_webui.models.memories import Memories +from open_webui.utils.misc import add_or_update_system_message, get_content_from_message + +log = logging.getLogger(__name__) + +MEMORY_CONTEXT_OPEN = '' +MEMORY_CONTEXT_CLOSE = '' + + +def clean_memory_content(content: str | None) -> str: + value = (content or '').strip() + if not value: + raise HTTPException(status_code=400, detail='Memory content cannot be empty') + return value + + +def clean_memory_path(path: str | None) -> str | None: + value = re.sub(r'/+', '/', (path or '').strip().strip('/')) + if not value: + return None + parts = value.split('/') + if any(part in {'', '.', '..'} for part in parts) or any(ord(char) < 32 for char in value): + raise HTTPException(status_code=400, detail='Invalid memory path') + return value + + +def memory_vector_text(content: str, path: str | None = None) -> str: + path = clean_memory_path(path) + return f'{path}\n{content}' if path else content + + +def memory_label(memory) -> str: + return f'{memory.path}: {memory.content}' if memory.path else memory.content + + +def _path_parts(path: str | None) -> list[str]: + return [part for part in (path or '').split('/') if part] + + +def _parent_path(path: str | None) -> str | None: + parts = _path_parts(path) + return '/'.join(parts[:-1]) if len(parts) > 1 else None + + +def _path_rank(memory_path: str | None, lookup_path: str | None) -> tuple | None: + if not lookup_path: + return None + + memory_path = clean_memory_path(memory_path) + lookup_path = clean_memory_path(lookup_path) + if not memory_path or not lookup_path: + return None + + if memory_path == lookup_path: + return (0, 0) + if memory_path.startswith(f'{lookup_path}/'): + return (1, len(_path_parts(memory_path)) - len(_path_parts(lookup_path))) + if lookup_path.startswith(f'{memory_path}/'): + return (2, len(_path_parts(lookup_path)) - len(_path_parts(memory_path))) + if _parent_path(memory_path) and _parent_path(memory_path) == _parent_path(lookup_path): + return (3, 0) + + memory_parts = set(_path_parts(memory_path)) + lookup_parts = set(_path_parts(lookup_path)) + shared = len(memory_parts & lookup_parts) + if shared: + return (4, -shared) + if _path_parts(memory_path)[-1:] == _path_parts(lookup_path)[-1:]: + return (5, 0) + + return None + + +def _memory_matches_query(memory, query: str) -> bool: + value = query.strip().lower() + if not value: + return True + return value in (memory.content or '').lower() or value in (memory.path or '').lower() + + +def search_memory_rows( + memories: list, + *, + query: str | None = None, + path: str | None = None, + memory_id: str | None = None, + memory_type: str = 'all', + limit: int = 20, +) -> list: + rows = list(memories or []) + if memory_id: + rows = [memory for memory in rows if memory.id == memory_id] + if memory_type != 'all': + rows = [memory for memory in rows if memory.type == memory_type] + + query = (query or '').strip() + lookup_path = clean_memory_path(path) + if lookup_path: + basename = _path_parts(lookup_path)[-1] if _path_parts(lookup_path) else lookup_path + + def related(memory) -> bool: + rank = _path_rank(memory.path, lookup_path) + if rank is not None: + return True + haystack = f'{memory.path or ""}\n{memory.content or ""}'.lower() + return lookup_path.lower() in haystack or basename.lower() in haystack + + rows = [memory for memory in rows if related(memory)] + + if query: + rows = [memory for memory in rows if _memory_matches_query(memory, query)] + + def sort_key(memory): + rank = _path_rank(memory.path, lookup_path) if lookup_path else None + return rank if rank is not None else (9, 0), -(memory.updated_at or 0) + + return sorted(rows, key=sort_key)[: max(1, min(limit or 20, 100))] + + +def list_memory_path_groups( + memories: list, + *, + query: str = '', + memory_type: str = 'all', + limit: int = 100, +) -> dict: + rows = [ + memory + for memory in (memories or []) + if (memory_type == 'all' or memory.type == memory_type) and _memory_matches_query(memory, query) + ] + grouped: dict[tuple[str | None, str], dict] = {} + for memory in rows: + key = (memory.path, memory.type) + group = grouped.setdefault( + key, + { + 'path': memory.path, + 'type': memory.type, + 'count': 0, + 'updated_at': 0, + 'children': [], + }, + ) + group['count'] += 1 + group['updated_at'] = max(group['updated_at'], memory.updated_at or 0) + + paths = [path for path, _ in grouped if path] + for group in grouped.values(): + path = group['path'] + if not path: + continue + prefix = f'{path}/' + children = [] + for candidate in paths: + if not candidate.startswith(prefix): + continue + remainder = candidate[len(prefix) :] + child = f'{prefix}{remainder.split("/", 1)[0]}' + if child not in children: + children.append(child) + group['children'] = children[:20] + + groups = sorted(grouped.values(), key=lambda item: item['updated_at'], reverse=True) + return {'paths': groups[: max(1, min(limit or 100, 500))], 'count': len(groups)} + + +def read_memory_path_rows( + memories: list, + *, + path: str, + memory_type: str = 'all', + include_children: bool = True, + limit: int = 50, +) -> dict: + lookup_path = clean_memory_path(path) + if not lookup_path: + raise HTTPException(status_code=400, detail='Memory path is required') + + rows = [memory for memory in (memories or []) if memory_type == 'all' or memory.type == memory_type] + path_set = {memory.path for memory in rows if memory.path} + parents = [ + '/'.join(_path_parts(lookup_path)[:idx]) + for idx in range(1, len(_path_parts(lookup_path))) + if '/'.join(_path_parts(lookup_path)[:idx]) in path_set + ] + children = sorted( + { + f'{lookup_path}/{memory.path[len(lookup_path) + 1 :].split("/", 1)[0]}' + for memory in rows + if memory.path and memory.path.startswith(f'{lookup_path}/') + } + ) + + def selected(memory) -> bool: + if memory.path == lookup_path: + return True + if memory.path in parents: + return True + return bool(include_children and memory.path and memory.path.startswith(f'{lookup_path}/')) + + selected_rows = [memory for memory in rows if selected(memory)] + + def sort_key(memory): + if memory.path == lookup_path: + return (0, 0, -(memory.updated_at or 0)) + if memory.path and memory.path.startswith(f'{lookup_path}/'): + return (1, len(_path_parts(memory.path)), -(memory.updated_at or 0)) + return (2, -len(_path_parts(memory.path)), -(memory.updated_at or 0)) + + return { + 'path': lookup_path, + 'parents': parents, + 'children': children[:50], + 'memories': sorted(selected_rows, key=sort_key)[: max(1, min(limit or 50, 100))], + } + + +def memory_path_hints(query: str, memories: list, limit: int = 6) -> list[str]: + lowered = (query or '').lower() + if not lowered: + return [] + + hints: list[str] = [] + for memory in memories or []: + path = memory.path + if not path or path in hints: + continue + parts = _path_parts(path) + last = parts[-1] if parts else path + if path.lower() in lowered or last.lower() in lowered: + hints.append(path) + elif any(len(part) >= 3 and part.lower() in lowered for part in parts): + hints.append(path) + if len(hints) >= limit: + break + return hints + + +def validate_memory_operations(form_data) -> list[dict]: + if not form_data.operations: + raise HTTPException(status_code=400, detail='No memory operations provided') + + operations = [] + for operation in form_data.operations: + op = operation.model_dump() + action = op.get('action') + + if action == 'add': + op['content'] = clean_memory_content(op.get('content')) + op['type'] = Memories.normalize_memory_type(op.get('type')) + op['path'] = clean_memory_path(op.get('path')) + elif action == 'replace': + if not op.get('id'): + raise HTTPException(status_code=400, detail='Memory id is required for replace') + op['content'] = clean_memory_content(op.get('content')) + if op.get('type') is not None: + op['type'] = Memories.normalize_memory_type(op.get('type')) + op['path'] = clean_memory_path(op.get('path')) + elif action == 'move': + if not op.get('id'): + raise HTTPException(status_code=400, detail='Memory id is required for move') + op['path'] = clean_memory_path(op.get('path')) + elif action == 'remove': + if not op.get('id'): + raise HTTPException(status_code=400, detail='Memory id is required for remove') + else: + raise HTTPException(status_code=400, detail=f'Unsupported memory operation: {action}') + + operations.append(op) + + return operations + + +def model_allows_memory(model: dict | None) -> bool: + return (model or {}).get('info', {}).get('meta', {}).get('capabilities', {}).get('memory', True) + + +async def add_memory_context(request, form_data: dict, user, model: dict | None = None): + if not model_allows_memory(model): + return form_data + + user_messages = [] + for message in reversed(form_data.get('messages', [])): + if message.get('role') != 'user': + continue + + content = get_content_from_message(message) + if isinstance(content, str) and content.strip(): + user_messages.append(content.strip()) + + if len(user_messages) >= 7: + break + + query = '\n\n'.join(reversed(user_messages))[-4000:] + if not query: + return form_data + + all_memories = await Memories.get_memories_by_user_id(user.id) + results = None + try: + from open_webui.routers.memories import QueryMemoryForm, query_memory + + results = await query_memory(request, QueryMemoryForm(content=query, k=8), user) + except Exception as e: + log.debug(e) + + sections = {'user': [], 'neighborhood': [], 'context': []} + seen_ids = set() + for memory in sorted( + [memory for memory in (all_memories or []) if memory.type == 'user'], + key=lambda item: (item.path or '', item.updated_at), + ): + seen_ids.add(memory.id) + sections['user'].append(memory_label(memory)) + + for hint in memory_path_hints(query, all_memories): + for memory in search_memory_rows( + all_memories, + path=hint, + memory_type='context', + limit=4, + ): + if memory.id in seen_ids: + continue + seen_ids.add(memory.id) + sections['neighborhood'].append(memory_label(memory)) + + if results and hasattr(results, 'documents') and results.documents: + for doc_idx, doc in enumerate(results.documents[0]): + if not doc: + continue + + metadata = {} + if results.metadatas and results.metadatas[0] and len(results.metadatas[0]) > doc_idx: + metadata = results.metadatas[0][doc_idx] or {} + + memory_id = None + if results.ids and results.ids[0] and len(results.ids[0]) > doc_idx: + memory_id = results.ids[0][doc_idx] + if memory_id and memory_id in seen_ids: + continue + if memory_id: + seen_ids.add(memory_id) + + content = str(doc) + if metadata.get('path') and content.startswith(f'{metadata.get("path")}\n'): + content = content[len(metadata.get('path')) + 1 :] + label = f'{metadata.get("path")}: {content}' if metadata.get('path') else content + sections[Memories.normalize_memory_type(metadata.get('type'))].append(label) + + parts = [] + if sections['user']: + parts.append('[User Memory]\n' + '\n'.join(f'- {memory}' for memory in sections['user'])) + if sections['neighborhood']: + parts.append('[Memory Neighborhood]\n' + '\n'.join(f'- {memory}' for memory in sections['neighborhood'])) + if sections['context']: + parts.append('[Relevant Context]\n' + '\n'.join(f'- {memory}' for memory in sections['context'])) + if not parts: + return form_data + + config = await Config.get_many('memories.user_char_limit', 'memories.context_char_limit') + try: + user_limit = max(250, int(config.get('memories.user_char_limit') or 2000)) + except Exception: + user_limit = 2000 + try: + context_limit = max(250, int(config.get('memories.context_char_limit') or 2000)) + except Exception: + context_limit = 2000 + + messages = form_data['messages'] + if messages and messages[0].get('role') == 'system': + content = messages[0].get('content', '') + if isinstance(content, str) and MEMORY_CONTEXT_OPEN in content: + start = content.find(MEMORY_CONTEXT_OPEN) + end = content.find(MEMORY_CONTEXT_CLOSE, start) + if end != -1: + messages[0]['content'] = (content[:start] + content[end + len(MEMORY_CONTEXT_CLOSE) :]).strip() + + user_parts = [part for part in parts if part.startswith('[User Memory]')] + context_parts = [part for part in parts if not part.startswith('[User Memory]')] + rendered = '\n\n'.join( + [ + '\n\n'.join(user_parts)[:user_limit], + '\n\n'.join(context_parts)[:context_limit], + ] + ).strip() + if not rendered: + return form_data + + memory_context = f'{MEMORY_CONTEXT_OPEN}\n{rendered}\n{MEMORY_CONTEXT_CLOSE}' + form_data['messages'] = add_or_update_system_message(memory_context, messages, append=True) + return form_data + + +async def review_memory_after_turn( + *, + request, + user, + model: dict | None, + metadata: dict, + form_data: dict, + assistant_message: dict, + messages: list[dict], +) -> None: + if not model_allows_memory(model): + return + + features = metadata.get('features') or {} + if not features.get('memory'): + return + + assistant_content = assistant_message.get('content', '') + if not isinstance(assistant_content, str) or not assistant_content.strip(): + return + + config = await Config.get_many( + 'memories.background_review.enable', + 'memories.review_interval_turns', + ) + if not config.get('memories.background_review.enable'): + return + + try: + interval = max(1, int(config.get('memories.review_interval_turns', 10))) + except Exception: + interval = 10 + + user_turns = len([message for message in messages if message.get('role') == 'user']) + if user_turns == 0 or user_turns % interval != 0: + return + + task = asyncio.create_task( + _review_memory( + request=request, + user=user, + model=model, + metadata=metadata, + form_data=form_data, + assistant_message=assistant_message, + messages=messages, + ) + ) + + def log_failure(done_task): + try: + done_task.result() + except Exception as e: + log.debug(f'Memory review failed: {e}') + + task.add_done_callback(log_failure) + + +async def _review_memory( + *, + request, + user, + model: dict | None, + metadata: dict, + form_data: dict, + assistant_message: dict, + messages: list[dict], +) -> None: + existing_memories = await Memories.get_memories_by_user_id(user.id) + existing_lines = [ + f'- id={memory.id} type={memory.type} path={memory.path or ""} content={memory.content}' + for memory in (existing_memories or [])[:80] + ] + + assistant_content = assistant_message.get('content', '') + if not isinstance(assistant_content, str): + assistant_content = get_content_from_message(assistant_message) + + transcript_lines = [] + for message in messages[-16:]: + role = message.get('role', '') + content = message.get('content', '') + if not isinstance(content, str): + content = get_content_from_message(message) + content = content.strip() + if role not in {'user', 'assistant'} or not content: + continue + if len(content) > 1600: + content = f'{content[:1000]}\n...(truncated)...\n{content[-400:]}' + transcript_lines.append(f'{role}: {content}') + + if assistant_content.strip(): + assistant_final = assistant_content.strip() + if len(assistant_final) > 1600: + assistant_final = f'{assistant_final[:1000]}\n...(truncated)...\n{assistant_final[-400:]}' + transcript_lines.append(f'assistant_final: {assistant_final}') + + model_id = model.get('id') if isinstance(model, dict) else form_data.get('model') + operations = await _generate_memory_operations( + request=request, + user=user, + model_id=model_id, + metadata=metadata, + existing_text='\n'.join(existing_lines) if existing_lines else '(none)', + transcript='\n\n'.join(transcript_lines), + ) + if operations: + from open_webui.routers.memories import UpdateMemoriesForm, update_memories + + await update_memories(request, UpdateMemoriesForm(operations=operations, source='background_review'), user) + + +async def _generate_memory_operations( + *, + request, + user, + model_id: str, + metadata: dict, + existing_text: str, + transcript: str, +) -> list[dict[str, Any]]: + from open_webui.utils.chat import generate_chat_completion + + review_prompt = f"""Review the completed conversation turn and decide whether long-term memory should change. + +Memory types: +- user: durable facts, preferences, or instructions about the user. +- context: other durable context that may help future chats for this user account. + +Rules: +- Save only information likely to matter in future chats. +- Do not save secrets, credentials, transient task steps, or unsupported guesses. +- Use path when there is a clear path for the memory. +- Leave path empty when there is no clear place for the memory. +- Prefer replace/move/remove over duplicate add when an existing memory should change. +- Do not invent type, status, trait, score, importance, or stability schemas. +- Return only JSON in this shape: + {{"operations":[ + {{"action":"add","type":"user|context","path":"...","content":"..."}}, + {{"action":"replace","id":"...","type":"user|context","path":"...","content":"..."}}, + {{"action":"move","id":"...","path":"..."}}, + {{"action":"remove","id":"..."}} + ]}} +- Use an empty operations array if nothing should be remembered. + +Existing memories: +{existing_text} + +Conversation: +{transcript} +""" + + response = await generate_chat_completion( + request, + form_data={ + 'model': model_id, + 'messages': [ + { + 'role': 'system', + 'content': "You are Open WebUI's private memory reviewer. Return only valid JSON.", + }, + {'role': 'user', 'content': review_prompt}, + ], + 'stream': False, + 'metadata': { + 'task': 'memory_review', + 'chat_id': metadata.get('chat_id'), + 'message_id': metadata.get('message_id'), + }, + }, + user=user, + ) + + if not isinstance(response, dict) or not response.get('choices'): + return [] + + response_message = response.get('choices', [{}])[0].get('message', {}) + content = response_message.get('content') or response_message.get('reasoning_content') or '' + start = content.find('{') + end = content.rfind('}') + if start == -1 or end == -1 or end < start: + return [] + + try: + parsed = json.loads(content[start : end + 1]) + except Exception: + return [] + + operations = parsed.get('operations') if isinstance(parsed, dict) else None + return operations if isinstance(operations, list) else [] diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 63de31fbba..fc8802a683 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -2,7 +2,6 @@ import ast import asyncio import base64 import copy -import html import inspect import json import logging @@ -32,6 +31,7 @@ from open_webui.env import ( BYPASS_MODEL_ACCESS_CONTROL, CHAT_RESPONSE_MAX_TOOL_CALL_ITERATIONS, CHAT_RESPONSE_STREAM_DELTA_CHUNK_SIZE, + ENABLE_API_OUTLET_FILTERS, ENABLE_CHAT_RESPONSE_BASE64_IMAGE_URL_CONVERSION, ENABLE_QUERIES_CACHE, ENABLE_REALTIME_CHAT_SAVE, @@ -40,6 +40,7 @@ from open_webui.env import ( RAG_SYSTEM_CONTEXT, ) from open_webui.models.chats import Chats +from open_webui.models.config import Config from open_webui.models.folders import Folders from open_webui.models.functions import Functions from open_webui.models.models import Models @@ -52,7 +53,6 @@ from open_webui.routers.images import ( image_edits, image_generations, ) -from open_webui.routers.memories import QueryMemoryForm, query_memory from open_webui.routers.pipelines import ( process_pipeline_inlet_filter, process_pipeline_outlet_filter, @@ -76,6 +76,7 @@ from open_webui.utils.access_control import has_connection_access, has_permissio from open_webui.utils.access_control.files import get_accessible_folder_files from open_webui.utils.chat import generate_chat_completion from open_webui.utils.code_interpreter import execute_code_jupyter +from open_webui.utils.context_compaction import compact_messages_for_request from open_webui.utils.files import ( convert_markdown_base64_images, get_file_url_from_base64, @@ -88,6 +89,7 @@ from open_webui.utils.filter import ( ) from open_webui.utils.mcp.client import MCPClient +from open_webui.utils.memory import add_memory_context, review_memory_after_turn from open_webui.utils.misc import ( add_or_update_system_message, add_or_update_user_message, @@ -108,9 +110,9 @@ from open_webui.utils.misc import ( set_last_user_message_content, strip_empty_content_blocks, ) -from open_webui.utils.payload import apply_system_prompt_to_body +from open_webui.utils.payload import apply_system_prompt_to_body, resolve_system_prompt from open_webui.utils.plugin import load_function_module_by_id -from open_webui.utils.response import normalize_usage +from open_webui.utils.response import merge_usage, normalize_usage from open_webui.utils.sanitize import sanitize_code from open_webui.utils.task import ( get_task_model_id, @@ -145,6 +147,7 @@ DEFAULT_REASONING_TAGS = [ ('<|begin_of_thought|>', '<|end_of_thought|>'), ('◁think▷', '◁/think▷'), ] + DEFAULT_SOLUTION_TAGS = [('<|begin_of_solution|>', '<|end_of_solution|>')] DEFAULT_CODE_INTERPRETER_TAGS = [('', '')] @@ -374,210 +377,6 @@ def get_citation_source_from_tool_result( ] -def split_content_and_whitespace(content): - content_stripped = content.rstrip() - original_whitespace = content[len(content_stripped) :] if len(content) > len(content_stripped) else '' - return content_stripped, original_whitespace - - -def is_opening_code_block(content): - backtick_segments = content.split('```') - # Even number of segments means the last backticks are opening a new block - return len(backtick_segments) > 1 and len(backtick_segments) % 2 == 0 - - -_OPENAI_TOOL_DISPLAY_NAMES = { - 'web_search_call': 'Web Search', - 'file_search_call': 'File Search', - 'computer_call': 'Computer Use', -} - - -def _render_openai_tool_call_handler(item: dict, done: bool) -> str: - """Render an OpenAI Responses API server-side tool item as a
block. - - Handles web_search_call, file_search_call, and computer_call items whose - schemas are defined in the openai-python SDK (generated from OpenAPI spec). - """ - item_type = item.get('type', '') - call_id = item.get('id', '') - display_name = _OPENAI_TOOL_DISPLAY_NAMES.get(item_type, item_type) - - # Build a short summary of what the tool did - summary = '' - if item_type == 'web_search_call': - action = item.get('action', {}) - if isinstance(action, dict): - atype = action.get('type', '') - if atype == 'search': - queries = action.get('queries') or [] - query = action.get('query', '') - summary = ( - f'Search: {", ".join(str(q) for q in queries)}' - if queries - else (f'Search: {query}' if query else '') - ) - elif atype == 'open_page': - summary = f'Open page: {action.get("url", "")}' if action.get('url') else '' - elif atype == 'find_in_page': - summary = f'Find in page: {action.get("pattern", "")}' if action.get('pattern') else '' - elif item_type == 'file_search_call': - queries = item.get('queries', []) - if queries: - summary = f'Queries: {", ".join(str(q) for q in queries)}' - elif item_type == 'computer_call': - action = item.get('action') - actions = item.get('actions') - if isinstance(action, dict): - summary = f'Action: {action.get("type", "unknown")}' - elif isinstance(actions, list) and actions: - summary = f'Actions: {", ".join(a.get("type", "?") for a in actions if isinstance(a, dict))}' - - escaped_name = html.escape(display_name) - if done: - return f'
\nTool Executed\n{html.escape(summary)}\n
\n' - return f'
\nExecuting...\n
\n' - - -def serialize_output(output: list) -> str: - """ - Convert OR-aligned output items to HTML for display. - For LLM consumption, use convert_output_to_messages() instead. - """ - parts: list[str] = [] - - # First pass: collect function_call_output items by call_id for lookup - tool_outputs = {} - for item in output: - if item.get('type') == 'function_call_output': - tool_outputs[item.get('call_id')] = item - - # Second pass: render items in order - for idx, item in enumerate(output): - item_type = item.get('type', '') - - if item_type == 'message': - for content_part in item.get('content', []): - if 'text' in content_part: - text = content_part.get('text', '').strip() - if text: - parts.append(text) - - elif item_type == 'function_call': - call_id = item.get('call_id', '') - name = item.get('name', '') - arguments = item.get('arguments', '') - - result_item = tool_outputs.get(call_id) - if result_item: - result_parts: list[str] = [] - for result_output in result_item.get('output', []): - if 'text' in result_output: - output_text = result_output.get('text', '') - result_parts.append(str(output_text) if not isinstance(output_text, str) else output_text) - result_text = ''.join(result_parts) - files = result_item.get('files') - embeds = result_item.get('embeds', '') - - parts.append( - f'
\nTool Executed\n{html.escape(json.dumps(result_text, ensure_ascii=False))}\n
' - ) - else: - parts.append( - f'
\nExecuting...\n
' - ) - - elif item_type == 'function_call_output': - # Already handled inline with function_call above - pass - - elif item_type in _OPENAI_TOOL_DISPLAY_NAMES: - status = item.get('status', 'in_progress') - done = status in ('completed', 'failed', 'incomplete') or idx != len(output) - 1 - parts.append(_render_openai_tool_call_handler(item, done).rstrip('\n')) - - elif item_type == 'reasoning': - reasoning_parts: list[str] = [] - # Check for 'summary' (new structure) or 'content' (legacy/fallback) - source_list = item.get('summary', []) or item.get('content', []) - for content_part in source_list: - if 'text' in content_part: - reasoning_parts.append(content_part.get('text', '')) - elif 'summary' in content_part: # Handle potential nested logic if any - pass - - reasoning_content = ''.join(reasoning_parts).strip() - - duration = item.get('duration') - status = item.get('status', 'in_progress') - - # Infer completion: if this reasoning item is NOT the last item, - # render as done (a subsequent item means reasoning is complete) - is_last_item = idx == len(output) - 1 - - display = html.escape( - '\n'.join( - (f'> {line}' if not line.startswith('>') else line) for line in reasoning_content.splitlines() - ) - ) - - if status == 'completed' or duration is not None or not is_last_item: - parts.append( - f'
\nThought for {duration or 0} seconds\n{display}\n
' - ) - else: - parts.append( - f'
\nThinking…\n{display}\n
' - ) - - elif item_type == 'open_webui:code_interpreter': - # Code interpreter needs to inspect/mutate prior accumulated content - # to strip trailing unclosed code fences — materialize only here. - content = '\n'.join(parts) - content_stripped, original_whitespace = split_content_and_whitespace(content) - if is_opening_code_block(content_stripped): - content = content_stripped.rstrip('`').rstrip() + original_whitespace - else: - content = content_stripped + original_whitespace - - # Re-split back into parts list after mutation - parts = [content] if content else [] - - # Render the code_interpreter item as a
block - # so the frontend Collapsible renders "Analyzing..."/"Analyzed". - code = item.get('code', '').strip() - lang = item.get('lang', 'python') - status = item.get('status', 'in_progress') - duration = item.get('duration') - is_last_item = idx == len(output) - 1 - - # Build inner content: code block - display = '' - if code: - display = f'```{lang}\n{code}\n```' - - # Build output attribute as HTML-escaped JSON for CodeBlock.svelte - ci_output = item.get('output') - output_attr = '' - if ci_output: - if isinstance(ci_output, dict): - output_json = json.dumps(ci_output, ensure_ascii=False) - else: - output_json = json.dumps({'result': str(ci_output)}, ensure_ascii=False) - output_attr = f' output="{html.escape(output_json)}"' - - if status == 'completed' or duration is not None or not is_last_item: - parts.append( - f'
\nAnalyzed\n{display}\n
' - ) - else: - parts.append( - f'
\nAnalyzing…\n{display}\n
' - ) - - return '\n'.join(parts).strip() - - def deep_merge(target, source): """ Merge source into target recursively (returning new structure). @@ -980,13 +779,13 @@ async def apply_source_context_to_messages( if RAG_SYSTEM_CONTEXT: return add_or_update_system_message( - await rag_template(request.app.state.config.RAG_TEMPLATE, context, user_message), + await rag_template(await Config.get('rag.template'), context, user_message), messages, append=True, ) else: return add_or_update_user_message( - await rag_template(request.app.state.config.RAG_TEMPLATE, context, user_message), + await rag_template(await Config.get('rag.template'), context, user_message), messages, append=False, ) @@ -1158,6 +957,23 @@ async def process_tool_result( except json.JSONDecodeError: pass tool_response.append(text) + elif resource.get('blob'): + resource_mime_type = resource.get('mimeType') or 'application/octet-stream' + resource_blob = resource.get('blob', '') + if resource_mime_type.startswith('image/'): + tool_result_files.append( + { + 'type': 'image', + 'url': f'data:{resource_mime_type};base64,{resource_blob}', + } + ) + else: + resource_uri = resource.get('uri', 'resource') + tool_response.append( + f'[Resource: {resource_uri}] (binary data, mimeType: {resource_mime_type})' + ) + elif resource.get('uri'): + tool_response.append(resource.get('uri')) tool_result = tool_response[0] if len(tool_response) == 1 else tool_response else: # OpenAPI for item in tool_result: @@ -1290,8 +1106,8 @@ async def chat_completion_tools_handler( task_model_id = get_task_model_id( body['model'], - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) @@ -1301,8 +1117,8 @@ async def chat_completion_tools_handler( specs = [tool['spec'] for tool in tools.values()] tools_specs = json.dumps(specs, ensure_ascii=False) - if request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE != '': - template = request.app.state.config.TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE + if await Config.get('task.tools.prompt_template') != '': + template = await Config.get('task.tools.prompt_template') else: template = DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE @@ -1456,41 +1272,6 @@ async def chat_completion_tools_handler( return body, {'sources': sources} -async def chat_memory_handler(request: Request, form_data: dict, extra_params: dict, user): - try: - results = await query_memory( - request, - QueryMemoryForm( - **{ - 'content': get_last_user_message(form_data['messages']) or '', - 'k': 3, - } - ), - user, - ) - except Exception as e: - log.debug(e) - results = None - - user_context = '' - if results and hasattr(results, 'documents'): - if results.documents and len(results.documents) > 0: - for doc_idx, doc in enumerate(results.documents[0]): - created_at_date = 'Unknown Date' - - if results.metadatas[0][doc_idx].get('created_at'): - created_at_timestamp = results.metadatas[0][doc_idx]['created_at'] - created_at_date = time.strftime('%Y-%m-%d', time.localtime(created_at_timestamp)) - - user_context += f'{doc_idx + 1}. [{created_at_date}] {doc}\n' - - form_data['messages'] = add_or_update_system_message( - f'User Context:\n{user_context}\n', form_data['messages'], append=True - ) - - return form_data - - async def chat_web_search_handler(request: Request, form_data: dict, extra_params: dict, user): event_emitter = extra_params['__event_emitter__'] await event_emitter( @@ -1792,7 +1573,7 @@ async def chat_image_generation_handler(request: Request, form_data: dict, extra system_message_content = '' - if len(input_images) > 0 and request.app.state.config.ENABLE_IMAGE_EDIT: + if len(input_images) > 0 and await Config.get('images.edit.enable'): # Edit image(s) try: images = await image_edits( @@ -1852,7 +1633,7 @@ async def chat_image_generation_handler(request: Request, form_data: dict, extra else: # Create image(s) - if request.app.state.config.ENABLE_IMAGE_PROMPT_GENERATION: + if await Config.get('image_generation.prompt.enable'): try: res = await generate_image_prompt( request, @@ -2018,17 +1799,17 @@ async def chat_completion_files_handler( embedding_function=lambda query, prefix: request.app.state.EMBEDDING_FUNCTION( query, prefix=prefix, user=user ), - k=request.app.state.config.TOP_K, + k=await Config.get('rag.top_k'), reranking_function=( (lambda query, documents: request.app.state.RERANKING_FUNCTION(query, documents, user=user)) if request.app.state.RERANKING_FUNCTION else None ), - k_reranker=request.app.state.config.TOP_K_RERANKER, - r=request.app.state.config.RELEVANCE_THRESHOLD, - hybrid_bm25_weight=request.app.state.config.HYBRID_BM25_WEIGHT, - hybrid_search=request.app.state.config.ENABLE_RAG_HYBRID_SEARCH, - full_context=all_full_context or request.app.state.config.RAG_FULL_CONTEXT, + k_reranker=await Config.get('rag.top_k_reranker'), + r=await Config.get('rag.relevance_threshold'), + hybrid_bm25_weight=await Config.get('rag.hybrid_bm25_weight'), + hybrid_search=await Config.get('rag.enable_hybrid_search'), + full_context=all_full_context or await Config.get('rag.full_context'), user=user, ) except Exception as e: @@ -2074,6 +1855,7 @@ def apply_params_to_form_data(form_data, model): 'stream_delta_chunk_size': int, 'function_calling': str, 'reasoning_tags': list, + 'compact_token_threshold': int, 'system': str, } @@ -2169,7 +1951,10 @@ async def load_messages_from_db(chat_id: str, message_id: str) -> Optional[list[ if not db_messages: return None - return [{k: v for k, v in msg.items() if k in ('role', 'content', 'output', 'files')} for msg in db_messages] + return [ + {k: v for k, v in msg.items() if k in ('role', 'content', 'output', 'files', 'contextSummary')} + for msg in db_messages + ] def get_reasoning_format(model: dict) -> str | None: @@ -2220,7 +2005,51 @@ def process_messages_with_output( return processed -SKILL_MENTION_RE = re.compile(r'<\$([^|>]+)\|?[^>]*>') +def strip_compaction_fields(messages: list[dict]) -> list[dict]: + stripped = [] + for message in messages: + clean = dict(message) + clean.pop('contextSummary', None) + clean.pop('context_summary', None) + stripped.append(clean) + return stripped + + +def sanitize_tool_pairs(messages: list[dict]) -> list[dict]: + tool_result_ids = { + message.get('tool_call_id') + for message in messages + if message.get('role') == 'tool' and message.get('tool_call_id') + } + + tool_call_ids = { + tool_call.get('id') + for message in messages + for tool_call in (message.get('tool_calls') or []) + if message.get('role') == 'assistant' and tool_call.get('id') + } + + sanitized = [] + for message in messages: + if message.get('role') == 'assistant' and message.get('tool_calls'): + kept = [ + tool_call for tool_call in message.get('tool_calls') or [] if tool_call.get('id') in tool_result_ids + ] + if kept: + sanitized.append({**message, 'tool_calls': kept}) + else: + clean = dict(message) + clean.pop('tool_calls', None) + clean.pop('reasoning_items', None) + if clean.get('content'): + sanitized.append(clean) + elif message.get('role') != 'tool' or message.get('tool_call_id') in tool_call_ids: + sanitized.append(message) + + return sanitized + + +SKILL_MENTION_RE = re.compile(r'<\$([^|>]+)(?:\|[^>]*)?>') def _get_text_parts(message: dict) -> list[str]: @@ -2244,7 +2073,7 @@ def extract_skill_ids_from_messages(messages: list[dict]) -> set[str]: def strip_skill_mentions(messages: list[dict]) -> None: """Replace <$skillId|label> mention tags with the label in message content in-place.""" - strip_re = re.compile(r'<\$[^|>]+\|?([^>]*)>') + strip_re = re.compile(r'<\$[^|>]+(?:\|([^>]*))?>') for message in messages: content = message.get('content') if isinstance(content, str) and strip_re.search(content): @@ -2269,8 +2098,8 @@ async def connect_mcp_server( Returns None if the server is not found or access is denied. """ mcp_server_connection = None - for server_connection in request.app.state.config.TOOL_SERVER_CONNECTIONS: - if server_connection.get('type', '') == 'mcp' and server_connection.get('info', {}).get('id') == server_id: + for server_connection in await Config.get('tool_server.connections', []): + if server_connection.get('type', '') == 'mcp' and (server_connection.get('info') or {}).get('id') == server_id: mcp_server_connection = server_connection break @@ -2367,7 +2196,11 @@ async def process_chat_payload(request, form_data, user, metadata, model): assistant_message = await Chats.get_message_by_id_and_message_id(chat_id, assistant_message_id) if assistant_message and (assistant_message.get('content') or assistant_message.get('output')): db_messages.append( - {k: v for k, v in assistant_message.items() if k in ('role', 'content', 'output', 'files')} + { + k: v + for k, v in assistant_message.items() + if k in ('role', 'content', 'output', 'files', 'contextSummary') + } ) system_message = get_system_message(form_data.get('messages', [])) @@ -2400,11 +2233,44 @@ async def process_chat_payload(request, form_data, user, metadata, model): if regeneration_prompt: form_data['messages'].append({'role': 'user', 'content': regeneration_prompt}) + if chat_id and user_message_id and not chat_id.startswith('local:') and not chat_id.startswith('channel:'): + if getattr(request.state, 'direct', False) and hasattr(request.state, 'model'): + compaction_models = { + request.state.model['id']: request.state.model, + } + else: + compaction_models = request.app.state.MODELS + + system_message = get_system_message(form_data.get('messages', [])) + system_prompt = get_content_from_message(system_message) if system_message else '' + + try: + form_data['messages'], context_summary, _ = await compact_messages_for_request( + request, + user, + form_data.get('messages', []), + metadata, + form_data.get('model'), + compaction_models, + system_prompt, + ) + if context_summary: + form_data['messages'] = add_or_update_system_message( + f'[CONVERSATION SUMMARY]\n{context_summary}', + form_data['messages'], + append=True, + ) + except Exception: + log.exception('Context compaction failed; continuing with full chat history') + + form_data['messages'] = strip_compaction_fields(form_data.get('messages', [])) + # Process messages with OR-aligned output items for clean LLM messages form_data['messages'] = process_messages_with_output( form_data.get('messages', []), reasoning_format=get_reasoning_format(model), ) + form_data['messages'] = sanitize_tool_pairs(form_data['messages']) system_message = get_system_message(form_data.get('messages', [])) if system_message: # Chat Controls/User Settings @@ -2442,8 +2308,8 @@ async def process_chat_payload(request, form_data, user, metadata, model): task_model_id = get_task_model_id( form_data['model'], - request.app.state.config.TASK_MODEL, - request.app.state.config.TASK_MODEL_EXTERNAL, + await Config.get('task.model.default'), + await Config.get('task.model.external'), models, ) @@ -2471,7 +2337,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): if 'files' in folder.data: # Defensive: filter to entries the caller can still read. allowed_files = await get_accessible_folder_files(folder.data['files'], user) - if metadata.get('params', {}).get('function_calling') != 'native': + if metadata.get('params', {}).get('function_calling') == 'legacy': form_data['files'] = [ *allowed_files, *form_data.get('files', []), @@ -2485,7 +2351,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): user_message = get_last_user_message(form_data['messages']) model_knowledge = model.get('info', {}).get('meta', {}).get('knowledge', False) - if model_knowledge and metadata.get('params', {}).get('function_calling') != 'native': + if model_knowledge and metadata.get('params', {}).get('function_calling') == 'legacy': await event_emitter( { 'type': 'status', @@ -2550,9 +2416,9 @@ async def process_chat_payload(request, form_data, user, metadata, model): extra_params['__features__'] = features if features: if 'voice' in features and features['voice']: - if getattr(request.app.state.config, 'ENABLE_VOICE_MODE_PROMPT', True): - if request.app.state.config.VOICE_MODE_PROMPT_TEMPLATE: - template = request.app.state.config.VOICE_MODE_PROMPT_TEMPLATE + if await Config.get('task.voice.prompt.enable'): + if await Config.get('task.voice.prompt_template'): + template = await Config.get('task.voice.prompt_template') else: template = DEFAULT_VOICE_MODE_PROMPT_TEMPLATE @@ -2562,29 +2428,27 @@ async def process_chat_payload(request, form_data, user, metadata, model): ) if 'memory' in features and features['memory']: - # Skip forced memory injection when native FC is enabled - model can use memory tools - if metadata.get('params', {}).get('function_calling') != 'native': - form_data = await chat_memory_handler(request, form_data, extra_params, user) + form_data = await add_memory_context(request, form_data, user, model) if 'web_search' in features and features['web_search']: # Skip forced RAG web search when native FC is enabled - model can use web_search tool - if metadata.get('params', {}).get('function_calling') != 'native': + if metadata.get('params', {}).get('function_calling') == 'legacy': form_data = await chat_web_search_handler(request, form_data, extra_params, user) if 'image_generation' in features and features['image_generation']: # Skip forced image generation when native FC is enabled - model can use generate_image tool - if metadata.get('params', {}).get('function_calling') != 'native': + if metadata.get('params', {}).get('function_calling') == 'legacy': form_data = await chat_image_generation_handler(request, form_data, extra_params, user) if 'code_interpreter' in features and features['code_interpreter']: - engine = getattr(request.app.state.config, 'CODE_INTERPRETER_ENGINE', 'pyodide') + engine = await Config.get('code_interpreter.engine', 'pyodide') # Skip XML-tag prompt injection when native FC is enabled — # execute_code will be injected as a builtin tool instead - if metadata.get('params', {}).get('function_calling') != 'native': + if metadata.get('params', {}).get('function_calling') == 'legacy': prompt = ( - request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE - if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE != '' + await Config.get('code_interpreter.prompt_template') + if await Config.get('code_interpreter.prompt_template') != '' else DEFAULT_CODE_INTERPRETER_PROMPT ) @@ -2617,43 +2481,51 @@ async def process_chat_payload(request, form_data, user, metadata, model): # If the original caller provided tools, use them as-is (skip resolution). # Otherwise, save any tools that filter inlets added for merging later. - inlet_filter_tools = None if payload_tools else form_data.get('tools', None) + inlet_filter_tools = None if payload_tools is not None else form_data.get('tools', None) - # Skills — extract IDs from message content (<$skillId|label> tags) so - # persisted chats work without relying on the frontend to send skill_ids. - user_skill_ids = set(form_data.pop('skill_ids', None) or []) - user_skill_ids |= extract_skill_ids_from_messages(form_data.get('messages', [])) - model_skill_ids = set(model.get('info', {}).get('meta', {}).get('skillIds', [])) - - all_skill_ids = user_skill_ids | model_skill_ids + # Mentioned skills get full content; selected/default skills can be loaded through view_skill. + mentioned_skill_ids = extract_skill_ids_from_messages(form_data.get('messages', [])) + skill_ids = ( + set(form_data.pop('skill_ids', None) or []) + | set(model.get('info', {}).get('meta', {}).get('skillIds', [])) + | mentioned_skill_ids + ) available_skills = [] - if all_skill_ids: + view_skill_ids = [] + use_builtin_tools = ( + bool(metadata.get('session_id')) + and metadata.get('params', {}).get('function_calling') != 'legacy' + and (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get('builtin_tools', True) + ) + + if skill_ids: from open_webui.models.skills import Skills as SkillsModel accessible_skill_ids = {s.id for s in await SkillsModel.get_skills_by_user_id(user.id, 'read')} - available_skills = [] - for sid in all_skill_ids: + for sid in skill_ids: if sid in accessible_skill_ids: s = await SkillsModel.get_skill_by_id(sid) if s and s.is_active: available_skills.append(s) - skill_descriptions = '' + skill_manifest = '' for skill in available_skills: - if skill.id in user_skill_ids: - # User-selected: inject full content + if skill.id in mentioned_skill_ids or not use_builtin_tools: form_data['messages'] = add_or_update_system_message( f'\n{skill.content}\n', form_data['messages'], append=True, ) else: - # Model-attached: name+description only - skill_descriptions += f'\n{skill.id}\n{skill.name}\n{skill.description or ""}\n\n' + view_skill_ids.append(skill.id) + skill_manifest += ( + f'\n{skill.id}\n{skill.name}\n' + f'{skill.description or ""}\n\n' + ) - if skill_descriptions: + if skill_manifest: form_data['messages'] = add_or_update_system_message( - f'\n{skill_descriptions}', + f'\n{skill_manifest}', form_data['messages'], append=True, ) @@ -2701,13 +2573,14 @@ async def process_chat_payload(request, form_data, user, metadata, model): 'tool_ids': tool_ids, 'terminal_id': terminal_id, 'files': files, + 'features': features, } form_data['metadata'] = metadata - # When the caller provides an explicit OpenAI-style `tools` array in the - # request body, skip all server-side tool resolution and pass the caller's - # tools through to the model unchanged. - if not payload_tools: + # When the caller provides an explicit `tools` key in the request body, + # skip all server-side tool resolution and pass the caller's tools through + # unchanged. Sending `tools: []` explicitly opts out of builtin injection. + if payload_tools is None: # Server side tools tool_ids = metadata.get('tool_ids', None) # Client side tools @@ -2838,12 +2711,10 @@ async def process_chat_payload(request, form_data, user, metadata, model): if mcp_clients: metadata['mcp_clients'] = mcp_clients - # Inject builtin tools for native function calling based on enabled features and model capability - # Check if builtin_tools capability is enabled for this model (defaults to True if not specified) - builtin_tools_enabled = (model.get('info', {}).get('meta', {}).get('capabilities') or {}).get( - 'builtin_tools', True - ) - if metadata.get('params', {}).get('function_calling') == 'native' and builtin_tools_enabled: + # Inject builtin tools for native function calling based on enabled features and model capability. + # Only inject when the request originates from the UI (identified by session_id). + # API callers don't expect hidden tools; they can explicitly request tools via tool_ids. + if use_builtin_tools: # Add file context to user messages chat_id = metadata.get('chat_id') form_data['messages'] = await add_file_context(form_data.get('messages', []), chat_id, user) @@ -2852,7 +2723,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): { **extra_params, '__event_emitter__': event_emitter, - '__skill_ids__': [s.id for s in available_skills if s.id not in user_skill_ids], + '__skill_ids__': view_skill_ids, }, features, model, @@ -2866,7 +2737,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): # (e.g. pipe functions) can access all tools including MCP and builtins. metadata['tools'] = tools_dict - if metadata.get('params', {}).get('function_calling') == 'native': + if metadata.get('params', {}).get('function_calling') != 'legacy': # If the function calling is native, then call the tools function calling handler form_data['tools'] = [ {'type': 'function', 'function': tool.get('spec', {})} for tool in tools_dict.values() @@ -2897,7 +2768,15 @@ async def process_chat_payload(request, form_data, user, metadata, model): # restore to the true original (before file-source injection) rather # than a snapshot that already has the RAG template baked in. system_message = get_system_message(form_data['messages']) - metadata['system_prompt'] = get_content_from_message(system_message) if system_message else None + system_content = get_content_from_message(system_message) if system_message else '' + model_system_prompt = await resolve_system_prompt( + (form_data.get('params') or {}).get('system'), + metadata, + user, + ) + if model_system_prompt: + system_content = f'{model_system_prompt}\n{system_content}' if system_content else model_system_prompt + metadata['system_prompt'] = system_content or None metadata['user_prompt'] = get_last_user_message(form_data['messages']) metadata['sources'] = sources[:] if sources else [] @@ -3021,6 +2900,43 @@ def build_response_object(response, response_data): return response +def update_assistant_message_from_stream(assistant_message, raw): + line = raw.decode('utf-8', 'replace') if isinstance(raw, bytes) else raw + if not isinstance(line, str): + return + + for raw_part in line.splitlines(): + part = raw_part.removeprefix('data:').strip() + if not part or part == '[DONE]': + continue + + try: + data = json.loads(part) + except Exception: + continue + + if not isinstance(data, dict): + continue + + if data.get('type', '').startswith('response.'): + output, meta = handle_responses_streaming_event(data, assistant_message.get('output', [])) + if output: + assistant_message['output'] = output + if meta and meta.get('usage'): + assistant_message['usage'] = merge_usage(assistant_message.get('usage'), meta['usage']) + continue + + raw_usage = data.get('usage', {}) or {} + raw_usage.update(data.get('timings', {})) + if raw_usage: + assistant_message['usage'] = merge_usage(assistant_message.get('usage'), raw_usage) + + for choice in data.get('choices', []): + content = (choice.get('delta', {}) or {}).get('content') + if content: + assistant_message['content'] = assistant_message.get('content', '') + content + + async def get_system_oauth_token(request, user): """Get the system OAuth token for a user. @@ -3270,6 +3186,17 @@ async def background_tasks_handler(ctx): except Exception as e: pass + if messages: + await review_memory_after_turn( + request=request, + user=user, + model=ctx['model'], + metadata=metadata, + form_data=form_data, + assistant_message=ctx.get('assistant_message') or {}, + messages=messages, + ) + async def outlet_filter_handler(ctx): """Run outlet filters inline after chat completion. @@ -3278,9 +3205,7 @@ async def outlet_filter_handler(ctx): Persists outlet-modified content to DB and emits a chat:outlet event so the frontend can sync its in-memory state. - For temp chats (local: prefix), messages are built from form_data - plus the assistant response message stored in ctx['assistant_message'], - since temp chats have no DB-persisted history. + For temp/API chats, messages are built from form_data plus ctx['assistant_message']. """ request = ctx['request'] user = ctx['user'] @@ -3292,17 +3217,17 @@ async def outlet_filter_handler(ctx): chat_id = metadata.get('chat_id', '') message_id = metadata.get('message_id') - if not chat_id or not message_id: + if not chat_id and not ctx.get('assistant_message'): return - is_temp_chat = chat_id.startswith('local:') or chat_id.startswith('channel:') + if not message_id: + message_id = output_id('msg') + is_temp_chat = chat_id.startswith('local:') or chat_id.startswith('channel:') try: messages_map = None - if is_temp_chat: - # Temp chats have no DB record — build message list from - # the in-memory form_data plus the assistant response. + if is_temp_chat or not chat_id: form_messages = ctx.get('form_data', {}).get('messages', []) assistant_message = ctx.get('assistant_message', {}) @@ -3314,7 +3239,6 @@ async def outlet_filter_handler(ctx): for m in form_messages ] - # Append the full assistant message (content, output, usage, etc.) if assistant_message: message_list.append( { @@ -3323,6 +3247,9 @@ async def outlet_filter_handler(ctx): **assistant_message, } ) + + if not message_list: + return else: messages_map = await Chats.get_messages_map_by_chat_id(chat_id) if not messages_map: @@ -3383,8 +3310,6 @@ async def outlet_filter_handler(ctx): extra_params=extra_params, ) - # Persist outlet-modified content and notify frontend - # (skip DB persistence for temp chats — they have no DB record) if outlet_result and outlet_result.get('messages'): if not is_temp_chat and messages_map: for message in outlet_result['messages']: @@ -3396,18 +3321,16 @@ async def outlet_filter_handler(ctx): 'output' ) if content_changed or output_changed: - # If output was modified, re-derive content from it - new_content = message.get('content', original_message.get('content', '')) - if output_changed: - new_content = serialize_output(message['output']) + message_update = { + 'originalContent': original_message.get('content'), + **({'output': message['output']} if output_changed else {}), + } + if content_changed: + message_update['content'] = message.get('content', '') await Chats.upsert_message_to_chat_by_id_and_message_id( chat_id, outlet_message_id, - { - 'content': new_content, - 'originalContent': original_message.get('content'), - **({'output': message['output']} if output_changed else {}), - }, + message_update, ) if event_emitter: @@ -3493,7 +3416,29 @@ async def non_streaming_chat_response_handler(response, ctx): # otherwise generate from response content response_output = response_data.get('output') if not response_output: - response_output = [ + choice_message = choices[0].get('message', {}) + reasoning_content = choice_message.get('reasoning_content') or choice_message.get('reasoning') + reasoning_details = choice_message.get('reasoning_details') + response_output = [] + if reasoning_content or reasoning_details: + reasoning_item = { + 'type': 'reasoning', + 'id': output_id('r'), + 'status': 'completed', + 'start_tag': '', + 'end_tag': '', + 'attributes': {'type': 'reasoning_content'}, + 'content': ( + [{'type': 'output_text', 'text': reasoning_content}] if reasoning_content else [] + ), + 'summary': None, + } + if reasoning_details: + reasoning_item['reasoning_details'] = ( + reasoning_details if isinstance(reasoning_details, list) else [reasoning_details] + ) + response_output.append(reasoning_item) + response_output.append( { 'type': 'message', 'id': output_id('msg'), @@ -3501,7 +3446,7 @@ async def non_streaming_chat_response_handler(response, ctx): 'role': 'assistant', 'content': [{'type': 'output_text', 'text': content}], } - ] + ) await event_emitter( { @@ -3532,18 +3477,19 @@ async def non_streaming_chat_response_handler(response, ctx): ) # Send a webhook notification if the user is not active - if request.app.state.config.ENABLE_USER_WEBHOOKS and not await Users.is_user_active(user.id): + if await Config.get('ui.enable_user_webhooks') and not await Users.is_user_active(user.id): webhook_url = await Users.get_user_webhook_url_by_id(user.id) if webhook_url: + webui_url = await Config.get('webui.url') await post_webhook( request.app.state.WEBUI_NAME, webhook_url, - f'{content}\n\n{title} - {request.app.state.config.WEBUI_URL}/c/{metadata["chat_id"]}', + f'{content}\n\n{title} - {webui_url}/c/{metadata["chat_id"]}', { 'action': 'chat', 'message': content, 'title': title, - 'url': f'{request.app.state.config.WEBUI_URL}/c/{metadata["chat_id"]}', + 'url': f'{webui_url}/c/{metadata["chat_id"]}', }, ) @@ -3562,6 +3508,18 @@ async def non_streaming_chat_response_handler(response, ctx): return response + choices = response_data.get('choices', []) + output = response_data.get('output') + content = choices[0].get('message', {}).get('content') if choices else '' + if ENABLE_API_OUTLET_FILTERS and (content or output): + usage = normalize_usage(response_data.get('usage', {}) or {}) + ctx['assistant_message'] = { + **({'content': content} if content else {}), + **({'output': output} if output else {}), + **({'usage': usage} if usage else {}), + } + await outlet_filter_handler(ctx) + if isinstance(response, dict): response = merge_events_into_response(response_data, events) @@ -3881,14 +3839,14 @@ async def streaming_chat_response_handler(response, ctx): DETECT_CODE_INTERPRETER = ( bool(features.get('code_interpreter')) and builtin_tools_meta.get('code_interpreter', True) - and getattr(request.app.state.config, 'ENABLE_CODE_INTERPRETER', True) + and await Config.get('code_interpreter.enable') and model_capabilities.get('code_interpreter', True) and ( getattr(user, 'role', None) == 'admin' or await has_permission( getattr(user, 'id', ''), 'features.code_interpreter', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), ) ) ) @@ -3933,10 +3891,12 @@ async def streaming_chat_response_handler(response, ctx): int(metadata.get('params', {}).get('stream_delta_chunk_size') or 1), ) last_delta_data = None + last_delta_type = None async def flush_pending_delta_data(threshold: int = 0): nonlocal delta_count nonlocal last_delta_data + nonlocal last_delta_type if delta_count >= threshold and last_delta_data: await event_emitter( @@ -3947,6 +3907,22 @@ async def streaming_chat_response_handler(response, ctx): ) delta_count = 0 last_delta_data = None + last_delta_type = None + + async def queue_pending_delta_data(delta_data: dict, delta_type: str): + nonlocal delta_count + nonlocal last_delta_data + nonlocal last_delta_type + + if last_delta_type and last_delta_type != delta_type: + await flush_pending_delta_data() + + delta_count += 1 + last_delta_data = delta_data + last_delta_type = delta_type + + if delta_count >= delta_chunk_size: + await flush_pending_delta_data(delta_chunk_size) async for line in response.body_iterator: line = line.decode('utf-8', 'replace') if isinstance(line, bytes) else line @@ -3958,6 +3934,26 @@ async def streaming_chat_response_handler(response, ctx): # "data:" is the prefix for each event if not data.startswith('data:'): + # Some upstreams return plain JSON error lines in a streaming response + # (without SSE `data:` prefix). Try to normalize these into standard + # error events so frontend and DB paths still receive them. + try: + raw_obj = json.loads(data) + raw_error = raw_obj.get('error') if isinstance(raw_obj, dict) else None + if raw_error: + try: + Chats.upsert_message_to_chat_by_id_and_message_id( + metadata['chat_id'], + metadata['message_id'], + { + 'error': {'content': raw_error}, + }, + ) + except Exception: + pass + await event_emitter({'type': 'chat:completion', 'data': {'error': raw_error}}) + except Exception: + pass continue # Remove the prefix @@ -3995,11 +3991,16 @@ async def streaming_chat_response_handler(response, ctx): ) # Check for Responses API events (type field starts with "response.") elif data.get('type', '').startswith('response.'): + response_event_type = data.get('type', '') + response_event_is_delta = response_event_type.endswith('.delta') output, response_metadata = handle_responses_streaming_event(data, output) + if not response_event_is_delta: + await flush_pending_delta_data() + # Emit citation sources from finalized output items # (mirrors Chat Completions annotation handling at delta level) - if data.get('type') == 'response.output_item.done': + if response_event_type == 'response.output_item.done': item = data.get('item', {}) if item.get('type') == 'message': for part in item.get('content', []): @@ -4033,7 +4034,6 @@ async def streaming_chat_response_handler(response, ctx): processed_data = { 'output': full_output(), - 'content': serialize_output(full_output()), } # print(data) @@ -4052,18 +4052,27 @@ async def streaming_chat_response_handler(response, ctx): # Normalize and capture usage for DB persistence if response_metadata.get('usage'): - response_metadata['usage'] = normalize_usage(response_metadata['usage']) - usage = response_metadata['usage'] + usage = merge_usage(usage, response_metadata['usage']) + response_metadata['usage'] = usage processed_data.update(response_metadata) processed_data.pop('done', None) - await event_emitter( - { - 'type': 'chat:completion', - 'data': processed_data, - } - ) + if response_event_is_delta: + response_delta_type = response_event_type.split('.')[1] + await queue_pending_delta_data( + processed_data, + 'tool_call' + if response_delta_type == 'function_call_arguments' + else 'content', + ) + else: + await event_emitter( + { + 'type': 'chat:completion', + 'data': processed_data, + } + ) continue else: choices = data.get('choices', []) @@ -4072,7 +4081,7 @@ async def streaming_chat_response_handler(response, ctx): raw_usage = data.get('usage', {}) or {} raw_usage.update(data.get('timings', {})) # llama.cpp if raw_usage: - usage = normalize_usage(raw_usage) + usage = merge_usage(usage, raw_usage) await event_emitter( { 'type': 'chat:completion', @@ -4107,6 +4116,7 @@ async def streaming_chat_response_handler(response, ctx): continue delta = choices[0].get('delta', {}) + delta_type = 'content' # Handle delta annotations annotations = delta.get('annotations') @@ -4176,9 +4186,6 @@ async def streaming_chat_response_handler(response, ctx): # Emit pending tool calls in real-time if response_tool_calls: - # Flush any pending text first - await flush_pending_delta_data() - # Build pending function_call output items for display pending_fc_items = [] for tc in response_tool_calls: @@ -4195,14 +4202,10 @@ async def streaming_chat_response_handler(response, ctx): } ) - await event_emitter( - { - 'type': 'chat:completion', - 'data': { - 'content': serialize_output(full_output() + pending_fc_items), - }, - } - ) + data = { + 'output': full_output() + pending_fc_items, + } + delta_type = 'tool_call' image_urls = await get_image_urls(delta.get('images', []), request, metadata, user) if image_urls: @@ -4229,7 +4232,8 @@ async def streaming_chat_response_handler(response, ctx): or delta.get('reasoning') or delta.get('thinking') ) - if reasoning_content: + reasoning_details = delta.get('reasoning_details') + if reasoning_content or reasoning_details: if not output or output[-1].get('type') != 'reasoning': reasoning_item = { 'type': 'reasoning', @@ -4246,19 +4250,30 @@ async def streaming_chat_response_handler(response, ctx): else: reasoning_item = output[-1] - # Append to reasoning content - parts = reasoning_item.get('content', []) - if parts and parts[-1].get('type') == 'output_text': - parts[-1]['text'] += reasoning_content - else: - reasoning_item['content'] = [ - { - 'type': 'output_text', - 'text': reasoning_content, - } - ] + if reasoning_content: + # Append to reasoning content + parts = reasoning_item.get('content', []) + if parts and parts[-1].get('type') == 'output_text': + parts[-1]['text'] += reasoning_content + else: + reasoning_item['content'] = [ + { + 'type': 'output_text', + 'text': reasoning_content, + } + ] - data = {'content': serialize_output(full_output())} + data = { + 'output': full_output(), + } + delta_type = 'content' + + if reasoning_details: + reasoning_item.setdefault('reasoning_details', []).extend( + reasoning_details + if isinstance(reasoning_details, list) + else [reasoning_details] + ) if value: if ( @@ -4411,20 +4426,21 @@ async def streaming_chat_response_handler(response, ctx): metadata['chat_id'], metadata['message_id'], { - 'content': serialize_output(full_output()), 'output': full_output(), }, ) + data = { + 'output': full_output(), + } + delta_type = 'content' else: data = { - 'content': serialize_output(full_output()), + 'output': full_output(), } + delta_type = 'content' if delta: - delta_count += 1 - last_delta_data = data - if delta_count >= delta_chunk_size: - await flush_pending_delta_data(delta_chunk_size) + await queue_pending_delta_data(data, delta_type) else: await event_emitter( { @@ -4561,7 +4577,6 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(full_output()), 'output': full_output(), }, } @@ -4718,7 +4733,7 @@ async def streaming_chat_response_handler(response, ctx): display_files = [] for file_item in result.get('files', []): if file_item.get('type') == 'image' and file_item.get('url', '').startswith('data:'): - # LLM-only: add as input_image part (invisible to serialize_output) + # LLM-only: add as input_image part, not frontend display output. output_parts.append({'type': 'input_image', 'image_url': file_item['url']}) else: # Frontend display (MCP images, audio, etc.) @@ -4764,10 +4779,19 @@ async def streaming_chat_response_handler(response, ctx): original_user_message, form_data['messages'], ) - replace_system_message_content( - original_system_content or '', - form_data['messages'], - ) + if original_system_content is not None: + if get_system_message(form_data['messages']): + replace_system_message_content( + original_system_content, + form_data['messages'], + ) + else: + form_data['messages'] = add_or_update_system_message( + original_system_content, + form_data['messages'], + ) + else: + replace_system_message_content('', form_data['messages']) # Build context: file sources with content, # tool sources as citation markers only. @@ -4782,7 +4806,7 @@ async def streaming_chat_response_handler(response, ctx): source_context = source_context.strip() if source_context: rag_content = await rag_template( - request.app.state.config.RAG_TEMPLATE, + await Config.get('rag.template'), source_context, user_message, ) @@ -4815,7 +4839,6 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), 'output': frontend_output, }, } @@ -4939,7 +4962,6 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), 'output': output, }, } @@ -4976,7 +4998,7 @@ async def streaming_chat_response_handler(response, ctx): """) code = blocking_code + '\n' + code - if request.app.state.config.CODE_INTERPRETER_ENGINE == 'pyodide': + if await Config.get('code_interpreter.engine') == 'pyodide': ci_output = await event_caller( { 'type': 'execute:python', @@ -4988,21 +5010,21 @@ async def streaming_chat_response_handler(response, ctx): }, } ) - elif request.app.state.config.CODE_INTERPRETER_ENGINE == 'jupyter': + elif await Config.get('code_interpreter.engine') == 'jupyter': ci_output = await execute_code_jupyter( - request.app.state.config.CODE_INTERPRETER_JUPYTER_URL, + await Config.get('code_interpreter.jupyter.url'), code, ( - request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_TOKEN - if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH == 'token' + await Config.get('code_interpreter.jupyter.auth_token') + if await Config.get('code_interpreter.jupyter.auth') == 'token' else None ), ( - request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH_PASSWORD - if request.app.state.config.CODE_INTERPRETER_JUPYTER_AUTH == 'password' + await Config.get('code_interpreter.jupyter.auth_password') + if await Config.get('code_interpreter.jupyter.auth') == 'password' else None ), - request.app.state.config.CODE_INTERPRETER_JUPYTER_TIMEOUT, + await Config.get('code_interpreter.jupyter.timeout'), ) else: ci_output = {'stdout': 'Code interpreter engine not configured.'} @@ -5066,7 +5088,6 @@ async def streaming_chat_response_handler(response, ctx): { 'type': 'chat:completion', 'data': { - 'content': serialize_output(output), 'output': output, }, } @@ -5113,7 +5134,6 @@ async def streaming_chat_response_handler(response, ctx): ) data = { 'done': True, - 'content': serialize_output(output), 'output': output, 'title': title, **({'usage': usage} if usage else {}), @@ -5127,7 +5147,6 @@ async def streaming_chat_response_handler(response, ctx): metadata['message_id'], { 'done': True, - 'content': serialize_output(output), 'output': output, **({'usage': usage} if usage else {}), }, @@ -5146,18 +5165,19 @@ async def streaming_chat_response_handler(response, ctx): ) # Send a webhook notification if the user is not active - if request.app.state.config.ENABLE_USER_WEBHOOKS and not await Users.is_user_active(user.id): + if await Config.get('ui.enable_user_webhooks') and not await Users.is_user_active(user.id): webhook_url = await Users.get_user_webhook_url_by_id(user.id) if webhook_url: + webui_url = await Config.get('webui.url') await post_webhook( request.app.state.WEBUI_NAME, webhook_url, - f'{content}\n\n{title} - {request.app.state.config.WEBUI_URL}/c/{metadata["chat_id"]}', + f'{content}\n\n{title} - {webui_url}/c/{metadata["chat_id"]}', { 'action': 'chat', 'message': content, 'title': title, - 'url': f'{request.app.state.config.WEBUI_URL}/c/{metadata["chat_id"]}', + 'url': f'{webui_url}/c/{metadata["chat_id"]}', }, ) @@ -5169,7 +5189,6 @@ async def streaming_chat_response_handler(response, ctx): ) ctx['assistant_message'] = { - 'content': serialize_output(output), 'output': output, **({'usage': usage} if usage else {}), } @@ -5197,7 +5216,6 @@ async def streaming_chat_response_handler(response, ctx): metadata['message_id'], { 'done': True, - 'content': serialize_output(output), 'output': output, }, ) @@ -5225,6 +5243,8 @@ async def streaming_chat_response_handler(response, ctx): def wrap_item(item): return f'data: {item}\n\n' + assistant_message = {} + for event in events: event, _ = await process_filter_functions( request=request, @@ -5247,8 +5267,14 @@ async def streaming_chat_response_handler(response, ctx): ) if data: + if ENABLE_API_OUTLET_FILTERS: + update_assistant_message_from_stream(assistant_message, data) yield data + if ENABLE_API_OUTLET_FILTERS and assistant_message: + ctx['assistant_message'] = assistant_message + await outlet_filter_handler(ctx) + return StreamingResponse( stream_wrapper(response.body_iterator, events), headers=dict(response.headers), diff --git a/backend/open_webui/utils/misc.py b/backend/open_webui/utils/misc.py index d5d8078bed..509663fcfb 100644 --- a/backend/open_webui/utils/misc.py +++ b/backend/open_webui/utils/misc.py @@ -69,6 +69,44 @@ def is_string_allowed(string: Union[str, Sequence[str]], filter_list: list[str | return True +def _host_matches_pattern(host: str, pattern: str) -> bool: + """Match a hostname against a filter entry on DNS label boundaries. + + `pattern` matches `host` when equal or a parent domain of it, so `corp.com` + matches `api.corp.com` but not `evilcorp.com`, and an IP literal matches only + itself. Avoids the raw-suffix confusion of a plain endswith. + """ + host = (host or '').strip().lower().rstrip('.') + pattern = (pattern or '').strip().lower().rstrip('.') + if not host or not pattern: + return False + return host == pattern or host.endswith('.' + pattern) + + +def is_host_allowed(host: Union[str, Sequence[str]], filter_list: list[str | None] = None) -> bool: + """Allow/block a hostname (or list of hostnames / resolved IPs) against a + WEB_FETCH_FILTER_LIST-style filter, matching on label boundaries. + + Pass a parsed hostname, never a full URL: matching against a URL lets a path + component defeat the filter (e.g. ``https://blocked.example/x`` ends with ``/x``, + not the blocked host). Entries prefixed with ``!`` are blocked; the rest form an allowlist. + """ + if not filter_list: + return True + + allow_list, block_list = get_allow_block_lists(filter_list) + hosts = [host] if isinstance(host, str) else list(host or []) + + if allow_list: + if not any(_host_matches_pattern(h, allowed) for h in hosts for allowed in allow_list): + return False + + if any(_host_matches_pattern(h, blocked) for h in hosts for blocked in block_list): + return False + + return True + + def get_message_list(messages_map, message_id): """ Reconstructs a list of messages in order up to the specified message_id. @@ -212,10 +250,11 @@ def convert_output_to_messages( pending_tool_calls = [] pending_content = [] pending_reasoning = [] # Only populated when reasoning_format == 'reasoning_content' + pending_reasoning_details = [] def flush_pending(): - nonlocal pending_content, pending_tool_calls, pending_reasoning - if not pending_content and not pending_tool_calls and not pending_reasoning: + nonlocal pending_content, pending_tool_calls, pending_reasoning, pending_reasoning_details + if not pending_content and not pending_tool_calls and not pending_reasoning and not pending_reasoning_details: return message = { @@ -227,10 +266,14 @@ def convert_output_to_messages( if pending_reasoning: message['reasoning_content'] = '\n'.join(pending_reasoning) + if pending_reasoning_details: + message['reasoning_details'] = pending_reasoning_details + messages.append(message) pending_content = [] pending_tool_calls = [] pending_reasoning = [] + pending_reasoning_details = [] for item in output: item_type = item.get('type', '') @@ -301,7 +344,8 @@ def convert_output_to_messages( ) elif item_type == 'reasoning': - if not reasoning_format: + reasoning_details = item.get('reasoning_details') if raw else None + if not reasoning_format and not reasoning_details: continue reasoning_text = '' @@ -322,6 +366,11 @@ def convert_output_to_messages( # llama.cpp: collect for reasoning_content field pending_reasoning.append(reasoning_text) + if reasoning_details: + pending_reasoning_details.extend( + reasoning_details if isinstance(reasoning_details, list) else [reasoning_details] + ) + elif item_type == 'open_webui:code_interpreter': # Always include code interpreter content so the LLM knows # the code was already executed and doesn't retry. diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 60c5836637..39e139b053 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -12,6 +12,7 @@ from open_webui.config import ( from open_webui.env import BYPASS_MODEL_ACCESS_CONTROL, GLOBAL_LOG_LEVEL from open_webui.functions import get_function_models from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.functions import Functions from open_webui.models.groups import Groups from open_webui.models.models import Models @@ -20,8 +21,8 @@ from open_webui.routers import ollama, openai from open_webui.socket.utils import RedisDict from open_webui.utils.access_control import has_access, has_base_model_access from open_webui.utils.plugin import ( + get_functions_cache, get_function_module_from_cache, - load_function_module_by_id, ) logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL) @@ -52,16 +53,9 @@ async def fetch_openai_models(request: Request, user: UserModel = None): async def get_all_base_models(request: Request, user: UserModel = None): - openai_task = ( - fetch_openai_models(request, user) - if request.app.state.config.ENABLE_OPENAI_API - else asyncio.sleep(0, result=[]) - ) - ollama_task = ( - fetch_ollama_models(request, user) - if request.app.state.config.ENABLE_OLLAMA_API - else asyncio.sleep(0, result=[]) - ) + config = await Config.get_many('openai.enable', 'ollama.enable') + openai_task = fetch_openai_models(request, user) if config.get('openai.enable') else asyncio.sleep(0, result=[]) + ollama_task = fetch_ollama_models(request, user) if config.get('ollama.enable') else asyncio.sleep(0, result=[]) function_task = get_function_models(request) openai_models, ollama_models, function_models = await asyncio.gather(openai_task, ollama_task, function_task) @@ -70,15 +64,23 @@ async def get_all_base_models(request: Request, user: UserModel = None): async def get_all_models(request, refresh: bool = False, user: UserModel = None): + config = await Config.get_many( + 'models.base_models_cache', + 'evaluation.arena.enable', + 'evaluation.arena.models', + ) if ( request.app.state.MODELS and request.app.state.BASE_MODELS - and (request.app.state.config.ENABLE_BASE_MODELS_CACHE and not refresh) + and (config.get('models.base_models_cache') and not refresh) ): base_models = request.app.state.BASE_MODELS else: base_models = await get_all_base_models(request, user=user) - request.app.state.BASE_MODELS = base_models + if base_models: + request.app.state.BASE_MODELS = base_models + else: + base_models = request.app.state.BASE_MODELS # deep copy the base models to avoid modifying the original list models = [model.copy() for model in base_models] @@ -88,9 +90,10 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) return [] # Add arena models - if request.app.state.config.ENABLE_EVALUATION_ARENA_MODELS: + if config.get('evaluation.arena.enable'): arena_models = [] - if len(request.app.state.config.EVALUATION_ARENA_MODELS) > 0: + arena_config = config.get('evaluation.arena.models') or [] + if len(arena_config) > 0: arena_models = [ { 'id': model['id'], @@ -103,7 +106,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) 'owned_by': 'arena', 'arena': True, } - for model in request.app.state.config.EVALUATION_ARENA_MODELS + for model in arena_config ] else: # Add default arena model @@ -289,7 +292,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) # Apply global model defaults to all models # Per-model overrides take precedence over global defaults - default_metadata = getattr(request.app.state.config, 'DEFAULT_MODEL_METADATA', None) or {} + default_metadata = await Config.get('models.default_metadata', {}) or {} if default_metadata: for model in models: @@ -311,10 +314,11 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) # Batch-fetch all function valves in one query to avoid N+1 DB hits # inside get_action_priority (previously called per action × per model). all_function_valves = await Functions.get_function_valves_by_ids(list(all_function_ids)) + functions_cache = get_functions_cache(request) def get_action_priority(action_id): try: - function_module = request.app.state.FUNCTIONS.get(action_id) + function_module = functions_cache.get(action_id) if function_module and hasattr(function_module, 'Valves'): valves_db = all_function_valves.get(action_id) valves = function_module.Valves(**(valves_db if valves_db else {})) @@ -344,7 +348,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) log.info(f'Action not found: {action_id}') continue - function_module = request.app.state.FUNCTIONS.get(action_id) + function_module = functions_cache.get(action_id) if function_module is None: log.info(f'Failed to load action module: {action_id}') continue @@ -357,7 +361,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) log.info(f'Filter not found: {filter_id}') continue - function_module = request.app.state.FUNCTIONS.get(filter_id) + function_module = functions_cache.get(filter_id) if function_module is None: log.info(f'Failed to load filter module: {filter_id}') continue @@ -368,7 +372,11 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) models_dict = {model['id']: model for model in models} if isinstance(request.app.state.MODELS, RedisDict): - request.app.state.MODELS.set(models_dict) + try: + request.app.state.MODELS.set(models_dict) + except Exception as e: + log.warning(f'Failed to update Redis model cache, using in-process cache: {e}') + request.app.state.MODELS = models_dict else: request.app.state.MODELS = models_dict diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index f2e1aa14f6..67b66d1a0d 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -1,18 +1,17 @@ +import asyncio import base64 -import copy import fnmatch import hashlib import json import logging -import mimetypes import re -import secrets import sys import time import urllib import uuid from dataclasses import dataclass, field from datetime import datetime, timedelta +from types import SimpleNamespace from typing import Literal, Optional import aiohttp @@ -62,9 +61,9 @@ from open_webui.config import ( OAUTH_UPDATE_PICTURE_ON_LOGIN, OAUTH_USERNAME_CLAIM, WEBHOOK_URL, - AppConfig, ) -from open_webui.constants import ERROR_MESSAGES, WEBHOOK_MESSAGES +from open_webui.constants import ERROR_MESSAGES +from open_webui.events import EVENTS, publish_event from open_webui.env import ( AIOHTTP_CLIENT_ALLOW_REDIRECTS, AIOHTTP_CLIENT_SESSION_SSL, @@ -75,9 +74,9 @@ from open_webui.env import ( REDIS_KEY_PREFIX, WEBUI_AUTH_COOKIE_SAME_SITE, WEBUI_AUTH_COOKIE_SECURE, - WEBUI_NAME, ) from open_webui.models.auths import Auths +from open_webui.models.config import Config from open_webui.models.groups import GroupForm, GroupModel, Groups, GroupUpdateForm from open_webui.models.oauth_sessions import OAuthSessions from open_webui.models.users import Users @@ -85,7 +84,7 @@ from open_webui.retrieval.web.utils import validate_url from open_webui.utils.auth import create_token, get_password_hash from open_webui.utils.groups import apply_default_group_assignment from open_webui.utils.misc import parse_duration -from open_webui.utils.webhook import post_webhook +from open_webui.utils.validate import validate_profile_image_url from starlette.responses import RedirectResponse @@ -94,9 +93,13 @@ class OAuthClientMetadata(MCPOAuthClientMetadata): pass +OAuthResourceParameterMode = Literal['auto', 'include', 'omit'] + + class OAuthClientInformationFull(OAuthClientMetadata): issuer: Optional[str] = None # URL of the OAuth server that issued this client resource: Optional[str] = None # RFC 8707 resource indicator for JWT audience + oauth_resource_parameter: OAuthResourceParameterMode = 'auto' client_id: str client_secret: str | None = None @@ -111,31 +114,72 @@ from open_webui.env import GLOBAL_LOG_LEVEL logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL) log = logging.getLogger(__name__) -auth_manager_config = AppConfig() -auth_manager_config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE -auth_manager_config.ENABLE_OAUTH_SIGNUP = ENABLE_OAUTH_SIGNUP -auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE -auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL = OAUTH_MERGE_ACCOUNTS_BY_EMAIL -auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT -auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT = ENABLE_OAUTH_GROUP_MANAGEMENT -auth_manager_config.ENABLE_OAUTH_GROUP_CREATION = ENABLE_OAUTH_GROUP_CREATION -auth_manager_config.OAUTH_GROUP_DEFAULT_SHARE = OAUTH_GROUP_DEFAULT_SHARE -auth_manager_config.OAUTH_BLOCKED_GROUPS = OAUTH_BLOCKED_GROUPS -auth_manager_config.OAUTH_ROLES_CLAIM = OAUTH_ROLES_CLAIM -auth_manager_config.OAUTH_SUB_CLAIM = OAUTH_SUB_CLAIM -auth_manager_config.OAUTH_GROUPS_CLAIM = OAUTH_GROUPS_CLAIM -auth_manager_config.OAUTH_EMAIL_CLAIM = OAUTH_EMAIL_CLAIM -auth_manager_config.OAUTH_PICTURE_CLAIM = OAUTH_PICTURE_CLAIM -auth_manager_config.OAUTH_USERNAME_CLAIM = OAUTH_USERNAME_CLAIM -auth_manager_config.OAUTH_ALLOWED_ROLES = OAUTH_ALLOWED_ROLES -auth_manager_config.OAUTH_ADMIN_ROLES = OAUTH_ADMIN_ROLES -auth_manager_config.OAUTH_ALLOWED_DOMAINS = OAUTH_ALLOWED_DOMAINS -auth_manager_config.WEBHOOK_URL = WEBHOOK_URL -auth_manager_config.JWT_EXPIRES_IN = JWT_EXPIRES_IN -auth_manager_config.OAUTH_UPDATE_PICTURE_ON_LOGIN = OAUTH_UPDATE_PICTURE_ON_LOGIN -auth_manager_config.OAUTH_UPDATE_NAME_ON_LOGIN = OAUTH_UPDATE_NAME_ON_LOGIN -auth_manager_config.OAUTH_UPDATE_EMAIL_ON_LOGIN = OAUTH_UPDATE_EMAIL_ON_LOGIN -auth_manager_config.OAUTH_AUDIENCE = OAUTH_AUDIENCE +OAUTH_RESOURCE_PARAMETER_MODES = {'auto', 'include', 'omit'} + +OAUTH_RUNTIME_CONFIG = { + 'DEFAULT_USER_ROLE': ('ui.default_user_role', DEFAULT_USER_ROLE), + 'ENABLE_OAUTH_SIGNUP': ('oauth.enable_signup', ENABLE_OAUTH_SIGNUP), + 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE': ( + 'oauth.refresh_token.include_scope', + OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE, + ), + 'OAUTH_MERGE_ACCOUNTS_BY_EMAIL': ( + 'oauth.merge_accounts_by_email', + OAUTH_MERGE_ACCOUNTS_BY_EMAIL, + ), + 'ENABLE_OAUTH_ROLE_MANAGEMENT': ( + 'oauth.enable_role_mapping', + ENABLE_OAUTH_ROLE_MANAGEMENT, + ), + 'ENABLE_OAUTH_GROUP_MANAGEMENT': ( + 'oauth.enable_group_mapping', + ENABLE_OAUTH_GROUP_MANAGEMENT, + ), + 'ENABLE_OAUTH_GROUP_CREATION': ( + 'oauth.enable_group_creation', + ENABLE_OAUTH_GROUP_CREATION, + ), + 'OAUTH_GROUP_DEFAULT_SHARE': ( + 'oauth.group_default_share', + OAUTH_GROUP_DEFAULT_SHARE, + ), + 'OAUTH_BLOCKED_GROUPS': ('oauth.blocked_groups', OAUTH_BLOCKED_GROUPS), + 'OAUTH_ROLES_CLAIM': ('oauth.roles_claim', OAUTH_ROLES_CLAIM), + 'OAUTH_SUB_CLAIM': ('oauth.sub_claim', OAUTH_SUB_CLAIM), + 'OAUTH_GROUPS_CLAIM': ('oauth.group_claim', OAUTH_GROUPS_CLAIM), + 'OAUTH_EMAIL_CLAIM': ('oauth.email_claim', OAUTH_EMAIL_CLAIM), + 'OAUTH_PICTURE_CLAIM': ('oauth.picture_claim', OAUTH_PICTURE_CLAIM), + 'OAUTH_USERNAME_CLAIM': ('oauth.username_claim', OAUTH_USERNAME_CLAIM), + 'OAUTH_ALLOWED_ROLES': ('oauth.allowed_roles', OAUTH_ALLOWED_ROLES), + 'OAUTH_ADMIN_ROLES': ('oauth.admin_roles', OAUTH_ADMIN_ROLES), + 'OAUTH_ALLOWED_DOMAINS': ('oauth.allowed_domains', OAUTH_ALLOWED_DOMAINS), + 'WEBHOOK_URL': ('webhook_url', WEBHOOK_URL), + 'JWT_EXPIRES_IN': ('auth.jwt_expiry', JWT_EXPIRES_IN), + 'OAUTH_UPDATE_PICTURE_ON_LOGIN': ( + 'oauth.update_picture_on_login', + OAUTH_UPDATE_PICTURE_ON_LOGIN, + ), + 'OAUTH_UPDATE_NAME_ON_LOGIN': ( + 'oauth.update_name_on_login', + OAUTH_UPDATE_NAME_ON_LOGIN, + ), + 'OAUTH_UPDATE_EMAIL_ON_LOGIN': ( + 'oauth.update_email_on_login', + OAUTH_UPDATE_EMAIL_ON_LOGIN, + ), + 'OAUTH_AUDIENCE': ('oauth.audience', OAUTH_AUDIENCE), +} + + +def _default_value(value): + return getattr(value, 'value', value) + + +async def get_oauth_runtime_config() -> SimpleNamespace: + keys = [key for key, _default in OAUTH_RUNTIME_CONFIG.values()] + stored = await Config.get_many(*keys) + values = {name: stored.get(key, _default_value(default)) for name, (key, default) in OAUTH_RUNTIME_CONFIG.items()} + return SimpleNamespace(**values) # Conservative default when the provider omits both expires_in and expires_at. @@ -325,53 +369,57 @@ async def get_protected_resource_metadata(server_url: str) -> ProtectedResourceM headers={'Content-Type': 'application/json'}, ssl=AIOHTTP_CLIENT_SESSION_SSL, ) as response: - if response.status == 401: - resource_metadata_urls = [] - match = re.search( - r'resource_metadata=(?:"([^"]+)"|([^\s,]+))', - response.headers.get('WWW-Authenticate', ''), - ) - if match: - resource_metadata_urls = [match.group(1) or match.group(2)] - log.debug(f'Found resource_metadata URL: {resource_metadata_urls[0]}') - else: - # Fall back to well-known resource metadata URIs (RFC 9728 §4.2) - parsed, base_url = get_parsed_and_base_url(server_url) - if parsed.path and parsed.path != '/': - path = parsed.path.rstrip('/') - resource_metadata_urls.append( - urllib.parse.urljoin(base_url, f'/.well-known/oauth-protected-resource{path}') - ) + # Discover Protected Resource Metadata regardless of HTTP status. + # A 401 carries a WWW-Authenticate header pointing at the PRM, but + # some MCP servers (e.g. Google's gmail/drive/calendar remote MCPs) + # answer 200 to an anonymous `initialize`, so we must still fall + # back to the RFC 9728 well-known URIs when there is no 401/header. + resource_metadata_urls = [] + match = re.search( + r'resource_metadata=(?:"([^"]+)"|([^\s,]+))', + response.headers.get('WWW-Authenticate', ''), + ) + if match: + resource_metadata_urls = [match.group(1) or match.group(2)] + log.debug(f'Found resource_metadata URL: {resource_metadata_urls[0]}') + else: + # Fall back to well-known resource metadata URIs (RFC 9728 §4.2) + parsed, base_url = get_parsed_and_base_url(server_url) + if parsed.path and parsed.path != '/': + path = parsed.path.rstrip('/') resource_metadata_urls.append( - urllib.parse.urljoin(base_url, '/.well-known/oauth-protected-resource') + urllib.parse.urljoin(base_url, f'/.well-known/oauth-protected-resource{path}') ) - log.debug(f'No resource_metadata in header, trying well-known URIs: {resource_metadata_urls}') + resource_metadata_urls.append( + urllib.parse.urljoin(base_url, '/.well-known/oauth-protected-resource') + ) + log.debug(f'No resource_metadata in header, trying well-known URIs: {resource_metadata_urls}') - # Fetch Protected Resource metadata from candidate URLs - for resource_metadata_url in resource_metadata_urls: - try: - async with session.get( - resource_metadata_url, ssl=AIOHTTP_CLIENT_SESSION_SSL - ) as resource_response: - if resource_response.status == 200: - resource_metadata = await resource_response.json() + # Fetch Protected Resource metadata from candidate URLs + for resource_metadata_url in resource_metadata_urls: + try: + async with session.get( + resource_metadata_url, ssl=AIOHTTP_CLIENT_SESSION_SSL + ) as resource_response: + if resource_response.status == 200: + resource_metadata = await resource_response.json() - resource = resource_metadata.get('resource') or None - if resource: - log.debug(f'Discovered resource indicator: {resource}') + resource = resource_metadata.get('resource') or None + if resource: + log.debug(f'Discovered resource indicator: {resource}') - servers = resource_metadata.get('authorization_servers', []) - scopes = resource_metadata.get('scopes_supported', []) - if scopes: - log.debug(f'Discovered resource scopes: {scopes}') + servers = resource_metadata.get('authorization_servers', []) + scopes = resource_metadata.get('scopes_supported', []) + if scopes: + log.debug(f'Discovered resource scopes: {scopes}') - if servers: - authorization_servers = servers - log.debug(f'Discovered authorization servers: {servers}') - break - except Exception as e: - log.debug(f'Failed to fetch resource metadata from {resource_metadata_url}: {e}') - continue + if servers: + authorization_servers = servers + log.debug(f'Discovered authorization servers: {servers}') + break + except Exception as e: + log.debug(f'Failed to fetch resource metadata from {resource_metadata_url}: {e}') + continue except Exception as e: log.debug(f'MCP Protected Resource discovery failed: {e}') @@ -418,12 +466,14 @@ async def get_oauth_client_info_with_dynamic_client_registration( client_id: str, oauth_server_url: str, oauth_server_key: Optional[str] = None, + oauth_scope: str | None = None, ) -> OAuthClientInformationFull: try: oauth_server_metadata = None oauth_server_metadata_url = None - redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/') + webui_url = await Config.get('webui.url') + redirect_base_url = (str(webui_url or request.base_url)).rstrip('/') oauth_client_metadata = OAuthClientMetadata( client_name='Open WebUI', @@ -435,6 +485,16 @@ async def get_oauth_client_info_with_dynamic_client_registration( # Attempt to fetch OAuth server metadata to get registration endpoint & scopes resource_metadata = await get_protected_resource_metadata(oauth_server_url) resource = resource_metadata.resource + + # Prefer the resource-specific scopes from the Protected Resource Metadata + # (RFC 9728) over the AS's full scopes_supported catalog, for least + # privilege. Mirrors the static-credentials flow (#24690). + scope_override = ' '.join(oauth_scope.replace(',', ' ').split()) if oauth_scope else None + if scope_override: + oauth_client_metadata.scope = scope_override + elif resource_metadata.scopes_supported: + oauth_client_metadata.scope = ' '.join(resource_metadata.scopes_supported) + discovery_urls = resource_metadata.get_discovery_urls(oauth_server_url) for url in discovery_urls: async with aiohttp.ClientSession(trust_env=True) as session: @@ -532,6 +592,7 @@ async def get_oauth_client_info_with_static_credentials( oauth_server_url: str, oauth_client_id: str, oauth_client_secret: str, + oauth_scope: str | None = None, ) -> OAuthClientInformationFull: """ Build an OAuthClientInformationFull from user-provided static credentials. @@ -542,7 +603,8 @@ async def get_oauth_client_info_with_static_credentials( oauth_server_metadata = None oauth_server_metadata_url = None - redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/') + webui_url = await Config.get('webui.url') + redirect_base_url = (str(webui_url or request.base_url)).rstrip('/') redirect_uri = f'{redirect_base_url}/oauth/clients/{client_id}/callback' # Discover server metadata (authorization endpoint, token endpoint, scopes, etc.) @@ -565,7 +627,9 @@ async def get_oauth_client_info_with_static_credentials( # Unlike the Authorization Server's scopes_supported (which is a full catalog # of every scope the server can grant), the PRM scopes_supported represents # what this specific resource requires — making it safe to request them all. - scope = ' '.join(resource_metadata.scopes_supported) if resource_metadata.scopes_supported else None + scope = (' '.join(oauth_scope.replace(',', ' ').split()) if oauth_scope else None) or ( + ' '.join(resource_metadata.scopes_supported) if resource_metadata.scopes_supported else None + ) # Determine token_endpoint_auth_method token_endpoint_auth_method = 'client_secret_post' @@ -605,7 +669,7 @@ def resolve_oauth_client_info(connection: dict) -> dict: For oauth_2.1_static, overlays admin-provided credentials from info.oauth_client_id and info.oauth_client_secret onto the blob. """ - info = connection.get('info', {}) + info = connection.get('info') or {} data = decrypt_data(info.get('oauth_client_info', '')) if connection.get('auth_type') == 'oauth_2.1_static': @@ -616,6 +680,94 @@ def resolve_oauth_client_info(connection: dict) -> dict: return data +def normalize_oauth_resource_parameter(value: str | None) -> OAuthResourceParameterMode: + if value in OAUTH_RESOURCE_PARAMETER_MODES: + return value + return 'auto' + + +def get_connection_oauth_resource_parameter(connection: dict) -> OAuthResourceParameterMode: + info = connection.get('info') or {} + config = connection.get('config') or {} + return normalize_oauth_resource_parameter( + info.get('oauth_resource_parameter') or config.get('oauth_resource_parameter') + ) + + +def apply_connection_oauth_options(connection: dict, oauth_client_info: dict) -> dict: + info = connection.get('info') or {} + config = connection.get('config') or {} + oauth_scope = info.get('oauth_scope') or config.get('oauth_scope') + oauth_scope = ' '.join(oauth_scope.replace(',', ' ').split()) if oauth_scope else None + + options = { + **oauth_client_info, + 'oauth_resource_parameter': get_connection_oauth_resource_parameter(connection), + } + if oauth_scope: + options['scope'] = oauth_scope + return options + + +def scope_has_resource_indicator(scope: str | None) -> bool: + if not scope: + return False + return any(scope_value.startswith(('https://', 'http://', 'api://')) for scope_value in scope.split()) + + +def should_send_oauth_resource(client_info: OAuthClientInformationFull | None) -> bool: + if not client_info or not client_info.resource: + return False + + mode = normalize_oauth_resource_parameter(client_info.oauth_resource_parameter) + if mode == 'omit': + return False + if mode == 'include': + return True + + return not scope_has_resource_indicator(client_info.scope) + + +def build_oauth_request_params(client_info: OAuthClientInformationFull | None) -> dict: + if not client_info: + return {} + + params = {} + if client_info.scope: + params['scope'] = client_info.scope + if should_send_oauth_resource(client_info): + params['resource'] = client_info.resource + return params + + +async def recover_static_oauth_client_metadata(connection: dict, oauth_client_info: dict) -> dict: + if connection.get('auth_type') != 'oauth_2.1_static': + return oauth_client_info + + if oauth_client_info.get('scope') and oauth_client_info.get('resource'): + return oauth_client_info + + server_url = connection.get('url') + if not server_url: + return oauth_client_info + + try: + resource_metadata = await get_protected_resource_metadata(server_url) + except Exception as e: + log.debug(f'Unable to recover static OAuth metadata for {server_url}: {e}') + return oauth_client_info + + recovered = {**oauth_client_info} + if not recovered.get('scope') and resource_metadata.scopes_supported: + recovered['scope'] = ' '.join(resource_metadata.scopes_supported) + log.info(f'Recovered static OAuth scopes for {server_url} from protected resource metadata') + + if not recovered.get('resource') and resource_metadata.resource: + recovered['resource'] = resource_metadata.resource + + return recovered + + class OAuthClientManager: def __init__(self, app): self.oauth = OAuth() @@ -629,7 +781,7 @@ class OAuthClientManager: 'client_secret': oauth_client_info.client_secret, 'client_kwargs': { 'follow_redirects': True, - **({'timeout': int(OAUTH_CLIENT_TIMEOUT.value)} if OAUTH_CLIENT_TIMEOUT.value else {}), + **({'timeout': int(OAUTH_CLIENT_TIMEOUT)} if OAUTH_CLIENT_TIMEOUT else {}), **({'scope': oauth_client_info.scope} if oauth_client_info.scope else {}), **( {'token_endpoint_auth_method': oauth_client_info.token_endpoint_auth_method} @@ -661,7 +813,7 @@ class OAuthClientManager: } return self.clients[client_id] - def ensure_client_from_config(self, client_id): + async def ensure_client_from_config(self, client_id): """ Lazy-load an OAuth client from the current TOOL_SERVER_CONNECTIONS config if it hasn't been registered on this node yet. @@ -670,7 +822,7 @@ class OAuthClientManager: return self.clients[client_id]['client'] try: - connections = getattr(self.app.state.config, 'TOOL_SERVER_CONNECTIONS', []) + connections = await Config.get('tool_server.connections', []) except Exception: connections = [] @@ -680,7 +832,7 @@ class OAuthClientManager: if connection.get('auth_type', 'none') not in ('oauth_2.1', 'oauth_2.1_static'): continue - server_id = connection.get('info', {}).get('id') + server_id = (connection.get('info') or {}).get('id') if not server_id: continue @@ -688,12 +840,14 @@ class OAuthClientManager: if client_id != expected_client_id: continue - oauth_client_info = connection.get('info', {}).get('oauth_client_info', '') + oauth_client_info = (connection.get('info') or {}).get('oauth_client_info', '') if not oauth_client_info: continue try: oauth_client_info = resolve_oauth_client_info(connection) + oauth_client_info = await recover_static_oauth_client_metadata(connection, oauth_client_info) + oauth_client_info = apply_connection_oauth_options(connection, oauth_client_info) return self.add_client(expected_client_id, OAuthClientInformationFull(**oauth_client_info))['client'] except Exception as e: log.error(f'Failed to lazily add OAuth client {expected_client_id} from config: {e}') @@ -727,7 +881,8 @@ class OAuthClientManager: redirect_uri = str(client_info.redirect_uris[0]) try: - auth_data = await client.create_authorization_url(redirect_uri=redirect_uri) + kwargs = build_oauth_request_params(client_info) + auth_data = await client.create_authorization_url(redirect_uri=redirect_uri, **kwargs) authorization_url = auth_data.get('url') if not authorization_url: @@ -765,7 +920,16 @@ class OAuthClientManager: error_message = f'{error or ""} {error_description or ""}'.lower() - if any(keyword in error_message for keyword in ('invalid_client', 'invalid client', 'client id')): + if any( + keyword in error_message + for keyword in ( + 'invalid_client', + 'invalid client', + 'client id', + 'redirect_uri', + 'redirect uri', + ) + ): log.warning( f'OAuth client preflight detected invalid registration for {client_info.client_id}: {error} {error_description}' ) @@ -776,22 +940,22 @@ class OAuthClientManager: return True - def get_client(self, client_id): + async def get_client(self, client_id): if client_id not in self.clients: - self.ensure_client_from_config(client_id) + await self.ensure_client_from_config(client_id) client = self.clients.get(client_id) return client['client'] if client else None - def get_client_info(self, client_id): + async def get_client_info(self, client_id): if client_id not in self.clients: - self.ensure_client_from_config(client_id) + await self.ensure_client_from_config(client_id) client = self.clients.get(client_id) return client['client_info'] if client else None - def get_server_metadata_url(self, client_id): - client = self.get_client(client_id) + async def get_server_metadata_url(self, client_id): + client = await self.get_client(client_id) if not client: return None @@ -874,6 +1038,7 @@ class OAuthClientManager: Returns: dict: New token data, or None if refresh failed """ + auth_config = await get_oauth_runtime_config() client_id = session.provider token_data = session.token @@ -882,14 +1047,14 @@ class OAuthClientManager: return None try: - client = self.get_client(client_id) + client = await self.get_client(client_id) if not client: log.error(f'No OAuth client found for provider {client_id}') return None token_endpoint = None async with aiohttp.ClientSession(trust_env=True) as session_http: - async with session_http.get(self.get_server_metadata_url(client_id)) as r: + async with session_http.get(await self.get_server_metadata_url(client_id)) as r: if r.status == 200: openid_data = await r.json() token_endpoint = openid_data.get('token_endpoint') @@ -905,9 +1070,8 @@ class OAuthClientManager: 'refresh_token': token_data['refresh_token'], 'client_id': client.client_id, } - # RFC 8707: include resource indicator so refreshed tokens retain correct audience - client_info = self.get_client_info(client_id) - if client_info and client_info.resource: + client_info = await self.get_client_info(client_id) + if should_send_oauth_resource(client_info): refresh_data['resource'] = client_info.resource if hasattr(client, 'client_secret') and client.client_secret: @@ -917,7 +1081,7 @@ class OAuthClientManager: if ( hasattr(client, 'client_kwargs') and client.client_kwargs.get('scope') - and getattr(self.app.state.config, 'OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE', False) + and auth_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE ): refresh_data['scope'] = client.client_kwargs['scope'] @@ -950,40 +1114,37 @@ class OAuthClientManager: return None async def handle_authorize(self, request, client_id: str) -> RedirectResponse: - client = self.get_client(client_id) or self.ensure_client_from_config(client_id) + client = await self.get_client(client_id) if client is None: raise HTTPException(404) - client_info = self.get_client_info(client_id) + client_info = await self.get_client_info(client_id) if client_info is None: - # ensure_client_from_config registers client_info too - client_info = self.get_client_info(client_id) + # get_client registers client_info too + client_info = await self.get_client_info(client_id) if client_info is None: raise HTTPException(404) redirect_uri = client_info.redirect_uris[0] if client_info.redirect_uris else None redirect_uri_str = str(redirect_uri) if redirect_uri else None - # RFC 8707: pass resource indicator so the IdP sets the correct JWT audience - kwargs = {} - if client_info.resource: - kwargs['resource'] = client_info.resource + # Pass explicit scope/resource parameters for providers that require them. + kwargs = build_oauth_request_params(client_info) return await client.authorize_redirect(request, redirect_uri_str, **kwargs) async def handle_callback(self, request, client_id: str, user_id: str, response): - client = self.get_client(client_id) or self.ensure_client_from_config(client_id) + client = await self.get_client(client_id) if client is None: raise HTTPException(404) error_message = None try: - client_info = self.get_client_info(client_id) + client_info = await self.get_client_info(client_id) # Note: Do NOT pass client_id/client_secret explicitly here. # The Authlib client already has these configured during add_client(). # Passing them again causes Authlib to concatenate them (e.g., "ID1,ID1"), # which results in 401 errors from the token endpoint. (Fix for #19823) - # RFC 8707: pass resource indicator for correct JWT audience on token exchange token_kwargs = {} - if client_info and client_info.resource: + if should_send_oauth_resource(client_info): token_kwargs['resource'] = client_info.resource token = await client.authorize_access_token(request, **token_kwargs) @@ -1028,7 +1189,8 @@ class OAuthClientManager: exc_info=True, ) - redirect_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/') + webui_url = await Config.get('webui.url') + redirect_url = (str(webui_url or request.base_url)).rstrip('/') if error_message: log.debug(error_message) @@ -1157,6 +1319,7 @@ class OAuthManager: """ provider = session.provider token_data = session.token + auth_config = await get_oauth_runtime_config() if not token_data.get('refresh_token'): log.warning(f'No refresh token available for session {session.id}') @@ -1195,7 +1358,7 @@ class OAuthManager: if ( hasattr(client, 'client_kwargs') and client.client_kwargs.get('scope') - and auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE + and auth_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE ): refresh_data['scope'] = client.client_kwargs['scope'] @@ -1228,6 +1391,7 @@ class OAuthManager: return None async def get_user_role(self, user, user_data): + auth_config = await get_oauth_runtime_config() user_count = await Users.get_num_users() if user and user_count == 1: # If the user is the only user, assign the role "admin" - actually repairs role for single user on login @@ -1239,16 +1403,16 @@ class OAuthManager: # default role here (not 'admin') — admin promotion happens # race-safely *after* insert via get_num_users() == 1. log.debug('First user bootstrap: using default role (admin promotion deferred to post-insert)') - return auth_manager_config.DEFAULT_USER_ROLE + return auth_config.DEFAULT_USER_ROLE - if auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT: + if auth_config.ENABLE_OAUTH_ROLE_MANAGEMENT: log.debug('Running OAUTH Role management') - oauth_claim = auth_manager_config.OAUTH_ROLES_CLAIM - oauth_allowed_roles = auth_manager_config.OAUTH_ALLOWED_ROLES - oauth_admin_roles = auth_manager_config.OAUTH_ADMIN_ROLES + oauth_claim = auth_config.OAUTH_ROLES_CLAIM + oauth_allowed_roles = auth_config.OAUTH_ALLOWED_ROLES + oauth_admin_roles = auth_config.OAUTH_ADMIN_ROLES oauth_roles = [] # Default/fallback role if no matching roles are found - role = auth_manager_config.DEFAULT_USER_ROLE + role = auth_config.DEFAULT_USER_ROLE # Next block extracts the roles from the user data, accepting nested claims of any depth if oauth_claim and oauth_allowed_roles and oauth_admin_roles: @@ -1306,7 +1470,7 @@ class OAuthManager: else: if not user: # If role management is disabled, use the default role for new users - role = auth_manager_config.DEFAULT_USER_ROLE + role = auth_config.DEFAULT_USER_ROLE else: # If role management is disabled, use the existing role for existing users role = user.role @@ -1314,11 +1478,12 @@ class OAuthManager: return role async def update_user_groups(self, user, user_data, default_permissions, db=None): + auth_config = await get_oauth_runtime_config() log.debug('Running OAUTH Group management') - oauth_claim = auth_manager_config.OAUTH_GROUPS_CLAIM + oauth_claim = auth_config.OAUTH_GROUPS_CLAIM try: - blocked_groups = json.loads(auth_manager_config.OAUTH_BLOCKED_GROUPS) + blocked_groups = json.loads(auth_config.OAUTH_BLOCKED_GROUPS) except Exception as e: log.exception(f'Error loading OAUTH_BLOCKED_GROUPS: {e}') blocked_groups = [] @@ -1346,7 +1511,7 @@ class OAuthManager: all_available_groups: list[GroupModel] = await Groups.get_all_groups(db=db) # Create groups if they don't exist and creation is enabled - if auth_manager_config.ENABLE_OAUTH_GROUP_CREATION: + if auth_config.ENABLE_OAUTH_GROUP_CREATION: log.debug('Checking for missing groups to create...') all_group_names = {g.name for g in all_available_groups} groups_created = False @@ -1363,7 +1528,7 @@ class OAuthManager: name=group_name, description=f"Group '{group_name}' created automatically via OAuth.", permissions=default_permissions, # Use default permissions from function args - data={'config': {'share': auth_manager_config.OAUTH_GROUP_DEFAULT_SHARE}}, + data={'config': {'share': auth_config.OAUTH_GROUP_DEFAULT_SHARE}}, ) # Use determined creator ID (admin or fallback to current user) created_group = await Groups.insert_new_group(creator_id, new_group_form, db=db) @@ -1459,7 +1624,7 @@ class OAuthManager: return '/user.png' try: - validate_url(picture_url) + await asyncio.to_thread(validate_url, picture_url) get_kwargs = {} if access_token: @@ -1475,12 +1640,17 @@ class OAuthManager: allow_redirects=AIOHTTP_CLIENT_ALLOW_REDIRECTS, ) as resp: if resp.ok: + upstream_mime = (resp.headers.get('Content-Type', '') or '').split(';', 1)[0].strip().lower() picture = await resp.read() base64_encoded_picture = base64.b64encode(picture).decode('utf-8') - guessed_mime_type = mimetypes.guess_type(picture_url)[0] - if guessed_mime_type is None: - guessed_mime_type = 'image/jpeg' - return f'data:{guessed_mime_type};base64,{base64_encoded_picture}' + try: + return validate_profile_image_url(f'data:{upstream_mime};base64,{base64_encoded_picture}') + except ValueError: + log.warning( + f'Rejected OAuth profile picture from {picture_url}: ' + f'MIME {upstream_mime!r} is not allowed' + ) + return '/user.png' else: log.warning(f'Failed to fetch profile picture from {picture_url}') return '/user.png' @@ -1489,6 +1659,7 @@ class OAuthManager: return '/user.png' async def handle_login(self, request, provider): + auth_config = await get_oauth_runtime_config() if provider not in OAUTH_PROVIDERS: raise HTTPException(404) # If the provider has a custom redirect URL, use that, otherwise automatically generate one @@ -1500,14 +1671,15 @@ class OAuthManager: ) kwargs = {} - if auth_manager_config.OAUTH_AUDIENCE: - kwargs['audience'] = auth_manager_config.OAUTH_AUDIENCE + if auth_config.OAUTH_AUDIENCE: + kwargs['audience'] = auth_config.OAUTH_AUDIENCE if OAUTH_AUTHORIZE_PARAMS: kwargs.update(OAUTH_AUTHORIZE_PARAMS) return await client.authorize_redirect(request, redirect_uri, **kwargs) async def handle_callback(self, request, provider, response, db=None): + auth_config = await get_oauth_runtime_config() if provider not in OAUTH_PROVIDERS: raise HTTPException(404) @@ -1561,8 +1733,8 @@ class OAuthManager: id_token_claims = dict(user_data) if user_data else {} if ( (not user_data) - or (auth_manager_config.OAUTH_EMAIL_CLAIM not in user_data) - or (auth_manager_config.OAUTH_USERNAME_CLAIM not in user_data) + or (auth_config.OAUTH_EMAIL_CLAIM not in user_data) + or (auth_config.OAUTH_USERNAME_CLAIM not in user_data) ): user_data: UserInfo = await client.userinfo(token=token) # Merge back ID token claims that the userinfo endpoint doesn't @@ -1578,8 +1750,8 @@ class OAuthManager: raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) # Extract the "sub" claim, using custom claim if configured - if auth_manager_config.OAUTH_SUB_CLAIM: - sub = user_data.get(auth_manager_config.OAUTH_SUB_CLAIM) + if auth_config.OAUTH_SUB_CLAIM: + sub = user_data.get(auth_config.OAUTH_SUB_CLAIM) else: # Fallback to the default sub claim if not configured sub = user_data.get(OAUTH_PROVIDERS[provider].get('sub_claim', 'sub')) @@ -1593,7 +1765,7 @@ class OAuthManager: } # Email extraction - email_claim = auth_manager_config.OAUTH_EMAIL_CLAIM + email_claim = auth_config.OAUTH_EMAIL_CLAIM email = user_data.get(email_claim, '') # We currently mandate that email addresses are provided if not email: @@ -1635,8 +1807,8 @@ class OAuthManager: email = email.lower() # If allowed domains are configured, check if the email domain is in the list if ( - '*' not in auth_manager_config.OAUTH_ALLOWED_DOMAINS - and email.split('@')[-1] not in auth_manager_config.OAUTH_ALLOWED_DOMAINS + '*' not in auth_config.OAUTH_ALLOWED_DOMAINS + and email.split('@')[-1] not in auth_config.OAUTH_ALLOWED_DOMAINS ): log.warning(f'OAuth callback failed, e-mail domain is not in the list of allowed domains: {user_data}') raise HTTPException(400, detail=ERROR_MESSAGES.INVALID_CRED) @@ -1645,7 +1817,7 @@ class OAuthManager: user = await Users.get_user_by_oauth_sub(provider, sub, db=db) if not user: # If the user does not exist, check if merging is enabled - if auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL: + if auth_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL: # Check if the user exists by email user = await Users.get_user_by_email(email, db=db) if user: @@ -1660,8 +1832,8 @@ class OAuthManager: # to avoid problems with the ENABLE_OAUTH_GROUP_MANAGEMENT check below user.role = determined_role - if auth_manager_config.OAUTH_UPDATE_NAME_ON_LOGIN: - username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM + if auth_config.OAUTH_UPDATE_NAME_ON_LOGIN: + username_claim = auth_config.OAUTH_USERNAME_CLAIM if username_claim: new_name = user_data.get(username_claim) if new_name and new_name != user.name: @@ -1669,8 +1841,8 @@ class OAuthManager: user.name = new_name log.debug(f'Updated name for user {user.email}') - if auth_manager_config.OAUTH_UPDATE_EMAIL_ON_LOGIN: - email_claim = auth_manager_config.OAUTH_EMAIL_CLAIM + if auth_config.OAUTH_UPDATE_EMAIL_ON_LOGIN: + email_claim = auth_config.OAUTH_EMAIL_CLAIM if email_claim: new_email = user_data.get(email_claim) if new_email and new_email.lower() != user.email.lower(): @@ -1685,8 +1857,8 @@ class OAuthManager: log.debug(f'Updated email for user {user.id}') # Update profile picture if enabled and different from current - if auth_manager_config.OAUTH_UPDATE_PICTURE_ON_LOGIN: - picture_claim = auth_manager_config.OAUTH_PICTURE_CLAIM + if auth_config.OAUTH_UPDATE_PICTURE_ON_LOGIN: + picture_claim = auth_config.OAUTH_PICTURE_CLAIM if picture_claim: new_picture_url = user_data.get( picture_claim, @@ -1700,13 +1872,13 @@ class OAuthManager: log.debug(f'Updated profile picture for user {user.email}') else: # If the user does not exist, check if signups are enabled - if auth_manager_config.ENABLE_OAUTH_SIGNUP: + if auth_config.ENABLE_OAUTH_SIGNUP: # Check if an existing user with the same email already exists existing_user = await Users.get_user_by_email(email, db=db) if existing_user: raise HTTPException(400, detail=ERROR_MESSAGES.EMAIL_TAKEN) - picture_claim = auth_manager_config.OAUTH_PICTURE_CLAIM + picture_claim = auth_config.OAUTH_PICTURE_CLAIM if picture_claim: picture_url = user_data.get( picture_claim, @@ -1715,7 +1887,7 @@ class OAuthManager: picture_url = await self._process_picture_url(picture_url, token.get('access_token')) else: picture_url = '/user.png' - username_claim = auth_manager_config.OAUTH_USERNAME_CLAIM + username_claim = auth_config.OAUTH_USERNAME_CLAIM name = user_data.get(username_claim) if not name: @@ -1724,7 +1896,7 @@ class OAuthManager: user = await Auths.insert_new_auth( email=email, - password=get_password_hash(str(uuid.uuid4())), # Random password, not used + password=await get_password_hash(str(uuid.uuid4())), # Random password, not used name=name, profile_image_url=picture_url, role=await self.get_user_role(None, user_data), @@ -1742,19 +1914,16 @@ class OAuthManager: await Users.update_user_role_by_id(user.id, 'admin', db=db) user = await Users.get_user_by_id(user.id, db=db) - if auth_manager_config.WEBHOOK_URL: - await post_webhook( - WEBUI_NAME, - auth_manager_config.WEBHOOK_URL, - WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - { - 'action': 'signup', - 'message': WEBHOOK_MESSAGES.USER_SIGNUP(user.name), - 'user': user.model_dump_json(exclude_none=True), - }, - ) - - await apply_default_group_assignment(request.app.state.config.DEFAULT_GROUP_ID, user.id, db=db) + default_group_id = await Config.get('ui.default_group_id') + await apply_default_group_assignment(default_group_id, user.id, db=db) + await publish_event( + request, + EVENTS.USER_CREATED, + actor=user, + subject_id=user.id, + source='oauth', + data={'role': user.role, 'provider': provider}, + ) else: raise HTTPException( @@ -1764,13 +1933,13 @@ class OAuthManager: jwt_token = create_token( data={'id': user.id}, - expires_delta=parse_duration(auth_manager_config.JWT_EXPIRES_IN), + expires_delta=parse_duration(auth_config.JWT_EXPIRES_IN), ) - if auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT: + if auth_config.ENABLE_OAUTH_GROUP_MANAGEMENT: await self.update_user_groups( user=user, user_data=user_data, - default_permissions=request.app.state.config.USER_PERMISSIONS, + default_permissions=await Config.get('user.permissions'), db=db, ) @@ -1782,7 +1951,8 @@ class OAuthManager: else ERROR_MESSAGES.DEFAULT('Error during OAuth process') ) - redirect_base_url = (str(request.app.state.config.WEBUI_URL or request.base_url)).rstrip('/') + webui_url = await Config.get('webui.url') + redirect_base_url = (str(webui_url or request.base_url)).rstrip('/') redirect_url = f'{redirect_base_url}/auth' if error_message: @@ -1792,7 +1962,7 @@ class OAuthManager: response = RedirectResponse(url=redirect_url, headers=response.headers) # Compute cookie expiry from JWT lifetime - expires_delta = parse_duration(auth_manager_config.JWT_EXPIRES_IN) + expires_delta = parse_duration(auth_config.JWT_EXPIRES_IN) cookie_max_age = int(expires_delta.total_seconds()) if expires_delta else None # Set the cookie token diff --git a/backend/open_webui/utils/payload.py b/backend/open_webui/utils/payload.py index 98c84b41ec..d6242261db 100644 --- a/backend/open_webui/utils/payload.py +++ b/backend/open_webui/utils/payload.py @@ -10,6 +10,26 @@ from open_webui.utils.misc import ( from open_webui.utils.task import prompt_template, prompt_variables_template +async def resolve_system_prompt( + system: Optional[str], + metadata: Optional[dict] = None, + user=None, +) -> str: + if not system: + return '' + + # Metadata (WebUI Usage) + if metadata: + variables = metadata.get('variables', {}) + if variables: + system = prompt_variables_template(system, variables) + + # Legacy (API Usage) + system = await prompt_template(system, user) + + return system + + # What goes out cannot be taken back. Let it be shaped # well before it leaves this place. # inplace function: form_data is modified @@ -20,18 +40,10 @@ async def apply_system_prompt_to_body( user=None, replace: bool = False, ) -> dict: + system = await resolve_system_prompt(system, metadata, user) if not system: return form_data - # Metadata (WebUI Usage) - if metadata: - variables = metadata.get('variables', {}) - if variables: - system = prompt_variables_template(system, variables) - - # Legacy (API Usage) - system = await prompt_template(system, user) - if replace: form_data['messages'] = replace_system_message_content(system, form_data.get('messages', [])) else: @@ -72,6 +84,7 @@ def remove_open_webui_params(params: dict) -> dict: 'stream_delta_chunk_size': int, 'function_calling': str, 'reasoning_tags': list, + 'compact_token_threshold': int, 'system': str, } diff --git a/backend/open_webui/utils/plugin.py b/backend/open_webui/utils/plugin.py index d7aa0a0a39..53531c4350 100644 --- a/backend/open_webui/utils/plugin.py +++ b/backend/open_webui/utils/plugin.py @@ -1,5 +1,6 @@ from __future__ import annotations +import asyncio import logging import os import re @@ -213,8 +214,10 @@ async def load_tool_module_by_id(tool_id, content=None): await Tools.update_tool_by_id(tool_id, {'content': content}) else: frontmatter = extract_frontmatter(content) - # Install required packages found within the frontmatter - install_frontmatter_requirements(frontmatter.get('requirements', '')) + # Install required packages found within the frontmatter. + # Runs `pip install` via subprocess, which can take a long time; + # offload to a thread so it doesn't block the event loop. + await asyncio.to_thread(install_frontmatter_requirements, frontmatter.get('requirements', '')) module_name = f'tool_{tool_id}' module = types.ModuleType(module_name) @@ -258,7 +261,8 @@ async def load_function_module_by_id(function_id: str, content: str | None = Non await Functions.update_function_by_id(function_id, {'content': content}) else: frontmatter = extract_frontmatter(content) - install_frontmatter_requirements(frontmatter.get('requirements', '')) + # `pip install` via subprocess can block for a long time; offload it. + await asyncio.to_thread(install_frontmatter_requirements, frontmatter.get('requirements', '')) module_name = f'function_{function_id}' module = types.ModuleType(module_name) @@ -285,6 +289,8 @@ async def load_function_module_by_id(function_id: str, content: str | None = Non return module.Filter(), 'filter', frontmatter elif hasattr(module, 'Action'): return module.Action(), 'action', frontmatter + elif hasattr(module, 'Event'): + return module.Event(), 'event', frontmatter else: raise Exception('No Function class found in the module') except Exception as e: @@ -298,7 +304,33 @@ async def load_function_module_by_id(function_id: str, content: str | None = Non os.unlink(temp_file.name) +def _state_cache(request, name: str) -> dict: + if not hasattr(request.app.state, name): + setattr(request.app.state, name, {}) + return getattr(request.app.state, name) + + +def get_tools_cache(request) -> dict: + return _state_cache(request, 'TOOLS') + + +def get_tool_contents_cache(request) -> dict: + return _state_cache(request, 'TOOL_CONTENTS') + + +def get_functions_cache(request) -> dict: + return _state_cache(request, 'FUNCTIONS') + + +def get_function_contents_cache(request) -> dict: + return _state_cache(request, 'FUNCTION_CONTENTS') + + async def get_tool_module_from_cache(request, tool_id, load_from_db=True): + tools_cache = get_tools_cache(request) + tool_contents_cache = get_tool_contents_cache(request) + content = None + if load_from_db: # Always load from the database by default tool = await Tools.get_tool_by_id(tool_id) @@ -312,27 +344,19 @@ async def get_tool_module_from_cache(request, tool_id, load_from_db=True): # Update the tool content in the database await Tools.update_tool_by_id(tool_id, {'content': content}) - if (hasattr(request.app.state, 'TOOL_CONTENTS') and tool_id in request.app.state.TOOL_CONTENTS) and ( - hasattr(request.app.state, 'TOOLS') and tool_id in request.app.state.TOOLS - ): - if request.app.state.TOOL_CONTENTS[tool_id] == content: - return request.app.state.TOOLS[tool_id], None + if tool_id in tool_contents_cache and tool_id in tools_cache: + if tool_contents_cache[tool_id] == content: + return tools_cache[tool_id], None tool_module, frontmatter = await load_tool_module_by_id(tool_id, content) else: - if hasattr(request.app.state, 'TOOLS') and tool_id in request.app.state.TOOLS: - return request.app.state.TOOLS[tool_id], None + if tool_id in tools_cache: + return tools_cache[tool_id], None tool_module, frontmatter = await load_tool_module_by_id(tool_id) - if not hasattr(request.app.state, 'TOOLS'): - request.app.state.TOOLS = {} - - if not hasattr(request.app.state, 'TOOL_CONTENTS'): - request.app.state.TOOL_CONTENTS = {} - - request.app.state.TOOLS[tool_id] = tool_module - request.app.state.TOOL_CONTENTS[tool_id] = content + tools_cache[tool_id] = tool_module + tool_contents_cache[tool_id] = content return tool_module, frontmatter @@ -340,6 +364,10 @@ async def get_tool_module_from_cache(request, tool_id, load_from_db=True): async def get_function_module_from_cache( request, function_id, function: FunctionModel | None = None, load_from_db=True ): + functions_cache = get_functions_cache(request) + function_contents_cache = get_function_contents_cache(request) + content = None + if load_from_db: # Always load from the database by default # This is useful for hooks like "inlet" or "outlet" where the content might change @@ -357,30 +385,22 @@ async def get_function_module_from_cache( # Update the function content in the database await Functions.update_function_by_id(function_id, {'content': content}) - if ( - hasattr(request.app.state, 'FUNCTION_CONTENTS') and function_id in request.app.state.FUNCTION_CONTENTS - ) and (hasattr(request.app.state, 'FUNCTIONS') and function_id in request.app.state.FUNCTIONS): - if request.app.state.FUNCTION_CONTENTS[function_id] == content: - return request.app.state.FUNCTIONS[function_id], None, None + if function_id in function_contents_cache and function_id in functions_cache: + if function_contents_cache[function_id] == content: + return functions_cache[function_id], None, None function_module, function_type, frontmatter = await load_function_module_by_id(function_id, content) else: # Load from cache (e.g. "stream" hook) # This is useful for performance reasons - if hasattr(request.app.state, 'FUNCTIONS') and function_id in request.app.state.FUNCTIONS: - return request.app.state.FUNCTIONS[function_id], None, None + if function_id in functions_cache: + return functions_cache[function_id], None, None function_module, function_type, frontmatter = await load_function_module_by_id(function_id) - if not hasattr(request.app.state, 'FUNCTIONS'): - request.app.state.FUNCTIONS = {} - - if not hasattr(request.app.state, 'FUNCTION_CONTENTS'): - request.app.state.FUNCTION_CONTENTS = {} - - request.app.state.FUNCTIONS[function_id] = function_module - request.app.state.FUNCTION_CONTENTS[function_id] = content + functions_cache[function_id] = function_module + function_contents_cache[function_id] = content return function_module, function_type, frontmatter @@ -443,6 +463,7 @@ async def install_tool_and_function_dependencies(): if dependencies := frontmatter.get('requirements'): all_dependencies += f'{dependencies}, ' - install_frontmatter_requirements(all_dependencies.strip(', ')) + # `pip install` via subprocess can block for a long time; offload it. + await asyncio.to_thread(install_frontmatter_requirements, all_dependencies.strip(', ')) except Exception as e: log.error(f'Error installing requirements: {e}') diff --git a/backend/open_webui/utils/redis.py b/backend/open_webui/utils/redis.py index f2ac75410e..1417be134c 100644 --- a/backend/open_webui/utils/redis.py +++ b/backend/open_webui/utils/redis.py @@ -185,7 +185,7 @@ class SentinelRedisProxy: if proxy._should_retry(attempt): proxy._log_retry(exc, attempt) if REDIS_RECONNECT_DELAY: - time.sleep(REDIS_RECONNECT_DELAY / 1000) + await asyncio.sleep(REDIS_RECONNECT_DELAY / 1000) continue proxy._log_exhausted(exc) raise diff --git a/backend/open_webui/utils/response.py b/backend/open_webui/utils/response.py index 7bc5375480..de3ede0a07 100644 --- a/backend/open_webui/utils/response.py +++ b/backend/open_webui/utils/response.py @@ -1,4 +1,5 @@ import json +from numbers import Number from uuid import uuid4 from open_webui.utils.misc import ( @@ -50,6 +51,91 @@ def normalize_usage(usage: dict) -> dict: return result +USAGE_TOKEN_KEYS = { + 'input_tokens', + 'output_tokens', + 'total_tokens', + 'prompt_tokens', + 'completion_tokens', +} + +USAGE_COST_KEYS = { + 'cost', + 'total_cost', + 'input_cost', + 'output_cost', + 'prompt_cost', + 'completion_cost', +} + +USAGE_DETAIL_KEYS = { + 'prompt_tokens_details', + 'completion_tokens_details', + 'input_tokens_details', + 'output_tokens_details', +} + + +def _is_numeric_usage_value(value) -> bool: + return isinstance(value, Number) and not isinstance(value, bool) + + +def _merge_numeric_usage_map(current: dict | None, incoming: dict | None) -> dict: + current = current or {} + incoming = incoming or {} + result = {**current, **incoming} + + for key in set(current) | set(incoming): + current_value = current.get(key, 0) + incoming_value = incoming.get(key, 0) + if isinstance(current_value, dict) or isinstance(incoming_value, dict): + result[key] = _merge_numeric_usage_map( + current_value if isinstance(current_value, dict) else {}, + incoming_value if isinstance(incoming_value, dict) else {}, + ) + elif _is_numeric_usage_value(current_value) or _is_numeric_usage_value(incoming_value): + result[key] = (current_value if _is_numeric_usage_value(current_value) else 0) + ( + incoming_value if _is_numeric_usage_value(incoming_value) else 0 + ) + + return result + + +def merge_usage(current: dict | None, incoming: dict | None) -> dict: + """ + Merge usage payloads from multiple model calls into one cumulative usage dict. + + Token fields are additive; non-numeric metadata keeps the latest provider value. + """ + current_usage = normalize_usage(current or {}) if current else {} + incoming_usage = normalize_usage(incoming or {}) if incoming else {} + + if not incoming_usage: + return current_usage + if not current_usage: + return incoming_usage + + result = {**current_usage, **incoming_usage} + + for key in USAGE_TOKEN_KEYS | USAGE_COST_KEYS: + if key in current_usage or key in incoming_usage: + current_value = current_usage.get(key, 0) + incoming_value = incoming_usage.get(key, 0) + if _is_numeric_usage_value(current_value) or _is_numeric_usage_value(incoming_value): + result[key] = (current_value if _is_numeric_usage_value(current_value) else 0) + ( + incoming_value if _is_numeric_usage_value(incoming_value) else 0 + ) + + for key in USAGE_DETAIL_KEYS: + if isinstance(current_usage.get(key), dict) or isinstance(incoming_usage.get(key), dict): + result[key] = _merge_numeric_usage_map( + current_usage.get(key) if isinstance(current_usage.get(key), dict) else {}, + incoming_usage.get(key) if isinstance(incoming_usage.get(key), dict) else {}, + ) + + return result + + def convert_ollama_tool_call_to_openai(tool_calls: list) -> list: openai_tool_calls = [] for tool_call in tool_calls: diff --git a/backend/open_webui/utils/task.py b/backend/open_webui/utils/task.py index 0b5f628305..4fb5fc5ec6 100644 --- a/backend/open_webui/utils/task.py +++ b/backend/open_webui/utils/task.py @@ -141,6 +141,9 @@ def truncate_content(content: str, max_chars: int, mode: str = 'middletruncate') - start: keep first max_chars characters - end: keep last max_chars characters """ + if max_chars <= 0: + return '' + if not content or len(content) <= max_chars: return content @@ -191,7 +194,9 @@ def apply_content_filter(messages: list[dict], filter_str: str) -> list[dict]: return result -def replace_messages_variable(template: str, messages: Optional[list[dict]] = None) -> str: +def replace_messages_variable( + template: str, messages: Optional[list[dict]] = None, variable_name: str = 'MESSAGES' +) -> str: def replacement_function(match): # Groups: (1) filter for bare MESSAGES # (2) START count, (3) filter for START @@ -237,12 +242,13 @@ def replace_messages_variable(template: str, messages: Optional[list[dict]] = No return get_messages_content(selected) + variable_pattern = re.escape(variable_name) template = re.sub( r'(?:' - r'\{\{MESSAGES(?:\|(\w+:\d+))?\}\}' - r'|\{\{MESSAGES:START:(\d+)(?:\|(\w+:\d+))?\}\}' - r'|\{\{MESSAGES:END:(\d+)(?:\|(\w+:\d+))?\}\}' - r'|\{\{MESSAGES:MIDDLETRUNCATE:(\d+)(?:\|(\w+:\d+))?\}\}' + rf'\{{\{{{variable_pattern}(?:\|(\w+:\d+))?\}}\}}' + rf'|\{{\{{{variable_pattern}:START:(\d+)(?:\|(\w+:\d+))?\}}\}}' + rf'|\{{\{{{variable_pattern}:END:(\d+)(?:\|(\w+:\d+))?\}}\}}' + rf'|\{{\{{{variable_pattern}:MIDDLETRUNCATE:(\d+)(?:\|(\w+:\d+))?\}}\}}' r')', replacement_function, template, diff --git a/backend/open_webui/utils/telemetry/constants.py b/backend/open_webui/utils/telemetry/constants.py index 1f2102a86f..4ab07c0c48 100644 --- a/backend/open_webui/utils/telemetry/constants.py +++ b/backend/open_webui/utils/telemetry/constants.py @@ -1,4 +1,9 @@ -from opentelemetry.semconv.trace import SpanAttributes as _SpanAttributes +from opentelemetry.semconv._incubating.attributes import ( + db_attributes as _db, +) +from opentelemetry.semconv._incubating.attributes import ( + http_attributes as _http, +) # Span Tags SPAN_DB_TYPE = 'mysql' @@ -9,11 +14,29 @@ SPAN_SQL_EXPLAIN = 'explain' SPAN_ERROR_TYPE = 'error' -class SpanAttributes(_SpanAttributes): - """ - Span Attributes +class SpanAttributes: + """Span attribute keys used by the telemetry instrumentors. + + Legacy semconv keys (http.* and db.*) are sourced from the `_incubating` + attribute modules, which still define these exact string values. + `opentelemetry.semconv.trace.SpanAttributes` (previously subclassed here) + is deprecated since semconv 1.25.0, and the *stable* http module renamed + the keys (e.g. `http.request.method`), so only the incubating module keeps + the original `http.method` / `http.url` / `http.status_code` / `db.*` values. + Sourcing from it keeps emitted span attribute keys unchanged. """ + # HTTP — legacy keys retained in the incubating module + HTTP_URL = _http.HTTP_URL # 'http.url' + HTTP_METHOD = _http.HTTP_METHOD # 'http.method' + HTTP_STATUS_CODE = _http.HTTP_STATUS_CODE # 'http.status_code' + + # DB — incubating semconv keys + DB_NAME = _db.DB_NAME # 'db.name' + DB_STATEMENT = _db.DB_STATEMENT # 'db.statement' + DB_OPERATION = _db.DB_OPERATION # 'db.operation' + + # Open WebUI custom keys (not part of semconv) DB_INSTANCE = 'db.instance' DB_TYPE = 'db.type' DB_IP = 'db.ip' diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index 2bfa1940f9..6c33882c50 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -15,9 +15,7 @@ from typing import ( Callable, Optional, Type, - Union, get_args, - get_origin, get_type_hints, ) from urllib.parse import quote, urlencode @@ -42,6 +40,7 @@ from open_webui.env import ( REDIS_KEY_PREFIX, ) from open_webui.models.access_grants import AccessGrants +from open_webui.models.config import Config from open_webui.models.groups import Groups from open_webui.models.tools import Tools from open_webui.models.users import UserModel @@ -65,8 +64,10 @@ from open_webui.tools.builtin import ( list_knowledge, list_knowledge_bases, list_memories, + list_memory_paths, query_knowledge_bases, query_knowledge_files, + read_memory_path, replace_memory_content, replace_note_content, search_calendar_events, @@ -81,6 +82,7 @@ from open_webui.tools.builtin import ( toggle_automation, update_automation, update_calendar_event, + update_memory, update_task, view_channel_message, view_channel_thread, @@ -94,13 +96,22 @@ from open_webui.tools.builtin import ( from open_webui.utils.access_control import has_access, has_connection_access, has_permission from open_webui.utils.headers import get_custom_headers, include_user_info_headers from open_webui.utils.misc import is_string_allowed -from open_webui.utils.plugin import load_tool_module_by_id +from open_webui.utils.plugin import get_tool_contents_cache, get_tools_cache, load_tool_module_by_id from pydantic import BaseModel, Field, create_model from pydantic.fields import FieldInfo log = logging.getLogger(__name__) +def normalize_bearer_token(token: Any) -> str: + return token.strip() if isinstance(token, str) else token or '' + + +def bearer_auth_header(token: Any) -> dict[str, str]: + token = normalize_bearer_token(token) + return {'Authorization': f'Bearer {token}'} if token else {} + + async def build_tool_server_headers( connection: dict, request, @@ -169,6 +180,28 @@ async def get_async_tool_function_and_apply_extra_params( function: Callable, extra_params: dict ) -> Callable[..., Awaitable]: sig = inspect.signature(function) + try: + type_hints = get_type_hints(function) + except Exception: + type_hints = {} + + def coerce_kwargs(kwargs): + for name, value in kwargs.items(): + if name not in sig.parameters or value is None: + continue + + annotation = type_hints.get(name, sig.parameters[name].annotation) + args = set(get_args(annotation)) + if isinstance(value, str) and (annotation is int or args == {int, type(None)}): + kwargs[name] = int(value) + elif ( + isinstance(value, (int, float)) + and not isinstance(value, bool) + and (annotation is str or args == {str, type(None)}) + ): + kwargs[name] = str(value) + return kwargs + extra_params = {k: v for k, v in extra_params.items() if k in sig.parameters} partial_func = partial(function, **extra_params) @@ -188,12 +221,12 @@ async def get_async_tool_function_and_apply_extra_params( # wrap the functools.partial as python-genai has trouble with it # https://github.com/googleapis/python-genai/issues/907 async def new_function(*args, **kwargs): - return await partial_func(*args, **kwargs) + return await partial_func(*args, **coerce_kwargs(kwargs)) else: # Make it a coroutine function when it is not already async def new_function(*args, **kwargs): - return partial_func(*args, **kwargs) + return partial_func(*args, **coerce_kwargs(kwargs)) update_wrapper(new_function, function) new_function.__signature__ = new_sig @@ -249,11 +282,13 @@ async def get_tools(request: Request, tool_ids: list[str], user: UserModel, extr log.warning(f'Access denied to tool {tool_id} for user {user.id}') continue - module = request.app.state.TOOLS.get(tool_id) - if module is None or request.app.state.TOOL_CONTENTS.get(tool_id) != tool.content: + tools_cache = get_tools_cache(request) + tool_contents_cache = get_tool_contents_cache(request) + module = tools_cache.get(tool_id) + if module is None or tool_contents_cache.get(tool_id) != tool.content: module, _ = await load_tool_module_by_id(tool_id, content=tool.content) - request.app.state.TOOLS[tool_id] = module - request.app.state.TOOL_CONTENTS[tool_id] = tool.content + tools_cache[tool_id] = module + tool_contents_cache[tool_id] = tool.content __user__ = { **extra_params['__user__'], @@ -345,7 +380,7 @@ async def get_tools(request: Request, tool_ids: list[str], user: UserModel, extr continue tool_server_idx = tool_server_data.get('idx', 0) - connections = request.app.state.config.TOOL_SERVER_CONNECTIONS + connections = await Config.get('tool_server.connections', []) if tool_server_idx >= len(connections): log.warning( f'Tool server index {tool_server_idx} out of range ' @@ -451,6 +486,16 @@ async def get_builtin_tools( # Helper to check user-level feature permission (admins always pass) user = extra_params.get('__user__', {}) + config = await Config.get_many( + 'web.search.enable', + 'image_generation.enable', + 'images.edit.enable', + 'code_interpreter.enable', + 'notes.enable', + 'channels.enable', + 'automations.enable', + 'calendar.enable', + ) async def has_user_permission(feature_key: str) -> bool: if user.get('role') == 'admin': @@ -458,7 +503,7 @@ async def get_builtin_tools( return await has_permission( user.get('id', ''), f'features.{feature_key}', - request.app.state.config.USER_PERMISSIONS, + await Config.get('user.permissions'), ) # Time utilities - available for date calculations @@ -514,26 +559,30 @@ async def get_builtin_tools( if is_builtin_tool_enabled('chats'): builtin_functions.extend([search_chats, view_chat]) - # Add memory tools if builtin category enabled AND enabled for this chat + # Add memory tools when memory is enabled and the model allows this builtin category. if ( is_builtin_tool_enabled('memory') - and (features.get('memory') or get_model_capability('memory', False)) + and features.get('memory') + and get_model_capability('memory') and await has_user_permission('memories') ): builtin_functions.extend( [ search_memories, + list_memory_paths, + read_memory_path, + list_memories, + update_memory, add_memory, replace_memory_content, delete_memory, - list_memories, ] ) # Add web search tools if builtin category enabled AND enabled globally AND model has web_search capability if ( is_builtin_tool_enabled('web_search') - and getattr(request.app.state.config, 'ENABLE_WEB_SEARCH', False) + and config.get('web.search.enable') and get_model_capability('web_search') and features.get('web_search') and await has_user_permission('web_search') @@ -543,7 +592,7 @@ async def get_builtin_tools( # Add image generation/edit tools if builtin category enabled AND enabled globally AND model has image_generation capability if ( is_builtin_tool_enabled('image_generation') - and getattr(request.app.state.config, 'ENABLE_IMAGE_GENERATION', False) + and config.get('image_generation.enable') and get_model_capability('image_generation') and features.get('image_generation') and await has_user_permission('image_generation') @@ -551,7 +600,7 @@ async def get_builtin_tools( builtin_functions.append(generate_image) if ( is_builtin_tool_enabled('image_generation') - and getattr(request.app.state.config, 'ENABLE_IMAGE_EDIT', False) + and config.get('images.edit.enable') and get_model_capability('image_generation') and features.get('image_generation') and await has_user_permission('image_generation') @@ -561,7 +610,7 @@ async def get_builtin_tools( # Add code interpreter tool if builtin category enabled AND enabled globally AND model has code_interpreter capability if ( is_builtin_tool_enabled('code_interpreter') - and getattr(request.app.state.config, 'ENABLE_CODE_INTERPRETER', True) + and config.get('code_interpreter.enable') and get_model_capability('code_interpreter') and features.get('code_interpreter') and await has_user_permission('code_interpreter') @@ -569,19 +618,11 @@ async def get_builtin_tools( builtin_functions.append(execute_code) # Notes tools - search, view, create, and update user's notes - if ( - is_builtin_tool_enabled('notes') - and getattr(request.app.state.config, 'ENABLE_NOTES', False) - and await has_user_permission('notes') - ): + if is_builtin_tool_enabled('notes') and config.get('notes.enable') and await has_user_permission('notes'): builtin_functions.extend([search_notes, view_note, write_note, replace_note_content]) # Channels tools - search channels and messages - if ( - is_builtin_tool_enabled('channels') - and getattr(request.app.state.config, 'ENABLE_CHANNELS', False) - and await has_user_permission('channels') - ): + if is_builtin_tool_enabled('channels') and config.get('channels.enable') and await has_user_permission('channels'): builtin_functions.extend( [ search_channels, @@ -602,7 +643,7 @@ async def get_builtin_tools( # Automation tools - create and manage scheduled automations from chat if ( is_builtin_tool_enabled('automations') - and getattr(request.app.state.config, 'ENABLE_AUTOMATIONS', False) + and config.get('automations.enable') and await has_user_permission('automations') ): builtin_functions.extend( @@ -610,11 +651,7 @@ async def get_builtin_tools( ) # Calendar tools - search/create/update/delete events - if ( - is_builtin_tool_enabled('calendar') - and getattr(request.app.state.config, 'ENABLE_CALENDAR', False) - and await has_user_permission('calendar') - ): + if is_builtin_tool_enabled('calendar') and config.get('calendar.enable') and await has_user_permission('calendar'): builtin_functions.extend( [search_calendar_events, create_calendar_event, update_calendar_event, delete_calendar_event] ) @@ -958,7 +995,7 @@ def convert_openapi_to_tool_payload(openapi_spec): async def set_tool_servers(request: Request): try: - request.app.state.TOOL_SERVERS = await get_tool_servers_data(request.app.state.config.TOOL_SERVER_CONNECTIONS) + request.app.state.TOOL_SERVERS = await get_tool_servers_data(await Config.get('tool_server.connections', [])) except Exception as e: log.error(f'Error fetching tool server data: {e}') request.app.state.TOOL_SERVERS = getattr(request.app.state, 'TOOL_SERVERS', None) or [] @@ -1055,7 +1092,7 @@ async def get_terminal_system_prompt( async def set_terminal_servers(request: Request): """Load and cache OpenAPI specs from all TERMINAL_SERVER_CONNECTIONS.""" - connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or [] + connections = await Config.get('terminal_server.connections', []) or [] # Build server configs compatible with get_tool_servers_data # Terminal connections store id/name at top level; translate to info dict @@ -1077,7 +1114,7 @@ async def set_terminal_servers(request: Request): server_configs.append( { 'url': base_url, - 'key': connection.get('key', ''), + 'key': normalize_bearer_token(connection.get('key', '')), 'auth_type': connection.get('auth_type', 'bearer'), 'path': connection.get('path', '/openapi.json'), 'spec_type': 'url', @@ -1101,7 +1138,7 @@ async def set_terminal_servers(request: Request): return headers = {} if connection.get('auth_type', 'bearer') == 'bearer': - headers['Authorization'] = f'Bearer {connection.get("key", "")}' + headers.update(bearer_auth_header(connection.get('key', ''))) prompt = await get_terminal_system_prompt(server['url'], headers) if prompt: server['system_prompt'] = prompt @@ -1148,7 +1185,7 @@ async def get_terminal_tools( - Loads specs from cache - Builds callables that route through the terminal proxy """ - connections = request.app.state.config.TERMINAL_SERVER_CONNECTIONS or [] + connections = await Config.get('terminal_server.connections', []) or [] connection = next((c for c in connections if c.get('id') == terminal_id), None) if connection is None: log.warning(f'Terminal server not found: {terminal_id}') @@ -1176,15 +1213,15 @@ async def get_terminal_tools( headers = {'Content-Type': 'application/json', 'X-User-Id': user.id} if auth_type == 'bearer': - headers['Authorization'] = f'Bearer {connection.get("key", "")}' + headers.update(bearer_auth_header(connection.get('key', ''))) elif auth_type == 'session': cookies = request.cookies - headers['Authorization'] = f'Bearer {request.state.token.credentials}' + headers.update(bearer_auth_header(request.state.token.credentials)) elif auth_type == 'system_oauth': cookies = request.cookies oauth_token = extra_params.get('__oauth_token__', None) if oauth_token: - headers['Authorization'] = f'Bearer {oauth_token.get("access_token", "")}' + headers.update(bearer_auth_header(oauth_token.get('access_token', ''))) # auth_type == "none": no Authorization header system_prompt = server_data.get('system_prompt') diff --git a/backend/open_webui/utils/valves.py b/backend/open_webui/utils/valves.py new file mode 100644 index 0000000000..c6e2212059 --- /dev/null +++ b/backend/open_webui/utils/valves.py @@ -0,0 +1,41 @@ +import base64 +import hashlib +import json +import logging +from functools import lru_cache + +from cryptography.fernet import Fernet, InvalidToken +from open_webui.env import ENABLE_VALVE_ENCRYPTION, WEBUI_SECRET_KEY + +log = logging.getLogger(__name__) + + +@lru_cache(maxsize=1) +def _fernet() -> Fernet: + key = WEBUI_SECRET_KEY.encode() + if len(WEBUI_SECRET_KEY) != 44: + key = base64.urlsafe_b64encode(hashlib.sha256(key).digest()) + return Fernet(key) + + +def encrypt_valves(valves: dict) -> dict | str: + if not ENABLE_VALVE_ENCRYPTION: + return valves + return _fernet().encrypt(json.dumps(valves).encode()).decode() + + +def decrypt_valves(valves) -> dict: + if not valves: + return {} + if isinstance(valves, dict): + return valves + if not isinstance(valves, str): + return {} + + try: + decrypted = json.loads(_fernet().decrypt(valves.encode()).decode()) + except (InvalidToken, json.JSONDecodeError) as e: + log.warning('Failed to decrypt valves: %s', type(e).__name__) + return {} + + return decrypted if isinstance(decrypted, dict) else {} diff --git a/backend/open_webui/utils/webhook.py b/backend/open_webui/utils/webhook.py index 8a65f348a8..d3026ffac6 100644 --- a/backend/open_webui/utils/webhook.py +++ b/backend/open_webui/utils/webhook.py @@ -1,45 +1,61 @@ +import asyncio import json import logging -import aiohttp from open_webui.config import WEBUI_FAVICON_URL from open_webui.env import ( AIOHTTP_CLIENT_ALLOW_REDIRECTS, AIOHTTP_CLIENT_SESSION_SSL, - AIOHTTP_CLIENT_TIMEOUT, VERSION, ) -from open_webui.retrieval.web.utils import validate_url +from open_webui.retrieval.web.utils import get_ssrf_safe_session, validate_url log = logging.getLogger(__name__) # Let this message reach those for whom it was written, and # may no network partition deny the word its destination. -async def post_webhook(name: str, url: str, message: str, event_data: dict) -> bool: +def _event_text(message: str, description: str | None = None, event_data: dict | None = None) -> str: + lines = [message] + if description and description != message: + lines.append(description) + + event_name = (event_data or {}).get('event') + if event_name: + lines.append(f'Event: {event_name}') + + return '\n'.join(lines) + + +async def post_webhook(name: str, url: str, message: str, event_data: dict, description: str | None = None) -> bool: try: log.debug(f'post_webhook: {url}, {message}, {event_data}') # Block private-IP / loopback / cloud-metadata targets — the URL is # caller-controlled (user notification settings under # ENABLE_USER_WEBHOOKS, automation notification triggers). - validate_url(url) + await asyncio.to_thread(validate_url, url) payload = {} # Slack and Google Chat Webhooks if 'https://hooks.slack.com' in url or 'https://chat.googleapis.com' in url: - payload['text'] = message + payload['text'] = _event_text(message, description, event_data) # Discord Webhooks elif 'https://discord.com/api/webhooks' in url: - payload['content'] = message if len(message) < 2000 else f'{message[: 2000 - 20]}... (truncated)' + content = _event_text(message, description, event_data) + payload['content'] = content if len(content) < 2000 else f'{content[: 2000 - 20]}... (truncated)' # Microsoft Teams Webhooks elif 'webhook.office.com' in url: action = event_data.get('action', 'undefined') - user_data = event_data.get('user', '{}') + user_data = event_data.get('user') or event_data.get('actor') or {} if isinstance(user_data, dict): user_dict = user_data else: user_dict = json.loads(user_data) - facts = [{'name': name, 'value': value} for name, value in user_dict.items()] + facts = [{'name': key, 'value': value} for key, value in user_dict.items()] + if event_data.get('event'): + facts.insert(0, {'name': 'event', 'value': event_data.get('event')}) + if description: + facts.insert(0, {'name': 'description', 'value': description}) payload = { '@type': 'MessageCard', '@context': 'http://schema.org/extensions', @@ -50,6 +66,7 @@ async def post_webhook(name: str, url: str, message: str, event_data: dict) -> b 'activityTitle': message, 'activitySubtitle': f'{name} ({VERSION}) - {action}', 'activityImage': WEBUI_FAVICON_URL, + 'text': description, 'facts': facts, 'markdown': True, } @@ -57,12 +74,10 @@ async def post_webhook(name: str, url: str, message: str, event_data: dict) -> b } # Default Payload else: - payload = {**event_data} + payload = event_data log.debug(f'payload: {payload}') - async with aiohttp.ClientSession( - trust_env=True, timeout=aiohttp.ClientTimeout(total=AIOHTTP_CLIENT_TIMEOUT) - ) as session: + async with get_ssrf_safe_session() as session: async with session.post( url, json=payload, diff --git a/backend/requirements-min.txt b/backend/requirements-min.txt index 05c28deba6..d5646443e6 100644 --- a/backend/requirements-min.txt +++ b/backend/requirements-min.txt @@ -1,59 +1,57 @@ # Minimal requirements for backend to run # WIP: use this as a reference to build a minimal docker image -fastapi==0.135.1 +fastapi==0.136.3 uvicorn[standard]==0.41.0 -pydantic==2.12.5 -python-multipart==0.0.22 +pydantic==2.13.4 +python-multipart==0.0.27 itsdangerous==2.2.0 -python-socketio==5.16.1 +python-socketio==5.16.2 python-jose==3.5.0 cryptography bcrypt==5.0.0 argon2-cffi==25.1.0 -PyJWT[crypto]==2.11.0 -authlib==1.6.10 +PyJWT[crypto]==2.13.0 +authlib==1.7.2 -requests==2.33.1 +requests==2.34.2 aiohttp==3.13.5 # do not update to 3.13.3 - broken async-timeout aiocache aiofiles -starlette-compress==1.7.0 +starlette-compress==1.7.1 Brotli==1.2.0 brotlicffi==1.2.0.1 httpx[socks,http2,zstd,cli,brotli]==0.28.1 starsessions[redis]==2.2.1 -sqlalchemy==2.0.48 -aiosqlite==0.21.0 -psycopg[binary]==3.2.9 +sqlalchemy==2.0.50 +aiosqlite==0.22.1 +psycopg[binary]==3.3.4 alembic==1.18.4 -peewee==3.19.0 -peewee-migrate==1.14.3 -pycrdt==0.12.47 +pycrdt==0.13.1 redis APScheduler==3.11.2 -RestrictedPython==8.1 +RestrictedPython==8.2 loguru==0.7.3 asgiref==3.11.1 -mcp==1.26.0 +mcp==1.27.2 openai langchain==1.2.10 -langchain-community==0.4.1 -langchain-classic==1.0.1 -langchain-text-splitters==1.1.1 +langchain-community==0.4.2 +langchain-classic==1.0.7 +langchain-text-splitters==1.1.2 fake-useragent==2.2.0 -chromadb==1.5.2 -black==26.3.1 +chromadb==1.5.9 +black==26.5.1 pydub -chardet==5.2.0 +chardet==7.4.3 beautifulsoup4 diff --git a/backend/requirements.txt b/backend/requirements.txt index 425a72b254..e33bf131ea 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,85 +1,83 @@ -fastapi==0.135.1 +fastapi==0.136.3 uvicorn[standard]==0.41.0 -pydantic==2.12.5 -python-multipart==0.0.22 +pydantic==2.13.4 +python-multipart==0.0.27 itsdangerous==2.2.0 -python-socketio==5.16.1 +python-socketio==5.16.2 python-jose==3.5.0 -cryptography==46.0.5 +cryptography==48.0.0 bcrypt==5.0.0 argon2-cffi==25.1.0 -PyJWT[crypto]==2.11.0 -authlib==1.6.10 +PyJWT[crypto]==2.13.0 +authlib==1.7.2 -requests==2.33.1 +requests==2.34.2 aiohttp==3.13.5 # do not update to 3.13.3 - broken async-timeout==5.0.1 aiocache==0.12.3 aiofiles==25.1.0 -starlette-compress==1.7.0 +starlette-compress==1.7.1 Brotli==1.2.0 brotlicffi==1.2.0.1 httpx[socks,http2,zstd,cli,brotli]==0.28.1 starsessions[redis]==2.2.1 python-mimeparse==2.0.0 -sqlalchemy[asyncio]==2.0.48 -aiosqlite==0.21.0 -psycopg[binary]==3.2.9 +sqlalchemy[asyncio]==2.0.50 +aiosqlite==0.22.1 +psycopg[binary]==3.3.4 alembic==1.18.4 -peewee==3.19.0 -peewee-migrate==1.14.3 -pycrdt==0.12.47 -redis==7.4.0 +pycrdt==0.13.1 +redis==8.0.0 APScheduler==3.11.2 -RestrictedPython==8.1 -pytz==2026.1.post1 +RestrictedPython==8.2 +pytz==2026.2 loguru==0.7.3 asgiref==3.11.1 # AI libraries -tiktoken==0.12.0 -mcp==1.26.0 +tiktoken==0.13.0 +mcp==1.27.2 openai==2.29.0 anthropic==0.86.0 google-genai==1.66.0 langchain==1.2.10 -langchain-community==0.4.1 -langchain-classic==1.0.1 -langchain-text-splitters==1.1.1 +langchain-community==0.4.2 +langchain-classic==1.0.7 +langchain-text-splitters==1.1.2 fake-useragent==2.2.0 -chromadb==1.5.2 +chromadb==1.5.9 weaviate-client==4.20.3 -opensearch-py==3.1.0 +opensearch-py==3.2.0 transformers==5.5.4 -sentence-transformers==5.4.0 +sentence-transformers==5.5.1 accelerate==1.13.0 pyarrow==20.0.0 # fix: pin pyarrow version to 20 for rpi compatibility #15897 einops==0.8.2 ftfy==6.3.1 -chardet==5.2.0 +chardet==7.4.3 pypdf==6.7.5 fpdf2==2.8.7 -pymdown-extensions==10.21 +pymdown-extensions==10.21.3 docx2txt==0.9 python-pptx==1.0.2 msoffcrypto-tool==6.0.0 -unstructured==0.18.31 +unstructured==0.22.31 -nltk==3.9.3 +nltk==3.9.4 Markdown==3.10.2 beautifulsoup4==4.14.3 -pypandoc==1.16.2 -pandas==3.0.1 +pypandoc==1.17 +pandas==3.0.3 openpyxl==3.1.5 pyxlsb==1.0.10 xlrd==2.0.2 @@ -88,48 +86,48 @@ psutil==7.2.2 sentencepiece==0.2.1 soundfile==0.13.1 -pillow==12.1.1 +pillow==12.2.0 opencv-python-headless==4.13.0.92 rapidocr-onnxruntime==1.4.4 rank-bm25==0.2.2 -onnxruntime==1.24.3 +onnxruntime==1.26.0 faster-whisper==1.2.1 -black==26.3.1 +black==26.5.1 youtube-transcript-api==1.2.4 pytube==15.0.0 pydub==0.25.1 -ddgs==9.11.3 +ddgs==9.14.4 azure-ai-documentintelligence==1.0.2 -azure-identity==1.25.2 -azure-storage-blob==12.28.0 -azure-search-documents==11.6.0 +azure-identity==1.25.3 +azure-storage-blob==12.29.0 +azure-search-documents==12.0.0 ## Google Drive -google-api-python-client==2.193.0 -google-auth-httplib2==0.3.0 -google-auth-oauthlib==1.3.0 +google-api-python-client==2.197.0 +google-auth-httplib2==0.4.0 +google-auth-oauthlib==1.4.0 -googleapis-common-protos==1.72.0 +googleapis-common-protos==1.75.0 google-cloud-storage==3.9.0 ## Databases -pymongo==4.16.0 -psycopg2-binary==2.9.11 +pymongo==4.17.0 +psycopg2-binary==2.9.12 pgvector==0.4.2 -PyMySQL==1.1.2 +PyMySQL==1.2.0 boto3==1.42.62 # mariadb==1.1.14 should be added if you want to support MariaDB # valkey-glide-sync==2.3.1 # optional: install manually if VECTOR_DB=valkey -pymilvus==2.6.9 -qdrant-client==1.17.0 -playwright==1.58.0 # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary -elasticsearch==9.3.0 +pymilvus==2.6.14 +qdrant-client==1.18.0 +playwright==1.60.0 # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary +elasticsearch==9.4.1 pinecone==6.0.2 oracledb==3.4.2 @@ -147,15 +145,15 @@ pytest-docker~=3.2.5 ldap3==2.9.1 ## Trace -opentelemetry-api==1.40.0 -opentelemetry-sdk==1.40.0 -opentelemetry-exporter-otlp==1.40.0 -opentelemetry-instrumentation==0.61b0 -opentelemetry-instrumentation-fastapi==0.61b0 -opentelemetry-instrumentation-sqlalchemy==0.61b0 -opentelemetry-instrumentation-redis==0.61b0 -opentelemetry-instrumentation-requests==0.61b0 -opentelemetry-instrumentation-logging==0.61b0 -opentelemetry-instrumentation-httpx==0.61b0 -opentelemetry-instrumentation-aiohttp-client==0.61b0 -opentelemetry-instrumentation-system-metrics==0.61b0 +opentelemetry-api==1.42.1 +opentelemetry-sdk==1.42.1 +opentelemetry-exporter-otlp==1.42.1 +opentelemetry-instrumentation==0.63b1 +opentelemetry-instrumentation-fastapi==0.63b1 +opentelemetry-instrumentation-sqlalchemy==0.63b1 +opentelemetry-instrumentation-redis==0.63b1 +opentelemetry-instrumentation-requests==0.63b1 +opentelemetry-instrumentation-logging==0.63b1 +opentelemetry-instrumentation-httpx==0.63b1 +opentelemetry-instrumentation-aiohttp-client==0.63b1 +opentelemetry-instrumentation-system-metrics==0.63b1 diff --git a/backend/start.sh b/backend/start.sh index 9e65465095..0846273b89 100755 --- a/backend/start.sh +++ b/backend/start.sh @@ -30,6 +30,7 @@ fi # ── Secret key setup ───────────────────────────────────────────────────────── KEY_FILE="${WEBUI_SECRET_KEY_FILE:-.webui_secret_key}" +WEBUI_SECRET_KEY_LENGTH="${WEBUI_SECRET_KEY_LENGTH:-24}" PORT="${PORT:-8080}" HOST="${HOST:-0.0.0.0}" @@ -38,7 +39,11 @@ if [[ -z "${WEBUI_SECRET_KEY:-}" && -z "${WEBUI_JWT_SECRET_KEY:-}" ]]; then if [[ ! -f "$KEY_FILE" ]]; then echo "Generating new WEBUI_SECRET_KEY..." - head -c 12 /dev/random | base64 > "$KEY_FILE" + if ! [[ "$WEBUI_SECRET_KEY_LENGTH" =~ ^[1-9][0-9]*$ ]]; then + echo "WEBUI_SECRET_KEY_LENGTH must be a positive integer." >&2 + exit 1 + fi + head -c "$WEBUI_SECRET_KEY_LENGTH" /dev/random | base64 > "$KEY_FILE" fi echo "Loading WEBUI_SECRET_KEY from ${KEY_FILE}" @@ -105,4 +110,4 @@ exec env WEBUI_SECRET_KEY="${WEBUI_SECRET_KEY:-}" \ --host "$HOST" \ --port "$PORT" \ --forwarded-allow-ips "${FORWARDED_ALLOW_IPS:-*}" \ - "${ARGS[@]}" \ No newline at end of file + "${ARGS[@]}" diff --git a/backend/start_windows.bat b/backend/start_windows.bat index c5f96e0e6f..b86beb11e8 100644 --- a/backend/start_windows.bat +++ b/backend/start_windows.bat @@ -27,6 +27,9 @@ IF "%HOST%"=="" SET HOST=0.0.0.0 IF "%FORWARDED_ALLOW_IPS%"=="" SET "FORWARDED_ALLOW_IPS='*'" SET "WEBUI_SECRET_KEY=%WEBUI_SECRET_KEY%" SET "WEBUI_JWT_SECRET_KEY=%WEBUI_JWT_SECRET_KEY%" +IF "%WEBUI_SECRET_KEY_LENGTH%" == "" ( + SET "WEBUI_SECRET_KEY_LENGTH=24" +) :: Check if WEBUI_SECRET_KEY and WEBUI_JWT_SECRET_KEY are not set IF "%WEBUI_SECRET_KEY% %WEBUI_JWT_SECRET_KEY%" == " " ( @@ -36,7 +39,7 @@ IF "%WEBUI_SECRET_KEY% %WEBUI_JWT_SECRET_KEY%" == " " ( echo Generating WEBUI_SECRET_KEY :: Generate a random value to use as a WEBUI_SECRET_KEY in case the user didn't provide one SET /p WEBUI_SECRET_KEY=>%KEY_FILE% + FOR /L %%i IN (1,1,%WEBUI_SECRET_KEY_LENGTH%) DO SET /p WEBUI_SECRET_KEY=>%KEY_FILE% echo WEBUI_SECRET_KEY generated ) diff --git a/docker-compose.playwright.yaml b/docker-compose.playwright.yaml index 167c2501d6..682d9558f3 100644 --- a/docker-compose.playwright.yaml +++ b/docker-compose.playwright.yaml @@ -1,8 +1,8 @@ services: playwright: - image: mcr.microsoft.com/playwright:v1.58.0-noble # Version must match requirements.txt + image: mcr.microsoft.com/playwright:v1.60.0-noble # Version must match requirements.txt container_name: playwright - command: npx -y playwright@1.58.0 run-server --port 3000 --host 0.0.0.0 + command: npx -y playwright@1.60.0 run-server --port 3000 --host 0.0.0.0 open-webui: environment: diff --git a/docs/SECURITY.md b/docs/SECURITY.md index f00c400243..aced4883c9 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -1,6 +1,8 @@ # Security Policy -Our primary goal is to ensure the protection and confidentiality of sensitive data stored by users on open-webui. +Our goal is to protect Open WebUI's users and their data, and to handle security reports with a clear, consistent, and publicly documented process. +We want to operate a transparent security process, in which accepted vulnerabilities are published openly as advisories so anyone can see what was found, how it was resolved and most importantly, which version contains a patch for it. +Our stance: a visible advisory history is evidence of active scrutiny and a disclosure process that works, not a measure of how fragile the software is. ## Supported Versions @@ -10,14 +12,55 @@ Our primary goal is to ensure the protection and confidentiality of sensitive da | dev | :x: | | others | :x: | -## Zero Tolerance for External Platforms +**If an issue is already fixed, or already being fixed in the open, at the time you file, the report will not be accepted** — it did not contribute to discovering or remediating the issue, and we will not publish an advisory for it. -Based on a precedent of an unacceptable degree of spamming and unsolicited communications from third-party platforms, we forcefully reaffirm our stance. **We refuse to engage with, join, or monitor any platforms outside of GitHub for vulnerability reporting.** Our reasons are not just procedural but are deep-seated in the ethos of our project, which champions transparency and direct community interaction inherent in the open-source culture. Any attempts to divert our processes to external platforms will be met with outright rejection. This policy is non-negotiable and understands no exceptions. +A fix counts as already-existing regardless of which branch it lives on — including `dev` — and regardless of whether it was silently resolved in an earlier version. Branch support status (see table above) governs where a vulnerability must be _reproducible_, not whether a fix already exists: a bug live in a supported branch but already fixed in `dev` is still an already-fixed issue under this rule. -Any reports or solicitations arriving from sources other than our designated GitHub repository will be dismissed without consideration. We’ve seen how external engagements can dilute and compromise the integrity of community-driven projects, and we’re not here to gamble with the security and privacy of our user community. +Two specific patterns this covers, both of which we reject: + +- Filing a report for a bug found in an **older version** that was already resolved by the time of the current supported version. +- **Monitoring our public commits or pull requests** and filing a report for an issue they already address or fix. We have observed automated monitoring of our public commits and PRs that produced reports against fixes others had already authored; this rule exists to reject that pattern. + +We need not decide whether you discovered the issue independently — we cannot, and it makes no difference. On the provable facts your report duplicates work that is already public and already fixed or being fixed; you filed strictly last, and there is no way to distinguish independent discovery from scraping. Credit for the issue belongs to whoever found or fixed it — who in turn forfeits their own claim to it by disclosing publicly instead of reporting it to us confidentially first. A publicly-disclosed fix therefore earns no advisory, and no credit for anyone. + +> [!TIP] +> **Before reporting, check whether your finding still reproduces on the `dev` branch** (and any other active development branch). +> We develop in the open, and a fix may already be committed there ahead of a release. Confirming this first saves you the effort of writing up a report we'd have to close as already-fixed. + +## Good-faith reports that aren't vulnerabilities + +If you've found something that you know is **not strictly a vulnerability under our policy** — but where public disclosure would still be irresponsible (e.g. an urgent dependency bump needed because of a downstream vuln, or similar) — you may **still report it privately** via [GitHub Security Advisories](https://github.com/open-webui/open-webui/security/advisories/new). We will handle it responsibly. + +In line with the CVE rules, we will **not** publish an advisory or mint a CVE for these — but we **will** act on them (e.g. ship the bump) and keep the report confidential until handled. +**Where a fix lands as a result of your report and you'd like credit, we'll try to acknowledge you (e.g. as a co-author on the change).** + +Thank you for your report! + +## What a Valid Report Gets You + +If your report describes a real vulnerability under this policy, here's what you can expect from us: + +- **Credit on the advisory.** You're named as the reporter on the published advisory. Where multiple reporters each demonstrated a distinct vector, every one of you is credited (see [Report Handling](#report-handling)). +- **Coordinated disclosure.** We won't publish out from under you while you're still working the issue with us. Status moves visibly on the advisory itself — including the CVE request — and GitHub notifies you of those updates, so you can follow it through to publication. +- **A real fix, handled responsibly.** For findings with broad or severe real-world impact, we may hold publication for up to ~2 weeks after the patched release so administrators can update before details are public. + +We're a small volunteer team, so what we _can't_ offer is a bounty or a guaranteed turnaround. What you get is a serious fix, honest credit, and a process that treats your work as the contribution it is. + +## Alignment with the CVE Program + +The **CVE Program rules** (and CNA operational rules) are the **baseline** for all CVE handling here, and this policy operates within them. Under those rules, the determination of whether a report constitutes a security vulnerability in Open WebUI is the vendor's to make; this policy documents the criteria by which we exercise that determination. Where the rules are silent, they still apply; where this policy specifies how we apply them to Open WebUI, it does so as the vendor's published disposition criteria, not as a replacement for or exception to the program rules. + +## Reporting Channel + +We accept vulnerability reports **only** through [GitHub Security Advisories](https://github.com/open-webui/open-webui/security/advisories/new). Reports submitted through **any** other platform — including but not limited to third-party vulnerability reporting platforms, vulnerability brokers, social media, email, Discord, or Reddit — will not be processed. + +This is not a procedural preference. As a volunteer- and community-driven project, our security process is built around the same transparency and direct community interaction as the rest of our work, and GitHub Security Advisories is where that process lives. We do not and cannot monitor or engage with external reporting platforms, and reports arriving through them will be closed without review. + +A report filed on another platform has no standing here: it confers no priority, establishes no filing date, and creates no obligation for us to triage, publish, or otherwise consider it. Only the GitHub Security Advisory record exists for the purposes of this policy — including determining who filed first. ## Foreign CNAs and Vendor Disposition +[Based on multiple precedents of foreign CNAs minting CVEs without communicating the report to us prior to publication and/or minting CVEs that do not withstand any scrutiny](https://docs.openwebui.com/security/vendor-dispositions/), this rule was established. When a report is filed via GitHub Security Advisories and the maintainers close it as out-of-scope per this policy, that closure is the **vendor's disposition** of the issue. A CVE Numbering Authority (CNA) that mints a CVE for such an issue without reflecting that vendor disposition in the resulting record is acting against vendor disposition. We respond to such records by: @@ -27,15 +70,18 @@ We respond to such records by: 3. Refusing to provide vendor statements, version mappings, fix references, or any other coordination that would lend authority to the record; 4. Escalating repeated patterns from a single CNA to the CVE Program Root. -**Channel compliance does not entitle a CNA to override vendor disposition.** Reporters who escalate a closed-as-out-of-scope GHSA report to a third-party CNA after vendor disposition has been issued are likewise considered to have acted against vendor disposition, and will be permanently barred from future GHSA submissions. +**Channel compliance does not entitle a CNA to override vendor disposition.** Reporters who escalate a closed-as-out-of-scope/not-a-vulnerability GHSA report to a third-party CNA after vendor disposition has been issued are likewise considered to have acted against vendor disposition, and **may be barred from future GHSA submissions.** -## Reporting a Vulnerability +## Rules for Reporting a Vulnerability -Reports not submitted through our designated GitHub repository will be disregarded, and we will categorically reject invitations to collaborate on external platforms. Our aggressive stance on this matter underscores our commitment to a secure, transparent, and open community where all operations are visible and contributors are accountable. +We appreciate the community's interest in identifying potential vulnerabilities! +If you want to report something that does not fulfill our rules and guidelines laid out here, you can still report it and we will handle it, [see our good faith reporting section for more information](#good-faith-reports-that-arent-vulnerabilities). -We appreciate the community's interest in identifying potential vulnerabilities. However, effective immediately, we will **not** accept low-effort vulnerability reports. Ensure that **submissions are constructive, actionable, reproducible, well documented and adhere to the following guidelines**: +However, effective immediately, we will **not** accept low-effort vulnerability reports. Ensure that **submissions are constructive, actionable, reproducible, well documented and adhere to the following guidelines**: -1. **Report MUST be a vulnerability:** A security vulnerability is an exploitable weakness where the system behaves in an unintended way, allowing attackers to bypass security controls, gain unauthorized access, execute arbitrary code, or escalate privileges. Configuration options, missing features, and expected protocol behavior are **not vulnerabilities**. A vulnerability must cross at least one of the security boundaries (Confidentiality, Integrity, Availability, Authenticity, Non-repudiation). **These boundaries are interpreted broadly; equivalent concepts in other security frameworks fall within them.** +**Security boundaries:** Throughout this policy, "the security boundaries" means the five we recognize: Confidentiality, Integrity, Availability, Authenticity, and Non-repudiation. We interpret these broadly — equivalent concepts from other security frameworks fall within them. A valid vulnerability must cross at least one of them against a party other than the reporter. + +1. **Report MUST be a vulnerability:** A security vulnerability is an exploitable weakness where the system behaves in an unintended way, allowing attackers to bypass security controls, gain unauthorized access, execute arbitrary code, or escalate privileges. Configuration options, missing features, and expected protocol behavior are not vulnerabilities. A vulnerability must cross at least one of the security boundaries (defined above). 2. **No Vague Reports**: Submissions such as "I found a vulnerability" without any details will be treated as spam and will not be accepted. @@ -46,24 +92,17 @@ We appreciate the community's interest in identifying potential vulnerabilities. > [!NOTE] > A PoC (Proof of Concept) is a **demonstration of exploitation of a vulnerability**. Your PoC must show: > -> 1. Exactly what security boundary was crossed (Confidentiality, Integrity, Availability, Authenticity, Non-repudiation - These boundaries are interpreted broadly; equivalent concepts in other security frameworks fall within them) +> 1. Exactly which security boundary was crossed > 2. How this vulnerability is triggered/abused (inputs, endpoints, UI actions, etc.) > 3. What actions the attacker can now perform -> 4. What data/action becomes possible that should not be possible -> 5. Exact steps and commands to reproduce (copy/paste runnable where possible), expected result vs. actual result -> -> **Failure to provide a reproducible PoC may lead to closure of the report** -> -> We will notify you, if we struggle to reproduce the exploit using your PoC to allow you to improve your PoC. -> If we cannot reproduce the issue from your PoC, we may ask for clarification or improvements -> However, if we repeatedly cannot reproduce the exploit using the PoC, the report may be closed. +> 4. Exact steps and commands to reproduce (copy/paste runnable where possible), expected result vs. actual result 5. **Remediation is required**: Along with the PoC, you must provide **either**: -1. **A patch/PR**, **or** -2. **a remediation plan** ("actionable steps") that a maintainer can apply without guesswork. +1. **a remediation plan** (i.e. "actionable steps" that a maintainer can apply), **or** +2. **a patch/PR** Your remediation guidance can include, for example: @@ -72,7 +111,7 @@ Your remediation guidance can include, for example: - The **recommended fix approach** (validation/sanitization rules, auth checks, safe defaults, etc.) - Any **security tradeoffs** or potential regressions to watch for -6. **Default Configuration Testing**: All vulnerability reports must be tested and reproducible using Open WebUI's out-of-the-box default configuration. Claims of vulnerabilities that only manifest with explicitly weakened security settings may be discarded, unless they are covered by the following exception: +6. **Default Configuration Testing**: Vulnerability reports must be tested and reproducible using Open WebUI's out-of-the-box default configuration. Claims of vulnerabilities that only manifest with explicitly weakened security settings may be discarded, unless they are covered by the following exception: > [!NOTE] > **Note**: If you believe you have found a security issue that @@ -81,13 +120,9 @@ Your remediation guidance can include, for example: > 2. represents a genuine bypass of intended security controls, **or** > 3. works only with non-default configurations, **but the configuration in question is likely to be used by production deployments**, **then we absolutely want to hear about it.** This policy is intended to filter configuration issues and deployment problems, not to discourage legitimate security research. -7. **Threat Model Understanding Required**: Reports must demonstrate understanding of Open WebUI's self-hosted, authenticated, extensible, role-based access control architecture. Comparing Open WebUI to services with fundamentally different security models without acknowledging the architectural differences may result in report rejection. +7. **Threat Model Understanding Required**: Reports must demonstrate understanding of Open WebUI's self-hosted, single-tenant, authenticated, extensible, role-based access control architecture. Comparing Open WebUI to services with fundamentally different security models without acknowledging the architectural differences may result in report rejection. -8. **CVSS Scoring Accuracy:** If you include a CVSS score with your report, it must accurately reflect the vulnerability according to CVSS methodology. Common errors include 1) rating PR:N (None) when authentication is required, 2) scoring hypothetical attack chains instead of the actual vulnerability, or 3) inflating severity without evidence. **We will adjust inaccurate CVSS scores.** Intentionally inflated scores may result in report rejection. - -> [!WARNING] -> -> **Using CVE Precedents:** If you cite other CVEs to support your report, ensure they are **genuinely comparable** in vulnerability type, threat model, and attack vector. Citing CVEs from different product categories, different vulnerability classes or different deployment models will lead us to suspect the use of AI in your report. +8. **CVSS Scoring Accuracy:** You do not have to include a CVSS score in your report. If you leave the CVSS section empty, we will fill it out for you prior to publishing. If you include a CVSS score with your report, it must accurately reflect the vulnerability according to CVSS methodology. In case of inaccurate CVSS, we will adjust the CVSS score of your report. If you cite other CVEs to support your report, ensure they are **genuinely comparable** in vulnerability type, threat model, and attack vector. 9. **Admin Actions Are Out of Scope:** Vulnerabilities that require an administrator to actively perform unsafe actions are **not considered valid vulnerabilities**. **Admins have full system control and are expected to understand the security implications of their actions and configurations**. This includes but is not limited to: adding malicious external servers (models, tools, webhooks, functions), pasting untrusted code into Functions/Tools, or intentionally weakening security settings. **Reports requiring admin negligence or social engineering of admins may be rejected.** @@ -95,12 +130,12 @@ Your remediation guidance can include, for example: > Similar to rule "Default Configuration Testing": If you believe you have found a vulnerability that affects admins and is NOT caused by admin negligence or intentionally malicious actions, > **then we absolutely want to hear about it.** This policy is intended to filter social engineering attacks on admins, malicious plugins being deployed by admins and similar malicious actions, not to discourage legitimate security research. -10. **Tools & Functions Code Execution Is Intended Behavior:** Open WebUI's Tools and Functions feature is **designed** to execute user-provided Python code on the server. This is core, intentional functionality — not a vulnerability (see also rule 7, [Threat Model Understanding](#threat-model-understanding-required)). Function creation is **restricted to administrators only**. Tool creation is controlled by the `workspace.tools` permission, which is **disabled by default** for non-admin users and should only be granted to fully trusted users who are equivalent to system administrators in terms of trust. **Granting a user the ability to create Tools is equivalent to giving them shell access to the server**. If an administrator grants this permission to untrusted users, this constitutes intentional misconfiguration and is additionally covered by rule 9 ([Admin Actions Are Out of Scope](#admin-actions-are-out-of-scope)). More generally, **reports describing ANY attack chain that involves Tools or Functions — including but not limited to code execution, file access, network requests, or environment variable access — will be closed as not a vulnerability / intended behavior.** This applies to both direct code execution and frontmatter-based package installation (`pip install`). +10. **Tools & Functions Code Execution Is Intended Behavior:** Open WebUI's Tools and Functions feature is **designed** to execute user-provided Python code on the server. This is core, intentional functionality — not a vulnerability (see also 'Threat Model Understanding'). Function creation is **restricted to administrators only**. Tool creation is controlled by the `workspace.tools` permission, which is **disabled by default** for non-admin users and should only be granted to fully trusted users who are equivalent to system administrators in terms of trust. **Granting a user the ability to create Tools is equivalent to giving them shell access to the server**. If an administrator grants this permission to untrusted users, this constitutes intentional misconfiguration and is additionally covered by 'Admin Actions Are Out of Scope'. More generally, **reports describing ANY attack chain that involves Tools or Functions — including but not limited to code execution, file access, network requests, or environment variable access — will be closed as not a vulnerability / intended behavior.** This applies to both direct code execution and frontmatter-based package installation (`pip install`). > [!IMPORTANT] > **For administrators:** Treat the `workspace.tools` permission as **root-equivalent access**. Only grant it to users you would trust with direct access to your server. If you enable this permission for untrusted users, you are accepting the risk of arbitrary code execution on your host. For more details, see our [Plugin Security documentation](https://docs.openwebui.com/features/extensibility/plugin/). -11. **Legacy Code Paths Are Out of Scope:** Open WebUI maintains some code paths that are explicitly marked as **legacy** in the official documentation. Legacy paths remain available — sometimes still the default — purely for **backwards-compatibility reasons**, not because they are the supported or maintained surface. The supported replacement is the migration target, and security and functional work happens on the replacement, not the legacy path. Reports describing a security boundary issue **on a legacy code path that does not also reproduce on the supported replacement** are out of scope under this rule. +11. **Legacy Code Paths Are Out of Scope:** Open WebUI maintains some code paths that are explicitly marked as legacy in the official documentation, which is authoritative as to what is legacy. Legacy paths remain available — sometimes still the default — purely for backwards-compatibility reasons, not because they are the supported or maintained surface. The supported replacement is the migration target, and security and functional work happens on the replacement, not the legacy path. Reports describing a security boundary issue on a legacy code path that does not also reproduce on the supported replacement are usually out of scope under this rule. > [!NOTE] > If you find a security issue that: @@ -110,51 +145,33 @@ Your remediation guidance can include, for example: > > we still want to hear about it. This rule is intended to filter reports that target deprecated paths with a documented modern alternative, not to discourage finding real bugs in paths users are still on. -12. **AI report transparency:** Due to an extreme spike in AI-aided vulnerability reports **you MUST DISCLOSE if AI was used in any capacity** - whether for writing the report, generating the PoC, or identifying the vulnerability. If AI helped you in any way shape or form in the creation of the report, PoC or finding the vulnerability, you MUST disclose it. +12. **AI report transparency:** Due to a spike in vulnerability reports **you must disclose if AI was used in any capacity** - whether for writing the report, generating the PoC, or identifying the vulnerability. If AI helped you in any way shape or form in the creation of the report, PoC or finding the vulnerability, you must disclose it. Note that AI-aided vulnerability reports **will not be rejected by us by default** but reports not declaring AI use, yet appear AI-aided will undergo severely more scrutiny. -> [!NOTE] -> AI-aided vulnerability reports **will not be rejected by us by default**. But: -> -> - If we suspect you used AI (but you did not disclose it to us), we will be asking thorough follow-up questions to validate your understanding of the reported vulnerability and Open WebUI itself. -> - If we suspect you used AI (but you did not disclose it to us) **and** your report ends up being invalid/not a vulnerability/not reproducible, then you **may be banned** from reporting future vulnerabilities. -> -> This measure was necessary due to the extreme rise in clearly AI written vulnerability reports, where the vast majority of them -> -> - were not a vulnerability -> - were faulty configurations rather than a real vulnerability -> - did not provide a PoC -> - violated any of the rules outlined here -> - had a clear lack of understanding of Open WebUI -> - wrote comments with conflicting information -> - used illogical and conflicting arguments - -13. **Self-Affecting Issues Are Not Vulnerabilities:** A vulnerability requires crossing a security boundary that affects **a party other than the reporter**. Crossing one of the five recognized security boundaries (Confidentiality, Integrity, Availability, Authenticity, Non-repudiation - These boundaries are interpreted broadly; equivalent concepts in other security frameworks fall within them) only against the reporter's own data, account, session, or environment is **not a vulnerability** - it is a bug, and belongs in the [Issue Tracker](https://github.com/open-webui/open-webui/issues), not in a security report. +13. **Self-Affecting Issues Are Not Vulnerabilities:** A vulnerability requires crossing a security boundary that affects **a party other than the reporter**. Crossing one of the security boundaries only against the reporter's own data, account, session, or environment is **not a vulnerability** - it is a bug, and belongs in the [Issue Tracker](https://github.com/open-webui/open-webui/issues), not in a security report. > [!NOTE] > This rule is about **who is harmed**, not about severity. A user modifying or deleting their own data, impairing their own session, observing their own configuration, or disabling security controls on their own account is out of scope under this rule, regardless of impact. > > If the same action also affects another user, the operator, the host system, or shared resources, identify that second party clearly in the PoC, and we want to hear about it. -**Non-compliant submissions will be closed, and repeat or extreme violators may be banned from submitting reports.** Our goal is to foster a constructive reporting environment where quality submissions promote better security for all users. - -## Where to report the vulnerability - -If you want to report a vulnerability and can meet the outlined requirements, [open a vulnerability report here](https://github.com/open-webui/open-webui/security/advisories/new). -If you feel like you are not able to follow ALL outlined requirements for vulnerability-specific reasons, still do report it, we will check every report either way. +**Non-compliant submissions may be closed, and repeat or extreme violators may be banned from submitting reports.** Our goal is to foster a constructive reporting environment where quality submissions promote better security for all users. +If you want to report something that does not fulfill our rules and guidelines laid out here, you can still report it and we will handle it, [see our good faith reporting section for more information](#good-faith-reports-that-arent-vulnerabilities). ## Expected Timeframe -Due to the very high volume of incoming vulnerability reports, issues, discussions, pull requests, and general project maintenance — lately compounded by an unbelievably high number of AI-generated reports (see [AI report transparency](#ai-report-transparency)) — our capacity to respond is limited. Open WebUI is a community-driven project maintained by a small team, and security reports are handled alongside all other project responsibilities. +We aim to triage new reports, ship fixes, and publish advisories promptly. However, due to the very high volume of incoming vulnerability reports, issues, discussions, pull requests, and general project maintenance — lately compounded by a high number of (AI-generated) reports — our capacity to respond is limited. Open WebUI is a community-driven project maintained by a small team, and security reports are handled alongside all other project responsibilities. -**Please expect several weeks** for your report to be triaged, investigated, fixed, and published. While we aim to respond to every report as quickly as possible, it is normal to experience periods of silence lasting up to several weeks. **This does not mean your report has been ignored** — it means we have not yet had the capacity to address it. The entire process can realistically take multiple weeks from initial submission to final publication. We appreciate your patience and understanding. +**Please expect several weeks** for your report to be triaged, investigated, fixed, and published. While we aim to respond to every report as quickly as possible, it is normal to experience periods of silence lasting up to several weeks. **This does not mean your report has been ignored** — it means we have not yet had the capacity to address it. Feel free to post a follow-up comment on your advisory for visibility if you feel your report may have been lost; we'll get to you as soon as our capacity allows. The entire process can realistically take multiple weeks from initial submission to final publication. We appreciate your patience and understanding. -For findings we judge to have **broad or severe real-world impact** — regardless of CVSS score — we may hold off on publishing for **1–2 weeks** after the patched version is released, to give administrators time to update their instances. +**We do not accept reporter-imposed publishing deadlines.** We coordinate disclosure on our own schedule, and we will triage, fix, and publish as fast as we reasonably can. Externally-imposed hard timelines do not speed this up — they do the opposite: they pull our limited time away from actually fixing issues and toward managing a clock, **at the expense of every other report (even ones that might be more serious)** in the queue and the project as a whole. A deadline attached to your report will not change when or how fast it is handled. + +For findings we judge to have **broad or severe real-world impact** — regardless of CVSS score — we may hold off on publishing for a couple of days, max ~2 weeks after the patched version is released, to give administrators time to update their instances. ## Report Handling -If you report a valid vulnerability that somebody else reported before you, we will close your report as a duplicate. The earliest filing is the one we will handle going forward, and we will not publish multiple advisories for the same vulnerability. +When multiple independent reporters describe the same vulnerability class **but** each demonstrates a **distinct and separate exploitation vector** — for example, the same missing authorization check reached through different endpoints — we will consolidate them into the earliest filing **and credit every reporter who demonstrated a distinct path on the consolidated advisory**. Only one CVE will be issued for the consolidated advisory. -When multiple independent reporters describe the same vulnerability class but each demonstrates a **distinct and separate exploitation vector** — for example, the same missing authorization check reached through different endpoints — we will consolidate them into the earliest filing and credit every reporter who demonstrated a distinct path. Only one CVE will be issued for the consolidated advisory. +The other case: If you report a valid vulnerability that somebody else reported before you (identical vulnerability, identical exploitation vector), we will close your report as a duplicate. The earliest filing is the one we will handle going forward, and we will not publish multiple advisories for the same vulnerability. ### Why duplicate reports don't receive credit @@ -166,37 +183,22 @@ We credit only the earliest filer of a given vulnerability: ## Responsible Disclosure -Vulnerability reports submitted through GitHub Security Advisories are **private and confidential**. Public disclosure of **ANY** details related to a submitted vulnerability report is **STRICTLY PROHIBITED** until the advisory has been **fully published** — not merely when a CVE ID has been assigned, but when the advisory itself is publicly visible. +Vulnerability reports submitted through GitHub Security Advisories are **private and confidential**. Generally: Public disclosure of **ANY** details is **STRICTLY PROHIBITED** until an advisory for the vulnerability has been **fully published** — not merely when a CVE ID has been assigned, but when an advisory itself is publicly visible. -This prohibition applies to **all channels**, including but not limited to: - -- Comments on pull requests, issues, or discussions (on GitHub or elsewhere) -- Social media, blogs, forums, or any other website -- Discord, Reddit, or any other platform, website or service +This prohibition applies to **all channels**, including but not limited to comments on pull requests, issues, or discussions (on GitHub or elsewhere), social media (Discord, Reddit or any other platform), blogs, forums, or any other website or service. This confidential, responsible disclosure process exists to give us time to fix bugs, publish fixes and alert users once a fix is ready. The entire premise of responsible disclosure is to **protect users from vulnerabilities**. Therefore, premature disclosure undermines the security of all Open WebUI users and **violates the trust** inherent in the responsible disclosure process. **Reporters who prematurely publicly disclose vulnerability details before official publication WILL BE PERMANENTLY BANNED from future reporting.** -## Product Security And For Non-Vulnerability Related Security Concerns: +## For Non-Vulnerability Related Questions or Security Concerns: -If your concern does not meet the vulnerability requirements outlined above, is not a vulnerability, **but is still related to security concerns**, then use the following channels instead: +You can use the following channels: - **Documentation issues/improvement ideas:** Open an issue on our [Documentation Repository](https://github.com/open-webui/docs) - **Feature requests:** Create a discussion in [GitHub Discussions - Ideas](https://github.com/open-webui/open-webui/discussions/) to discuss with the community if this feature request is wanted by multiple people - **Configuration help:** Ask the community for help and guidance on our [Discord Server](https://discord.gg/5rJgQTnV4s) or on [Reddit](https://www.reddit.com/r/OpenWebUI/) - **General issues:** Use our [Issue Tracker](https://github.com/open-webui/open-webui/issues) - **Bugs:** Report bugs to our [Issue Tracker](https://github.com/open-webui/open-webui/issues) - -**Examples of non-vulnerability, still security related concerns:** - -- Suggestions for better default configuration values -- Security hardening recommendations -- Deployment best practices guidance -- Unclear configuration instructions -- Need for additional security documentation -- Feature requests for optional security enhancements (2FA, audit logging, etc.) -- General security questions about production deployment - -Please use the adequate channel for your specific issue - e.g. best-practice guidance or additional documentation needs into the [Documentation Repository](https://github.com/open-webui/docs), and feature requests into the Main Repository as an issue or discussion. +- **Best-practice guidance:** Help expand the [Documentation](https://github.com/open-webui/docs). We regularly audit our internal processes and system architecture for vulnerabilities using a combination of automated and manual testing techniques. We are also planning to implement SAST and SCA scans in our project soon. @@ -204,4 +206,4 @@ For any other immediate concerns and questions, please create an issue in our [i --- -_Last updated on **2026-05-14**._ +_Last updated on **2026-06-13**._ diff --git a/package-lock.json b/package-lock.json index 249d3606c2..362335b4b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.9.6", + "version": "0.10.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.9.6", + "version": "0.10.0", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", @@ -93,15 +93,15 @@ "prosemirror-view": "^1.34.3", "pyodide": "^0.28.2", "shiki": "^4.0.1", - "socket.io-client": "^4.2.0", + "socket.io-client": "^4.8.3", "sortablejs": "^1.15.6", "sql.js": "^1.14.1", "svelte-sonner": "^0.3.19", "tippy.js": "^6.3.7", "turndown": "^7.2.0", "turndown-plugin-gfm": "^1.0.2", - "undici": "^7.3.0", - "uuid": "^9.0.1", + "undici": "^7.28.0", + "uuid": "^11.1.1", "vega": "^6.2.0", "vega-lite": "^6.4.1", "vite-plugin-static-copy": "^2.2.0", @@ -2914,12 +2914,6 @@ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", "license": "BSD-3-Clause" }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.2.tgz", - "integrity": "sha512-pa0vFRuws4wkvaXKK1uXZMAwAX4/t8ANaJo45iw/oQHNQ9q5xUzwgFmVJGXiga2BeN+zpX7Vf9vmsiIa2J+MUw==", - "license": "BSD-3-Clause" - }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", @@ -3550,9 +3544,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.61.1", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.61.1.tgz", - "integrity": "sha512-Ny8s1SR1TyQS2hD2Rvw0XKzU2Nw1eUF52dTb6T2bdcgz7wSC+Nyb5IwjWYlR4b2dvbbR5NJDiQwHg3rnNseghg==", + "version": "2.68.0", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.68.0.tgz", + "integrity": "sha512-PdKiWsqinAoubVsSiRgVFkg3MHzGhQPnwQ8VxnGQKpZYijpapZ3UHHBje0GeByt2TvfjHPw+kxV+dNK2RIZg9g==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.0.0", @@ -7685,9 +7679,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz", - "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==", + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", + "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -7782,39 +7776,18 @@ } }, "node_modules/engine.io-client": { - "version": "6.6.5", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.5.tgz", - "integrity": "sha512-QCwxUDULPlXv8F6tqMMKx5dNkTe6OaBYRMPYeXKBlyOoKvAmE0ac6pW7fFhSscJ/5SI7666/U/B+MElbsrJlIg==", + "version": "6.6.6", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.6.tgz", + "integrity": "sha512-iY6QdftLQ9pyiPoX082bpf/u1UewnOaJrtJIF9T0++QB34lZrj0uP+Q/bj8AlUsAxqhnkTV2BS8SBZSxOmoV5Q==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.4.1", "engine.io-parser": "~5.2.1", - "ws": "~8.20.1", + "ws": "~8.21.0", "xmlhttprequest-ssl": "~2.1.1" } }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "8.20.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.1.tgz", - "integrity": "sha512-It4dO0K5v//JtTXuPkfEOaI3uUN87iYPnqo/ZzqCoG3g8uhA66QUMs/SrM0YK7/NAu+r4LMh/9dq2A7k+rHs+w==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/engine.io-parser": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", @@ -8678,17 +8651,17 @@ } }, "node_modules/form-data": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", - "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.2", - "mime-types": "^2.1.12" + "hasown": "^2.0.4", + "mime-types": "^2.1.35" }, "engines": { "node": ">= 6" @@ -9193,9 +9166,9 @@ } }, "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -9921,10 +9894,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", + "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -10459,9 +10442,19 @@ } }, "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.1.tgz", + "integrity": "sha512-wVoTjP4Q6R0NW5hiZkVJaFZPWgtXfoGF+6LucL3/FtiNjmcHhYjEr5f1Kqjirc1nBW07J/ZuRFumqr2oqccEWg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "uc.micro": "^2.0.0" @@ -10749,14 +10742,24 @@ "license": "BSD-3-Clause" }, "node_modules/markdown-it": { - "version": "14.1.1", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.1.tgz", - "integrity": "sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==", + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.2.0.tgz", + "integrity": "sha512-1TGiQiJVRQ3NPmZH6sx5Cfnmg6GQm9jvC1ch4TK511NjSJvjzKLzn5pPfZRNZkRPZP0HqCioSndqH8v2nRaWVQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/markdown-it" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", - "linkify-it": "^5.0.0", + "linkify-it": "^5.0.1", "mdurl": "^2.0.0", "punycode.js": "^2.3.1", "uc.micro": "^2.1.0" @@ -10928,19 +10931,6 @@ "node": ">= 20" } }, - "node_modules/mermaid/node_modules/uuid": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", - "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "bin": { - "uuid": "dist/esm/bin/uuid" - } - }, "node_modules/micromark-util-character": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", @@ -12267,9 +12257,9 @@ } }, "node_modules/protobufjs": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.2.tgz", - "integrity": "sha512-N9EiLovGEQOJSPF26Ij7qUGvahfEnq0eeYZ02aigIedkmz1qZSwjnP9SBITHJuF/6MYbIW4HDN8zdYjsjqJKXQ==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.4.tgz", + "integrity": "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw==", "hasInstallScript": true, "license": "BSD-3-Clause", "dependencies": { @@ -12279,7 +12269,6 @@ "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", @@ -14077,9 +14066,9 @@ } }, "node_modules/tar": { - "version": "7.5.11", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", - "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "version": "7.5.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.19.tgz", + "integrity": "sha512-4LeEWl96twnS2Q7Bz4MGqgazLqO+hJN63GZxXoIqh1T3VweYD997gbU1ItNsQafqqXTXd5WFyFdReLtwvRBNiw==", "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/fs-minipass": "^4.0.0", @@ -14493,9 +14482,9 @@ } }, "node_modules/undici": { - "version": "7.24.3", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.3.tgz", - "integrity": "sha512-eJdUmK/Wrx2d+mnWWmwwLRyA7OQCkLap60sk3dOK4ViZR7DKwwptwuIvFBg2HaiP9ESaEdhtpSymQPvytpmkCA==", + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", + "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", "license": "MIT", "engines": { "node": ">=20.18.1" @@ -14620,16 +14609,16 @@ } }, "node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" ], "license": "MIT", "bin": { - "uuid": "dist/bin/uuid" + "uuid": "dist/esm/bin/uuid" } }, "node_modules/value-or-function": { diff --git a/package.json b/package.json index 44cb943595..84603e61f2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.9.6", + "version": "0.10.0", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", @@ -137,15 +137,15 @@ "prosemirror-view": "^1.34.3", "pyodide": "^0.28.2", "shiki": "^4.0.1", - "socket.io-client": "^4.2.0", + "socket.io-client": "^4.8.3", "sortablejs": "^1.15.6", "sql.js": "^1.14.1", "svelte-sonner": "^0.3.19", "tippy.js": "^6.3.7", "turndown": "^7.2.0", "turndown-plugin-gfm": "^1.0.2", - "undici": "^7.3.0", - "uuid": "^9.0.1", + "undici": "^7.28.0", + "uuid": "^11.1.1", "vega": "^6.2.0", "vega-lite": "^6.4.1", "vite-plugin-static-copy": "^2.2.0", diff --git a/pyproject.toml b/pyproject.toml index 7d98f25b41..468543e71c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,87 +6,85 @@ authors = [ ] license = { file = "LICENSE" } dependencies = [ - "fastapi==0.135.1", + "fastapi==0.136.3", "uvicorn[standard]==0.41.0", - "pydantic==2.12.5", - "python-multipart==0.0.22", + "pydantic==2.13.4", + "python-multipart==0.0.27", "itsdangerous==2.2.0", - "python-socketio==5.16.1", + "python-socketio==5.16.2", "python-jose==3.5.0", - "cryptography==46.0.5", + "cryptography==48.0.0", "bcrypt==5.0.0", "argon2-cffi==25.1.0", - "PyJWT[crypto]==2.11.0", - "authlib==1.6.10", + "PyJWT[crypto]==2.13.0", + "authlib==1.7.2", - "requests==2.33.1", + "requests==2.34.2", "aiohttp==3.13.5", # do not update to 3.13.3 - broken "async-timeout==5.0.1", "aiocache==0.12.3", "aiofiles==25.1.0", - "starlette-compress==1.7.0", + "starlette-compress==1.7.1", "Brotli==1.2.0", "brotlicffi==1.2.0.1", "httpx[socks,http2,zstd,cli,brotli]==0.28.1", "starsessions[redis]==2.2.1", "python-mimeparse==2.0.0", - "sqlalchemy[asyncio]==2.0.48", - "aiosqlite==0.21.0", - "psycopg[binary]==3.2.9", + "sqlalchemy[asyncio]==2.0.50", + "aiosqlite==0.22.1", + "psycopg[binary]==3.3.4", "alembic==1.18.4", - "peewee==3.19.0", - "peewee-migrate==1.14.3", - "pycrdt==0.12.47", - "redis==7.4.0", + "pycrdt==0.13.1", + "redis==8.0.0", # "valkey-glide-sync==2.3.1", # optional: install manually if VECTOR_DB=valkey - "pytz==2026.1.post1", + "pytz==2026.2", "APScheduler==3.11.2", - "RestrictedPython==8.1", + "RestrictedPython==8.2", "loguru==0.7.3", "asgiref==3.11.1", - "tiktoken==0.12.0", - "mcp==1.26.0", + "tiktoken==0.13.0", + "mcp==1.27.2", "openai==2.29.0", "anthropic==0.86.0", "google-genai==1.66.0", "langchain==1.2.10", - "langchain-community==0.4.1", - "langchain-classic==1.0.1", - "langchain-text-splitters==1.1.1", + "langchain-community==0.4.2", + "langchain-classic==1.0.7", + "langchain-text-splitters==1.1.2", "fake-useragent==2.2.0", - "chromadb==1.5.2", - "opensearch-py==3.1.0", - "PyMySQL==1.1.2", + "chromadb==1.5.9", + "opensearch-py==3.2.0", + "PyMySQL==1.2.0", "boto3==1.42.62", "transformers==5.5.4", - "sentence-transformers==5.4.0", + "sentence-transformers==5.5.1", "accelerate==1.13.0", "pyarrow==20.0.0", # fix: pin pyarrow version to 20 for rpi compatibility #15897 "einops==0.8.2", "ftfy==6.3.1", - "chardet==5.2.0", + "chardet==7.4.3", "pypdf==6.7.5", "fpdf2==2.8.7", - "pymdown-extensions==10.21", + "pymdown-extensions==10.21.3", "docx2txt==0.9", "python-pptx==1.0.2", "msoffcrypto-tool==6.0.0", - "nltk==3.9.3", + "nltk==3.9.4", "Markdown==3.10.2", "beautifulsoup4==4.14.3", - "pypandoc==1.16.2", - "pandas==3.0.1", + "pypandoc==1.17", + "pandas==3.0.3", "openpyxl==3.1.5", "pyxlsb==1.0.10", "xlrd==2.0.2", @@ -96,30 +94,30 @@ dependencies = [ "soundfile==0.13.1", "azure-ai-documentintelligence==1.0.2", - "pillow==12.1.1", + "pillow==12.2.0", "opencv-python-headless==4.13.0.92", "rapidocr-onnxruntime==1.4.4", "rank-bm25==0.2.2", - "onnxruntime==1.24.3", + "onnxruntime==1.26.0", "faster-whisper==1.2.1", - "black==26.3.1", + "black==26.5.1", "youtube-transcript-api==1.2.4", "pytube==15.0.0", "pydub==0.25.1", - "ddgs==9.11.3", + "ddgs==9.14.4", - "google-api-python-client==2.193.0", - "google-auth-httplib2==0.3.0", - "google-auth-oauthlib==1.3.0", + "google-api-python-client==2.197.0", + "google-auth-httplib2==0.4.0", + "google-auth-oauthlib==1.4.0", - "googleapis-common-protos==1.72.0", + "googleapis-common-protos==1.75.0", "google-cloud-storage==3.9.0", - "azure-identity==1.25.2", - "azure-storage-blob==12.28.0", + "azure-identity==1.25.3", + "azure-storage-blob==12.29.0", "ldap3==2.9.1", ] @@ -138,38 +136,38 @@ classifiers = [ [project.optional-dependencies] postgres = [ - "psycopg2-binary==2.9.11", + "psycopg2-binary==2.9.12", "pgvector==0.4.2", ] mariadb = [ "mariadb==1.1.14", ] unstructured = [ - "unstructured==0.18.31", + "unstructured==0.22.31", ] all = [ - "pymongo==4.16.0", - "psycopg2-binary==2.9.11", + "pymongo==4.17.0", + "psycopg2-binary==2.9.12", "pgvector==0.4.2", "moto[s3]>=5.0.26", "gcp-storage-emulator>=2024.8.3", "docker~=7.1.0", "pytest~=8.3.2", "pytest-docker~=3.2.5", - "playwright==1.58.0", # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary - "elasticsearch==9.3.0", + "playwright==1.60.0", # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary + "elasticsearch==9.4.1", - "qdrant-client==1.17.0", + "qdrant-client==1.18.0", "weaviate-client==4.20.3", - "pymilvus==2.6.9", + "pymilvus==2.6.14", "pinecone==6.0.2", "oracledb==3.4.2", "colbert-ai==0.2.22", - "azure-search-documents==11.6.0", - "unstructured==0.18.31", + "azure-search-documents==12.0.0", + "unstructured==0.22.31", ] [project.scripts] diff --git a/src/lib/apis/analytics/index.ts b/src/lib/apis/analytics/index.ts index 6bab2cbf81..88e16c48e1 100644 --- a/src/lib/apis/analytics/index.ts +++ b/src/lib/apis/analytics/index.ts @@ -246,7 +246,9 @@ export const getModelChats = async ( startDate: number | null = null, endDate: number | null = null, skip: number = 0, - limit: number = 50 + limit: number = 50, + orderBy: string | null = null, + direction: string | null = null ) => { let error = null; @@ -255,6 +257,8 @@ export const getModelChats = async ( if (endDate) searchParams.append('end_date', endDate.toString()); if (skip) searchParams.append('skip', skip.toString()); if (limit) searchParams.append('limit', limit.toString()); + if (orderBy) searchParams.append('order_by', orderBy); + if (direction) searchParams.append('direction', direction); const res = await fetch( `${WEBUI_API_BASE_URL}/analytics/models/${encodeURIComponent(modelId)}/chats?${searchParams.toString()}`, diff --git a/src/lib/apis/auths/index.ts b/src/lib/apis/auths/index.ts index 5368c86064..fcd5b1708c 100644 --- a/src/lib/apis/auths/index.ts +++ b/src/lib/apis/auths/index.ts @@ -254,6 +254,61 @@ export const updateLdapServer = async (token: string = '', body: object) => { return res; }; +export const getOAuthConfig = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/auths/admin/config/oauth`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateOAuthConfig = async (token: string, body: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/auths/admin/config/oauth`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify(body) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const userSignIn = async (email: string, password: string) => { let error = null; diff --git a/src/lib/apis/chats/index.ts b/src/lib/apis/chats/index.ts index 1916e35086..577b31cf49 100644 --- a/src/lib/apis/chats/index.ts +++ b/src/lib/apis/chats/index.ts @@ -1,6 +1,63 @@ import { WEBUI_API_BASE_URL } from '$lib/constants'; import { getTimeRange } from '$lib/utils'; +export const getChatConfig = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/config`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateChatConfig = async (token: string, config: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/config`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + }, + body: JSON.stringify(config) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const createNewChat = async (token: string, chat: object, folderId: string | null) => { let error = null; @@ -65,6 +122,38 @@ export const unarchiveAllChats = async (token: string) => { return res; }; +export const unshareAllChats = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/share/all`, { + method: 'DELETE', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { 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.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const importChats = async (token: string, chats: object[]) => { let error = null; @@ -255,6 +344,34 @@ export const getArchivedChatList = async ( })); }; +export const getArchivedChatCount = async (token: string = '') => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/archived/count`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getSharedChatList = async (token: string = '', page: number = 1, filter?: object) => { let error = null; @@ -1074,6 +1191,34 @@ export const updateChatById = async (token: string, id: string, chat: object) => return res; }; +export const deleteChatMessageById = async (token: string, id: string, messageId: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/chats/${id}/messages/${messageId}`, { + method: 'DELETE', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + ...(token && { authorization: `Bearer ${token}` }) + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const deleteChatById = async (token: string, id: string) => { let error = null; diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 7859a4e787..93df4464dc 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -1,7 +1,7 @@ import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants'; import type { Banner } from '$lib/types'; -export const importConfig = async (token: string, config) => { +export const importConfig = async (token: string, config: object) => { let error = null; const res = await fetch(`${WEBUI_API_BASE_URL}/configs/import`, { @@ -275,7 +275,8 @@ export const putOrchestratorPolicy = async ( url: string, key: string, policyId: string, - policyData: object + policyData: object, + authType: string = 'bearer' ): Promise => { let error = null; @@ -288,6 +289,7 @@ export const putOrchestratorPolicy = async ( body: JSON.stringify({ url: url.replace(/\/$/, ''), key, + auth_type: authType, policy_id: policyId, policy_data: policyData }) @@ -309,6 +311,91 @@ export const putOrchestratorPolicy = async ( return res; }; +export const putOrchestratorLifecycle = async ( + token: string, + url: string, + key: string, + policyId: string, + lifecycleData: object, + authType: string = 'bearer' +): Promise => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/terminal_servers/lifecycle`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + url: url.replace(/\/$/, ''), + key, + auth_type: authType, + policy_id: policyId, + lifecycle_data: lifecycleData + }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const refreshOrchestratorTerminals = async ( + token: string, + url: string, + key: string, + body: { + user_id?: string; + policy_id?: string; + only_idle?: boolean; + reset?: boolean; + }, + authType: string = 'bearer' +): Promise => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/terminal_servers/refresh`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + url: url.replace(/\/$/, ''), + key, + auth_type: authType, + ...body + }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + /** * Verify a terminal server connection via the backend proxy. * Used for system/admin connections to avoid CORS issues and API key exposure. @@ -379,6 +466,7 @@ type RegisterOAuthClientForm = { client_name?: string; client_secret?: string; oauth_server_url?: string; + oauth_scope?: string; }; export const registerOAuthClient = async ( @@ -421,6 +509,17 @@ export const getOAuthClientAuthorizationUrl = (clientId: string, type: null | st return `${WEBUI_BASE_URL}/oauth/clients/${oauthClientId}/authorize`; }; +export const initiateOAuthRedirect = (tool: { + id: string; + serverId: string; + authType?: string | null; +}) => { + sessionStorage.setItem('pendingOAuthToolId', tool.id); + sessionStorage.setItem('oauthRedirectInProgressToolId', tool.id); + const authUrl = getOAuthClientAuthorizationUrl(tool.serverId, tool.authType ?? 'mcp'); + window.open(authUrl, '_self', 'noopener'); +}; + export const getCodeExecutionConfig = async (token: string) => { let error = null; diff --git a/src/lib/apis/files/index.ts b/src/lib/apis/files/index.ts index 6c041452b7..433fe2d45f 100644 --- a/src/lib/apis/files/index.ts +++ b/src/lib/apis/files/index.ts @@ -145,10 +145,13 @@ export const uploadDir = async (token: string) => { return res; }; -export const getFiles = async (token: string = '') => { +export const getFiles = async (token: string = '', content: boolean = false) => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/files/`, { + const searchParams = new URLSearchParams(); + searchParams.append('content', String(content)); + + const res = await fetch(`${WEBUI_API_BASE_URL}/files/?${searchParams.toString()}`, { method: 'GET', headers: { Accept: 'application/json', @@ -180,7 +183,8 @@ export const searchFiles = async ( token: string, filename: string = '*', skip: number = 0, - limit: number = 50 + limit: number = 50, + content: boolean = false ) => { let error = null; @@ -188,6 +192,7 @@ export const searchFiles = async ( searchParams.append('filename', filename); searchParams.append('skip', String(skip)); searchParams.append('limit', String(limit)); + searchParams.append('content', String(content)); const res = await fetch(`${WEBUI_API_BASE_URL}/files/search?${searchParams.toString()}`, { method: 'GET', @@ -214,6 +219,34 @@ export const searchFiles = async ( return res; }; +export const getFileCount = async (token: string = '') => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/files/count`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getFileById = async (token: string, id: string) => { let error = null; diff --git a/src/lib/apis/folders/index.ts b/src/lib/apis/folders/index.ts index 5ac37a8251..b79e588947 100644 --- a/src/lib/apis/folders/index.ts +++ b/src/lib/apis/folders/index.ts @@ -234,3 +234,85 @@ export const deleteFolderById = async (token: string, id: string, deleteContents return res; }; + +export const updateFolderAccessById = async (token: string, id: string, accessGrants: any[]) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/folders/${id}/access/update`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify({ access_grants: accessGrants }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const getSharedFolders = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/folders/shared`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + return []; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const getSharedFolderChats = async (token: string, folderId: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/folders/${folderId}/shared/chats`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index 24b096cd75..70bd660e9a 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -1572,10 +1572,34 @@ export const getVersionUpdates = async (token: string) => { return res; }; -export const getWebhookUrl = async (token: string) => { +export type EventCatalogItem = { + event: string; + description: string; + message: string; +}; + +export type EventWebhookTarget = { + type: 'user' | 'group'; + id: string; +}; + +export type EventWebhook = { + id: string; + name: string; + url: string; + enabled: boolean; + events: string[]; + targets: EventWebhookTarget[] | null; + created_at?: number; + updated_at?: number; +}; + +export const getEvents = async ( + token: string +): Promise<{ schema: string; events: EventCatalogItem[] }> => { let error = null; - const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, { + const res = await fetch(`${WEBUI_BASE_URL}/api/events`, { method: 'GET', headers: { 'Content-Type': 'application/json', @@ -1596,21 +1620,18 @@ export const getWebhookUrl = async (token: string) => { throw error; } - return res.url; + return res; }; -export const updateWebhookUrl = async (token: string, url: string) => { +export const getEventWebhooks = async (token: string): Promise => { let error = null; - const res = await fetch(`${WEBUI_BASE_URL}/api/webhook`, { - method: 'POST', + const res = await fetch(`${WEBUI_BASE_URL}/api/events/webhooks`, { + method: 'GET', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` - }, - body: JSON.stringify({ - url: url - }) + } }) .then(async (res) => { if (!res.ok) throw await res.json(); @@ -1626,7 +1647,97 @@ export const updateWebhookUrl = async (token: string, url: string) => { throw error; } - return res.url; + return res; +}; + +export const createEventWebhook = async ( + token: string, + webhook: Partial +): Promise => { + let error = null; + + const res = await fetch(`${WEBUI_BASE_URL}/api/events/webhooks`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify(webhook) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateEventWebhook = async ( + token: string, + id: string, + webhook: Partial +): Promise => { + let error = null; + + const res = await fetch(`${WEBUI_BASE_URL}/api/events/webhooks/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify(webhook) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const deleteEventWebhook = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_BASE_URL}/api/events/webhooks/${id}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err; + return null; + }); + + if (error) { + throw error; + } + + return res; }; export interface ModelConfig { diff --git a/src/lib/apis/knowledge/index.ts b/src/lib/apis/knowledge/index.ts index d99e36f284..feb63ccdd8 100644 --- a/src/lib/apis/knowledge/index.ts +++ b/src/lib/apis/knowledge/index.ts @@ -38,6 +38,304 @@ export const createNewKnowledge = async ( return res; }; +export const getExternalKnowledgeConnections = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/connections`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const createExternalKnowledgeConnection = async (token: string, connection: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/connections`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(connection) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateExternalKnowledgeConnection = async ( + token: string, + id: string, + connection: object +) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/connections/${id}`, { + method: 'PATCH', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(connection) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const deleteExternalKnowledgeConnection = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/connections/${id}`, { + method: 'DELETE', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const testExternalKnowledgeConnection = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/connections/${id}/test`, { + 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(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const testExternalKnowledgeRetrieval = async ( + token: string, + id: string, + payload: object +) => { + let error = null; + + const res = await fetch( + `${WEBUI_API_BASE_URL}/knowledge/external/connections/${id}/retrieve-test`, + { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(payload) + } + ) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const testExternalKnowledgeSource = async (token: string, payload: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/source/test`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(payload) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const createExternalKnowledgeSource = async (token: string, payload: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/source/create`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(payload) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateExternalKnowledgeSource = async (token: string, id: string, payload: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/source/${id}`, { + method: 'PATCH', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(payload) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const createExternalKnowledge = async (token: string, payload: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/external/knowledge/create`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify(payload) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + error = err.detail; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getKnowledgeBases = async (token: string = '', page: number | null = null) => { let error = null; @@ -76,13 +374,15 @@ export const searchKnowledgeBases = async ( token: string = '', query: string | null = null, viewOption: string | null = null, - page: number | null = null + page: number | null = null, + source: string | null = null ) => { let error = null; const searchParams = new URLSearchParams(); if (query) searchParams.append('query', query); if (viewOption) searchParams.append('view_option', viewOption); + if (source) searchParams.append('source', source); if (page) searchParams.append('page', page.toString()); const res = await fetch(`${WEBUI_API_BASE_URL}/knowledge/search?${searchParams.toString()}`, { diff --git a/src/lib/apis/memories/index.ts b/src/lib/apis/memories/index.ts index d8fdc638fa..5ebee8fb47 100644 --- a/src/lib/apis/memories/index.ts +++ b/src/lib/apis/memories/index.ts @@ -28,7 +28,7 @@ export const getMemories = async (token: string) => { return res; }; -export const addNewMemory = async (token: string, content: string) => { +export const addNewMemory = async (token: string, content: string, type = 'user', path = '') => { let error = null; const res = await fetch(`${WEBUI_API_BASE_URL}/memories/add`, { @@ -39,7 +39,9 @@ export const addNewMemory = async (token: string, content: string) => { authorization: `Bearer ${token}` }, body: JSON.stringify({ - content: content + content: content, + type, + path }) }) .then(async (res) => { @@ -59,8 +61,15 @@ export const addNewMemory = async (token: string, content: string) => { return res; }; -export const updateMemoryById = async (token: string, id: string, content: string) => { +export const updateMemoryById = async ( + token: string, + id: string, + content: string, + type?: string, + path?: string +) => { let error = null; + const body = { content, ...(type ? { type } : {}), ...(path !== undefined ? { path } : {}) }; const res = await fetch(`${WEBUI_API_BASE_URL}/memories/${id}/update`, { method: 'POST', @@ -69,9 +78,7 @@ export const updateMemoryById = async (token: string, id: string, content: strin 'Content-Type': 'application/json', authorization: `Bearer ${token}` }, - body: JSON.stringify({ - content: content - }) + body: JSON.stringify(body) }) .then(async (res) => { if (!res.ok) throw await res.json(); diff --git a/src/lib/apis/models/index.ts b/src/lib/apis/models/index.ts index e7abaa309e..11866e1fb6 100644 --- a/src/lib/apis/models/index.ts +++ b/src/lib/apis/models/index.ts @@ -90,6 +90,37 @@ export const getModelTags = async (token: string = '') => { return res; }; +export const getBaseModelTags = async (token: string = '') => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/models/base/tags`, { + method: 'GET', + 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; + console.error(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const importModels = async (token: string, models: object[]) => { let error = null; @@ -118,10 +149,15 @@ export const importModels = async (token: string, models: object[]) => { return res; }; -export const getBaseModels = async (token: string = '') => { +export const getBaseModels = async (token: string = '', tag: string = '') => { let error = null; - const res = await fetch(`${WEBUI_API_BASE_URL}/models/base`, { + const searchParams = new URLSearchParams(); + if (tag) { + searchParams.append('tag', tag); + } + + const res = await fetch(`${WEBUI_API_BASE_URL}/models/base?${searchParams.toString()}`, { method: 'GET', headers: { Accept: 'application/json', diff --git a/src/lib/apis/retrieval/index.ts b/src/lib/apis/retrieval/index.ts index a84e7b6822..dccb5950b3 100644 --- a/src/lib/apis/retrieval/index.ts +++ b/src/lib/apis/retrieval/index.ts @@ -54,9 +54,11 @@ type RAGConfigForm = { PDF_EXTRACT_IMAGES?: boolean; ENABLE_GOOGLE_DRIVE_INTEGRATION?: boolean; ENABLE_ONEDRIVE_INTEGRATION?: boolean; + EXTERNAL_DOCUMENT_LOADER_HEADERS?: Record; chunk?: ChunkConfigForm; content_extraction?: ContentExtractConfigForm; web_loader_ssl_verification?: boolean; + web?: Record; youtube?: YoutubeConfigForm; }; diff --git a/src/lib/apis/terminal/index.ts b/src/lib/apis/terminal/index.ts index 69ee2c5a0a..ee38a9a8fa 100644 --- a/src/lib/apis/terminal/index.ts +++ b/src/lib/apis/terminal/index.ts @@ -15,8 +15,23 @@ export type TerminalFeatures = { terminal?: boolean; }; +export type TerminalFileRoot = { + path: string; + label: string; +}; + +export type TerminalCwd = { + cwd: string | null; + home?: string; + root?: TerminalFileRoot; +}; + import { WEBUI_API_BASE_URL } from '$lib/constants'; +const bearerHeaders = (apiKey: string): Record => ({ + Authorization: `Bearer ${apiKey.trim()}` +}); + export type TerminalServer = { id: string; url: string; @@ -39,7 +54,7 @@ export const getTerminalConfig = async ( ): Promise<{ features: TerminalFeatures } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/api/config`; const res = await fetch(url, { - headers: { Authorization: `Bearer ${apiKey}` } + headers: bearerHeaders(apiKey) }).catch(() => null); if (!res || !res.ok) return null; return res.json().catch(() => null); @@ -49,14 +64,19 @@ export const getCwd = async ( baseUrl: string, apiKey: string, sessionId?: string -): Promise => { +): Promise => { const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`; - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { headers }).catch(() => null); if (!res || !res.ok) return null; const json = await res.json().catch(() => null); - return json?.cwd ?? null; + if (!json) return null; + return { + cwd: json?.cwd ?? null, + home: json?.home, + root: json?.root + }; }; export const listFiles = async ( @@ -67,7 +87,7 @@ export const listFiles = async ( ): Promise => { // The endpoint uses `directory` as the query param name const url = `${baseUrl.replace(/\/$/, '')}/files/list?directory=${encodeURIComponent(path)}`; - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { headers }) .then(async (res) => { @@ -88,7 +108,7 @@ export const readFile = async ( sessionId?: string ): Promise => { const url = `${baseUrl.replace(/\/$/, '')}/files/read?path=${encodeURIComponent(path)}`; - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { headers }).catch((err) => { console.error('open-terminal readFile error:', err); @@ -116,7 +136,7 @@ export const downloadFileBlob = async ( sessionId?: string ): Promise<{ blob: Blob; filename: string } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/files/view?path=${encodeURIComponent(path)}`; - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { headers }).catch(() => null); @@ -135,7 +155,7 @@ export const archiveFromTerminal = async ( ): Promise<{ blob: Blob; filename: string } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/files/archive`; const headers: Record = { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }; if (sessionId) headers['X-Session-Id'] = sessionId; @@ -164,7 +184,7 @@ export const uploadToTerminal = async ( const url = `${baseUrl.replace(/\/$/, '')}/files/upload?directory=${encodeURIComponent(directory)}`; const body = new FormData(); body.append('file', file); - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { method: 'POST', @@ -190,7 +210,7 @@ export const createDirectory = async ( ): Promise<{ path: string } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/files/mkdir`; const headers: Record = { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }; if (sessionId) headers['X-Session-Id'] = sessionId; @@ -217,7 +237,7 @@ export const deleteEntry = async ( sessionId?: string ): Promise<{ path: string; type: string } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/files/delete?path=${encodeURIComponent(path)}`; - const headers: Record = { Authorization: `Bearer ${apiKey}` }; + const headers: Record = bearerHeaders(apiKey); if (sessionId) headers['X-Session-Id'] = sessionId; const res = await fetch(url, { method: 'DELETE', @@ -242,7 +262,7 @@ export const setCwd = async ( ): Promise<{ cwd: string } | null> => { const url = `${baseUrl.replace(/\/$/, '')}/files/cwd`; const headers: Record = { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }; if (sessionId) headers['X-Session-Id'] = sessionId; @@ -271,7 +291,7 @@ export const moveEntry = async ( ): Promise<{ source: string; destination: string } | { error: string }> => { const url = `${baseUrl.replace(/\/$/, '')}/files/move`; const headers: Record = { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }; if (sessionId) headers['X-Session-Id'] = sessionId; @@ -297,7 +317,7 @@ export const getListeningPorts = async ( ): Promise => { const url = `${baseUrl.replace(/\/$/, '')}/ports`; const res = await fetch(url, { - headers: { Authorization: `Bearer ${apiKey}` } + headers: bearerHeaders(apiKey) }).catch(() => null); if (!res || !res.ok) return []; const json = await res.json().catch(() => null); @@ -321,7 +341,7 @@ export const createNotebookSession = async ( const res = await fetch(url, { method: 'POST', headers: { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }, body: JSON.stringify({ path }) @@ -354,7 +374,7 @@ export const executeNotebookCell = async ( const res = await fetch(url, { method: 'POST', headers: { - Authorization: `Bearer ${apiKey}`, + ...bearerHeaders(apiKey), 'Content-Type': 'application/json' }, body: JSON.stringify(body) @@ -381,7 +401,7 @@ export const stopNotebookSession = async ( const url = `${baseUrl.replace(/\/$/, '')}/notebooks/${sessionId}`; const res = await fetch(url, { method: 'DELETE', - headers: { Authorization: `Bearer ${apiKey}` } + headers: bearerHeaders(apiKey) }).catch(() => null); return res?.ok ?? false; }; diff --git a/src/lib/apis/users/index.ts b/src/lib/apis/users/index.ts index 267aa69d22..fb68ab8f61 100644 --- a/src/lib/apis/users/index.ts +++ b/src/lib/apis/users/index.ts @@ -85,6 +85,33 @@ export const updateUserDefaultPermissions = async (token: string, permissions: o return res; }; +export const getUserDefaultPermissionsDefaults = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/users/default/permissions/defaults`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const updateUserRole = async (token: string, id: string, role: string) => { let error = null; diff --git a/src/lib/components/AddConnectionModal.svelte b/src/lib/components/AddConnectionModal.svelte index 37f4a7eb68..26b1190465 100644 --- a/src/lib/components/AddConnectionModal.svelte +++ b/src/lib/components/AddConnectionModal.svelte @@ -436,7 +436,7 @@ - {#if !ollama && !direct} + {#if !direct}
+ +
+
+
+
+ {$i18n.t('Lifecycle JSON')} +
+
+ +
+
+ +
+
+ + +
+ +
{/if}
diff --git a/src/lib/components/AddToolServerModal.svelte b/src/lib/components/AddToolServerModal.svelte index 255739332e..1267007214 100644 --- a/src/lib/components/AddToolServerModal.svelte +++ b/src/lib/components/AddToolServerModal.svelte @@ -61,6 +61,8 @@ let oauthClientId = ''; let oauthClientSecret = ''; let oauthServerUrl = ''; + let oauthScope = ''; + let oauthResourceParameter = 'auto'; let enable = true; let loading = false; @@ -92,9 +94,11 @@ client_id: string; client_secret?: string; oauth_server_url?: string; + oauth_scope?: string; } = { url: url, client_id: id, + ...(oauthScope ? { oauth_scope: oauthScope } : {}), ...(auth_type === 'oauth_2.1_static' ? { client_secret: oauthClientSecret, oauth_server_url: oauthServerUrl } : {}) @@ -225,6 +229,8 @@ id = data.info.id ?? ''; name = data.info.name ?? ''; description = data.info.description ?? ''; + oauthScope = data.info.oauth_scope ?? ''; + oauthResourceParameter = data.info.oauth_resource_parameter ?? 'auto'; } if (data.config) { @@ -258,7 +264,13 @@ info: { id: id, name: name, - description: description + description: description, + ...(type === 'mcp' && ['oauth_2.1', 'oauth_2.1_static'].includes(auth_type) + ? { + ...(oauthScope ? { oauth_scope: oauthScope } : {}), + oauth_resource_parameter: oauthResourceParameter + } + : {}) } } ]); @@ -342,6 +354,12 @@ id: id, name: name, description: description, + ...(type === 'mcp' && ['oauth_2.1', 'oauth_2.1_static'].includes(auth_type) + ? { + ...(oauthScope ? { oauth_scope: oauthScope } : {}), + oauth_resource_parameter: oauthResourceParameter + } + : {}), ...(oauthClientInfo ? { oauth_client_info: oauthClientInfo } : {}), ...(auth_type === 'oauth_2.1_static' ? { @@ -377,6 +395,8 @@ oauthClientId = ''; oauthClientSecret = ''; oauthServerUrl = ''; + oauthScope = ''; + oauthResourceParameter = 'auto'; enable = true; functionNameFilterList = ''; @@ -404,6 +424,8 @@ oauthClientId = connection.info?.oauth_client_id ?? ''; oauthClientSecret = connection.info?.oauth_client_secret ?? ''; oauthServerUrl = connection.info?.oauth_server_url ?? ''; + oauthScope = connection.info?.oauth_scope ?? ''; + oauthResourceParameter = connection.info?.oauth_resource_parameter ?? 'auto'; enable = connection.config?.enable ?? true; functionNameFilterList = connection.config?.function_name_filter_list ?? ''; @@ -874,6 +896,51 @@
{/if} + {#if type === 'mcp' && ['oauth_2.1', 'oauth_2.1_static'].includes(auth_type)} +
+
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ {/if} + {#if !direct}
diff --git a/src/lib/components/AutomationModal.svelte b/src/lib/components/AutomationModal.svelte index c16265515e..f112d093c0 100644 --- a/src/lib/components/AutomationModal.svelte +++ b/src/lib/components/AutomationModal.svelte @@ -1,5 +1,5 @@ @@ -250,6 +272,9 @@ allLoaded={allChatsLoaded} showUserInfo={true} shareUrl={true} + orderBy={chatOrderBy} + direction={chatDirection} + onSort={setChatSort} onLoadMore={loadMoreChats} onChatClick={() => (show = false)} /> diff --git a/src/lib/components/admin/Analytics/Dashboard.svelte b/src/lib/components/admin/Analytics/Dashboard.svelte index 245d00fc6f..009ccf2744 100644 --- a/src/lib/components/admin/Analytics/Dashboard.svelte +++ b/src/lib/components/admin/Analytics/Dashboard.svelte @@ -24,12 +24,20 @@ // Time period - persist in localStorage let selectedPeriod = (typeof localStorage !== 'undefined' && localStorage.getItem('analyticsPeriod')) || '7d'; + + // Custom date range (YYYY-MM-DD) - persist in localStorage + let customStart = + (typeof localStorage !== 'undefined' && localStorage.getItem('analyticsCustomStart')) || ''; + let customEnd = + (typeof localStorage !== 'undefined' && localStorage.getItem('analyticsCustomEnd')) || ''; + $: periods = [ { value: '24h', label: $i18n.t('Last 24 hours') }, { value: '7d', label: $i18n.t('Last 7 days') }, { value: '30d', label: $i18n.t('Last 30 days') }, { value: '90d', label: $i18n.t('Last 90 days') }, - { value: 'all', label: $i18n.t('All time') } + { value: 'all', label: $i18n.t('All time') }, + { value: 'custom', label: $i18n.t('Custom range') } ]; // User group filter @@ -48,6 +56,12 @@ return { start: now - 30 * day, end: now }; case '90d': return { start: now - 90 * day, end: now }; + case 'custom': { + // Parse YYYY-MM-DD inputs; end date is inclusive (covers the full day) + const start = customStart ? Math.floor(new Date(customStart).getTime() / 1000) : null; + const end = customEnd ? Math.floor(new Date(customEnd).getTime() / 1000) + day - 1 : null; + return { start, end }; + } default: return { start: null, end: null }; } @@ -55,7 +69,13 @@ // Data let summary = { total_messages: 0, total_chats: 0, total_models: 0, total_users: 0 }; - let modelStats: Array<{ model_id: string; count: number; name?: string }> = []; + let modelStats: Array<{ + model_id: string; + count: number; + unique_users?: number; + unique_chats?: number; + name?: string; + }> = []; let userStats: Array<{ user_id: string; name?: string; email?: string; count: number }> = []; let dailyStats: Array<{ date: string; models: Record }> = []; let tokenStats: Record< @@ -140,7 +160,13 @@ loading = false; }; - $: if (selectedPeriod || selectedGroupId !== undefined) { + // Reload when the period, group, or custom range changes. + // In custom mode, wait until both dates are set to avoid a half-specified query. + $: if (selectedPeriod === 'custom' ? customStart && customEnd : selectedPeriod) { + // reference customStart/customEnd so this block reruns when they change + customStart; + customEnd; + selectedGroupId; loadDashboard(); } @@ -163,6 +189,16 @@ const bTokens = tokenStats[b.model_id]?.total_tokens ?? 0; return modelDirection === 'asc' ? aTokens - bTokens : bTokens - aTokens; } + if (modelOrderBy === 'users') { + const aUsers = a.unique_users ?? 0; + const bUsers = b.unique_users ?? 0; + return modelDirection === 'asc' ? aUsers - bUsers : bUsers - aUsers; + } + if (modelOrderBy === 'chats') { + const aChats = a.unique_chats ?? 0; + const bChats = b.unique_chats ?? 0; + return modelDirection === 'asc' ? aChats - bChats : bChats - aChats; + } return modelDirection === 'asc' ? a.count - b.count : b.count - a.count; }); @@ -187,7 +223,11 @@ localStorage.setItem('analyticsPeriod', selectedPeriod); } - onMount(loadDashboard); + // Persist custom date range + $: if (typeof localStorage !== 'undefined') { + localStorage.setItem('analyticsCustomStart', customStart); + localStorage.setItem('analyticsCustomEnd', customEnd); + } @@ -209,6 +249,21 @@ {/each} {/if} + {#if selectedPeriod === 'custom'} + + + + {/if} @@ -372,6 +373,7 @@ class="p-0.5 rounded-full hover:bg-gray-100 dark:hover:bg-gray-900 transition" on:click={() => { query = ''; + handleSearchInput(); }} > @@ -408,7 +410,8 @@ items={[ { value: 'pipe', label: $i18n.t('Pipe') }, { value: 'filter', label: $i18n.t('Filter') }, - { value: 'action', label: $i18n.t('Action') } + { value: 'action', label: $i18n.t('Action') }, + { value: 'event', label: $i18n.t('Event') } ]} />
diff --git a/src/lib/components/admin/Functions/FunctionEditor.svelte b/src/lib/components/admin/Functions/FunctionEditor.svelte index eca65e929f..f97b713bca 100644 --- a/src/lib/components/admin/Functions/FunctionEditor.svelte +++ b/src/lib/components/admin/Functions/FunctionEditor.svelte @@ -41,7 +41,8 @@ } let codeEditor; - let boilerplate = `""" + let starterType = 'filter'; + const filterBoilerplate = `""" title: Example Filter author: open-webui author_url: https://github.com/open-webui @@ -109,6 +110,52 @@ class Filter: return body `; + const eventBoilerplate = `""" +title: Example Event +author: open-webui +author_url: https://github.com/open-webui +funding_url: https://github.com/open-webui +version: 0.1 +""" + +from pydantic import BaseModel + + +class Event: + class Valves(BaseModel): + pass + + def __init__(self): + self.valves = self.Valves() + + async def event( + self, + event: dict, + __event_id__: str = None, + __event_name__: str = None, + __id__: str = None, + __app__=None, + __request__=None, + ): + print(f"event:{__name__}") + print(f"event:id:{__event_id__}") + print(f"event:name:{__event_name__}") + print(f"event:payload:{event}") +`; + let boilerplate = filterBoilerplate; + + /** @param {'filter' | 'event'} type */ + const setStarterType = (type) => { + starterType = type; + boilerplate = type === 'event' ? eventBoilerplate : filterBoilerplate; + content = boilerplate; + _content = boilerplate; + }; + + /** @param {string} value */ + const selectStarterType = (value) => { + setStarterType(value === 'event' ? 'event' : 'filter'); + }; const _boilerplate = `from pydantic import BaseModel from typing import Optional, Union, Generator, Iterator @@ -328,7 +375,18 @@ class Pipe:
-
+
+ {#if !edit} + + {/if}
diff --git a/src/lib/components/admin/Settings.svelte b/src/lib/components/admin/Settings.svelte index 6b7bfbf0b4..2d75066031 100644 --- a/src/lib/components/admin/Settings.svelte +++ b/src/lib/components/admin/Settings.svelte @@ -8,6 +8,7 @@ import { getBackendConfig } from '$lib/apis'; import Database from './Settings/Database.svelte'; + import Authentication from './Settings/Authentication.svelte'; import General from './Settings/General.svelte'; import Pipelines from './Settings/Pipelines.svelte'; import Audio from './Settings/Audio.svelte'; @@ -37,6 +38,7 @@ const tabFromPath = pathParts[pathParts.length - 1]; selectedTab = [ 'general', + 'authentication', 'connections', 'models', 'evaluations', @@ -94,6 +96,24 @@ 'channels' ] }, + { + id: 'authentication', + title: 'Authentication', + route: '/admin/settings/authentication', + keywords: [ + 'authentication', + 'auth', + 'login', + 'signup', + 'ldap', + 'oauth', + 'oidc', + 'sso', + 'roles', + 'groups', + 'identity' + ] + }, { id: 'connections', title: 'Connections', @@ -135,7 +155,21 @@ id: 'integrations', title: 'Integrations', route: '/admin/settings/integrations', - keywords: ['tools', 'integrations', 'plugins', 'extensions', 'functions', 'openapi', 'server'] + keywords: [ + 'tools', + 'integrations', + 'plugins', + 'extensions', + 'functions', + 'openapi', + 'server', + 'knowledge', + 'vector db', + 'qdrant', + 'rag', + 'retrieval', + 'sources' + ] }, { id: 'documents', @@ -308,6 +342,7 @@ + @@ -344,6 +379,19 @@ clip-rule="evenodd" /> + {:else if tab.id === 'authentication'} + + + {:else if tab.id === 'connections'} + {:else if selectedTab === 'authentication'} + {:else if selectedTab === 'connections'} { diff --git a/src/lib/components/admin/Settings/Audio.svelte b/src/lib/components/admin/Settings/Audio.svelte index 271c5b8fa9..cf893a24b0 100644 --- a/src/lib/components/admin/Settings/Audio.svelte +++ b/src/lib/components/admin/Settings/Audio.svelte @@ -14,6 +14,7 @@ import Spinner from '$lib/components/common/Spinner.svelte'; import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; + import TTSVoiceInput from '$lib/components/workspace/Models/TTSVoiceInput.svelte'; import { TTS_RESPONSE_SPLIT } from '$lib/types'; @@ -58,8 +59,18 @@ let STT_WHISPER_MODEL_LOADING = false; + type Voice = { + id: string; + name?: string; + description?: string; + meta?: { + description?: string; + }; + }; + // eslint-disable-next-line no-undef let voices: SpeechSynthesisVoice[] = []; + let providerVoices: Voice[] = []; let models: Awaited>['models'] = []; const getModels = async () => { @@ -82,6 +93,8 @@ const getVoices = async () => { if (TTS_ENGINE === '') { + providerVoices = []; + const getVoicesLoop = setInterval(() => { voices = speechSynthesis.getVoices(); @@ -92,14 +105,18 @@ } }, 100); } else { + voices = []; + const res = await _getVoices(localStorage.token).catch((e) => { toast.error(`${e}`); }); if (res) { console.log(res); - voices = res.voices; - voices.sort((a, b) => a.name.localeCompare(b.name, $i18n.resolvedLanguage)); + providerVoices = res.voices ?? []; + providerVoices.sort((a, b) => + (a.name ?? a.id).localeCompare(b.name ?? b.id, $i18n.resolvedLanguage) + ); } } }; @@ -679,18 +696,12 @@
{$i18n.t('TTS Voice')}
- - - - {#each voices as voice} - - {/each} -
@@ -736,18 +747,12 @@
{$i18n.t('TTS Voice')}
- - - - {#each voices as voice} - - {/each} -
@@ -777,18 +782,12 @@
{$i18n.t('TTS Voice')}
- - - - {#each voices as voice} - - {/each} -
@@ -820,18 +819,12 @@
{$i18n.t('TTS Voice')}
- - - - {#each voices as voice} - - {/each} -
diff --git a/src/lib/components/admin/Settings/Authentication.svelte b/src/lib/components/admin/Settings/Authentication.svelte new file mode 100644 index 0000000000..8e692d1c9d --- /dev/null +++ b/src/lib/components/admin/Settings/Authentication.svelte @@ -0,0 +1,776 @@ + + +
+
+ {#if adminConfig !== null} +
+
{$i18n.t('User Access')}
+ +
+ +
+
{$i18n.t('Default User Role')}
+
+ +
+
+ +
+
{$i18n.t('Default Group')}
+
+ +
+
+ +
+
{$i18n.t('Enable New Sign Ups')}
+ + +
+ +
+
{$i18n.t('Enable API Keys')}
+ + +
+ + {#if adminConfig?.ENABLE_API_KEYS} +
+
+ {$i18n.t('API Key Endpoint Restrictions')} +
+ + +
+ + {#if adminConfig?.ENABLE_API_KEYS_ENDPOINT_RESTRICTIONS} + + {/if} + {/if} + +
+
+
{$i18n.t('JWT Expiration')}
+
+ +
+ +
+ +
+ {$i18n.t('Valid time units:')} + {$i18n.t("'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.")} +
+ + {#if adminConfig.JWT_EXPIRES_IN === '-1'} +
+ +
+ {/if} +
+
{$i18n.t('Pending Accounts')}
+ +
+ +
+
+ {$i18n.t('Show Admin Details in Account Pending Overlay')} +
+ + +
+ + {#if adminConfig.SHOW_ADMIN_DETAILS} +
+
+
{$i18n.t('Admin Contact Email')}
+
+ +
+ +
+
+ {/if} + +
+
+ {$i18n.t('Pending User Overlay Title')} +
+ +
+ +
+
+
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ + {#if sourceForm.provider !== 'pgvector'} +
+
+ +
+
+ +
+
+ {/if} +
+ + {#if sourceForm.provider === 'milvus'} +
+
+
+ +
+
+ +
+
+
+ {/if} + +
+ +
+
+
+ +
+
+ +
+
+
+ + {#if sourceForm.provider === 'pgvector'} +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ {/if} + +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+ +
+
+ + + + + +
+ +
+ {$i18n.t( + 'External vectors must be generated with the same embedding model configured in Open WebUI.' + )} +
+
+
+ +
+ + + +
+
+ + +
+
+ +
+ + + + +
+
+
+
{$i18n.t('External Knowledge Sources')}
+ {$i18n.t('Experimental')} +
+ + + + +
+ +
+ {#each items as item} + {@const connection = connectionForItem(item)} +
+ +
+
+ + + + +
+ {item.name} + {' '} + + {item?.meta?.external?.provider ?? connection?.provider} + {item?.meta?.external?.source?.name ? `· ${item.meta.external.source.name}` : ''} + +
+
+
+
+ +
+ + + + + + { + toggleSource(item); + }} + /> + +
+
+ {/each} +
+ + {#if loading} +
+ +
+ {:else if items.length === 0} +
+ {$i18n.t('No external knowledge sources configured.')} +
+ {/if} + +
+
+ {$i18n.t( + 'Create one read-only Knowledge source per external collection. Test must pass before the source is created.' + )} +
+
+
diff --git a/src/lib/components/admin/Settings/General.svelte b/src/lib/components/admin/Settings/General.svelte index ddb81e844b..44c4f44628 100644 --- a/src/lib/components/admin/Settings/General.svelte +++ b/src/lib/components/admin/Settings/General.svelte @@ -2,18 +2,9 @@ import DOMPurify from 'dompurify'; import { v4 as uuidv4 } from 'uuid'; - import { getBackendConfig, getVersionUpdates, getWebhookUrl, updateWebhookUrl } from '$lib/apis'; - import { - getAdminConfig, - getLdapConfig, - getLdapServer, - updateAdminConfig, - updateLdapConfig, - updateLdapServer - } from '$lib/apis/auths'; + import { getBackendConfig, getVersionUpdates } from '$lib/apis'; + import { getAdminConfig, updateAdminConfig } from '$lib/apis/auths'; import { getBanners, setBanners } from '$lib/apis/configs'; - import { getGroups } from '$lib/apis/groups'; - import SensitiveInput from '$lib/components/common/SensitiveInput.svelte'; import Switch from '$lib/components/common/Switch.svelte'; import Tooltip from '$lib/components/common/Tooltip.svelte'; import { WEBUI_BUILD_HASH, WEBUI_VERSION } from '$lib/constants'; @@ -24,40 +15,22 @@ import { toast } from 'svelte-sonner'; import Textarea from '$lib/components/common/Textarea.svelte'; import Banners from './Interface/Banners.svelte'; + import Events from './Events.svelte'; const i18n = getContext('i18n'); export let saveHandler: Function; - let updateAvailable = null; + let updateAvailable = false; let version = { - current: '', - latest: '' + current: WEBUI_VERSION, + latest: WEBUI_VERSION }; let adminConfig = null; - let webhookUrl = ''; - let groups = []; let banners: Banner[] = []; - // LDAP - let ENABLE_LDAP = false; - let LDAP_SERVER = { - label: '', - host: '', - port: '', - attribute_for_mail: 'mail', - attribute_for_username: 'uid', - app_dn: '', - app_dn_password: '', - search_base: '', - search_filters: '', - use_tls: false, - certificate_path: '', - ciphers: '' - }; - const checkForVersionUpdates = async () => { updateAvailable = null; version = await getVersionUpdates(localStorage.token).catch((error) => { @@ -73,26 +46,12 @@ console.info(updateAvailable); }; - const updateLdapServerHandler = async () => { - if (!ENABLE_LDAP) return; - const res = await updateLdapServer(localStorage.token, LDAP_SERVER).catch((error) => { - toast.error(`${error}`); - return null; - }); - if (res) { - toast.success($i18n.t('LDAP server updated')); - } - }; - const updateBanners = async () => { _banners.set(await setBanners(localStorage.token, banners)); }; const updateHandler = async () => { - webhookUrl = await updateWebhookUrl(localStorage.token, webhookUrl); const res = await updateAdminConfig(localStorage.token, adminConfig); - await updateLdapConfig(localStorage.token, ENABLE_LDAP); - await updateLdapServerHandler(); await updateBanners(); @@ -106,30 +65,9 @@ }; onMount(async () => { - if ($config?.features?.enable_version_update_check) { - checkForVersionUpdates(); - } + adminConfig = await getAdminConfig(localStorage.token); - await Promise.all([ - (async () => { - adminConfig = await getAdminConfig(localStorage.token); - })(), - - (async () => { - webhookUrl = await getWebhookUrl(localStorage.token); - })(), - (async () => { - LDAP_SERVER = await getLdapServer(localStorage.token); - })(), - (async () => { - groups = await getGroups(localStorage.token); - })() - ]); - - const ldapConfig = await getLdapConfig(localStorage.token); - ENABLE_LDAP = ldapConfig.ENABLE_LDAP; - - banners = await getBanners(localStorage.token); + banners = [...$_banners]; }); @@ -300,395 +238,6 @@ -
-
{$i18n.t('Authentication')}
- -
- -
-
{$i18n.t('Default User Role')}
-
- -
-
- -
-
{$i18n.t('Default Group')}
-
- -
-
- -
-
{$i18n.t('Enable New Sign Ups')}
- - -
- -
-
- {$i18n.t('Show Admin Details in Account Pending Overlay')} -
- - -
- - {#if adminConfig.SHOW_ADMIN_DETAILS} -
-
-
{$i18n.t('Admin Contact Email')}
-
- -
- -
-
- {/if} - -
-
- {$i18n.t('Pending User Overlay Title')} -
- + {/key} +
+
+ + {/if} + + {:else} +
+ +
+ {/if} {/if} {:else} diff --git a/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte b/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte index 23d26df782..6b47dcf72b 100644 --- a/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte +++ b/src/lib/components/workspace/Knowledge/KnowledgeBase/DirectoryRow.svelte @@ -116,7 +116,10 @@ + {$i18n.t('Upload')} + {/if} {/if} diff --git a/src/lib/components/workspace/Models/Knowledge/KnowledgeSelector.svelte b/src/lib/components/workspace/Models/Knowledge/KnowledgeSelector.svelte index 5677eae8c4..bed892c94b 100644 --- a/src/lib/components/workspace/Models/Knowledge/KnowledgeSelector.svelte +++ b/src/lib/components/workspace/Models/Knowledge/KnowledgeSelector.svelte @@ -34,12 +34,12 @@ $: items = [...noteItems, ...knowledgeItems, ...fileItems]; - $: if (query !== undefined) { + const handleSearchInput = () => { clearTimeout(searchDebounceTimer); searchDebounceTimer = setTimeout(() => { getItems(); }, 300); - } + }; onDestroy(() => { clearTimeout(searchDebounceTimer); @@ -111,6 +111,7 @@ if (e.detail === false) { onClose(); query = ''; + handleSearchInput(); } }} > @@ -118,16 +119,17 @@
-
+
-
+
@@ -141,7 +143,7 @@ {:else} {#each items as item, i} {#if i === 0 || item?.type !== items[i - 1]?.type} -
+
{#if item?.type === 'note'} {$i18n.t('Notes')} {:else if item?.type === 'collection'} @@ -153,7 +155,7 @@ {/if}
- + />
{/if} @@ -663,6 +698,7 @@
{ const tagName = e.detail; info.meta.tags = info.meta.tags.filter((tag) => tag.name !== tagName); @@ -854,10 +890,9 @@ {$i18n.t('TTS Voice')}
-
diff --git a/src/lib/components/workspace/Models/SkillsSelector.svelte b/src/lib/components/workspace/Models/SkillsSelector.svelte index 55c8b93977..01c38fd074 100644 --- a/src/lib/components/workspace/Models/SkillsSelector.svelte +++ b/src/lib/components/workspace/Models/SkillsSelector.svelte @@ -1,69 +1,62 @@
-
{$i18n.t('Skills')}
+
{$i18n.t('Skills')}
- {#if Object.keys(_skills).length > 10} -
- -
- {/if} -
{#if skills.length > 0} + { + selectSkill(e.detail); + }} + /> +
- {#each filteredSkillKeys as skill, skillIdx} + {#each selectedSkills as skill, skillIdx}
{ - _skills[skill].selected = e.detail === 'checked'; - selectedSkillIds = Object.keys(_skills).filter((s) => _skills[s].selected); + if (e.detail === 'unchecked') { + selectedSkillIds = selectedSkillIds.filter((id) => id !== skill.id); + } }} />
- -
- {_skills[skill].name} + +
+ {skill.name}
diff --git a/src/lib/components/workspace/Models/TTSVoiceInput.svelte b/src/lib/components/workspace/Models/TTSVoiceInput.svelte new file mode 100644 index 0000000000..ee2d91622c --- /dev/null +++ b/src/lib/components/workspace/Models/TTSVoiceInput.svelte @@ -0,0 +1,149 @@ + + + + + 0} + autocomplete="off" + on:focus={() => { + suggestionsOpen = true; + positionPopup(); + }} + on:input={() => { + suggestionsOpen = true; + positionPopup(); + }} + on:keydown={(event) => { + if (event.key === 'Escape') { + suggestionsOpen = false; + } + }} + on:blur={() => { + setTimeout(() => { + if (!popupElement?.contains(document.activeElement)) { + suggestionsOpen = false; + } + }, 0); + }} +/> + +{#if suggestionsOpen && filteredVoices.length > 0} +
+ {#each filteredVoices as voice (voice.id)} + + {/each} +
+{/if} diff --git a/src/lib/components/workspace/Models/ToolsSelector.svelte b/src/lib/components/workspace/Models/ToolsSelector.svelte index bbc484f907..09aa2241b2 100644 --- a/src/lib/components/workspace/Models/ToolsSelector.svelte +++ b/src/lib/components/workspace/Models/ToolsSelector.svelte @@ -1,51 +1,64 @@
-
{$i18n.t('Tools')}
+
{$i18n.t('Tools')}
{#if tools.length > 0} + { + selectTool(e.detail); + }} + /> +
- {#each Object.keys(_tools) as tool, toolIdx} + {#each selectedTools as tool, toolIdx}
{ - _tools[tool].selected = e.detail === 'checked'; - selectedToolIds = Object.keys(_tools).filter((t) => _tools[t].selected); + if (e.detail === 'unchecked') { + selectedToolIds = selectedToolIds.filter((id) => id !== tool.id); + } }} />
- -
- {_tools[tool].name} + +
+ {tool.name}
diff --git a/src/lib/components/workspace/Models/TypeaheadSelector.svelte b/src/lib/components/workspace/Models/TypeaheadSelector.svelte new file mode 100644 index 0000000000..047069b7bb --- /dev/null +++ b/src/lib/components/workspace/Models/TypeaheadSelector.svelte @@ -0,0 +1,35 @@ + + +
+ { + dispatch('select', e.detail); + value = ''; + }} + /> +
diff --git a/src/lib/components/workspace/Prompts.svelte b/src/lib/components/workspace/Prompts.svelte index 7974ee8ed3..31664ab8bc 100644 --- a/src/lib/components/workspace/Prompts.svelte +++ b/src/lib/components/workspace/Prompts.svelte @@ -59,18 +59,20 @@ let page = 1; - // Debounce only query changes - $: if (query !== undefined) { + const handleSearchInput = () => { loading = true; clearTimeout(searchDebounceTimer); searchDebounceTimer = setTimeout(() => { - page = 1; - getPromptList(); + if (page !== 1) { + page = 1; + } else { + getPromptList(); + } }, 300); - } + }; // Immediate response to page/filter changes - $: if (page && selectedTag !== undefined && viewOption !== undefined) { + $: if (loaded && page && selectedTag !== undefined && viewOption !== undefined) { getPromptList(); } @@ -130,7 +132,7 @@ const cloneHandler = async (prompt) => { const clonedPrompt = { ...prompt }; - clonedPrompt.title = `${clonedPrompt.title} (Clone)`; + clonedPrompt.name = `${clonedPrompt.name} (Clone)`; const baseCommand = clonedPrompt.command.startsWith('/') ? clonedPrompt.command.substring(1) : clonedPrompt.command; @@ -332,6 +334,7 @@ @@ -343,6 +346,7 @@ aria-label={$i18n.t('Clear search')} on:click={() => { query = ''; + handleSearchInput(); }} > @@ -468,6 +472,9 @@
{ + goto(`/workspace/prompts/${prompt.id}`); + }} shareHandler={() => { shareHandler(prompt); }} diff --git a/src/lib/components/workspace/Prompts/PromptMenu.svelte b/src/lib/components/workspace/Prompts/PromptMenu.svelte index 83bb5e1441..ffce23f396 100644 --- a/src/lib/components/workspace/Prompts/PromptMenu.svelte +++ b/src/lib/components/workspace/Prompts/PromptMenu.svelte @@ -11,6 +11,7 @@ const i18n = getContext('i18n'); + export let editHandler: Function; export let shareHandler: Function; export let cloneHandler: Function; export let exportHandler: Function; @@ -34,11 +35,37 @@
+ + {#if $config.features.enable_community_sharing} {/if} - {#if total && ($user?.role === 'admin' || $user?.permissions?.workspace?.skills)} + {#if total && ($user?.role === 'admin' || $user?.permissions?.workspace?.skills_export)} - {#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills} + {#if $user?.role === 'admin' || $user?.permissions?.workspace?.skills_export}
diff --git a/src/lib/constants/permissions.ts b/src/lib/constants/permissions.ts index b384e301b3..32538957ce 100644 --- a/src/lib/constants/permissions.ts +++ b/src/lib/constants/permissions.ts @@ -10,7 +10,9 @@ export const DEFAULT_PERMISSIONS = { prompts_import: false, prompts_export: false, tools_import: false, - tools_export: false + tools_export: false, + skills_import: false, + skills_export: false }, sharing: { models: false, @@ -25,6 +27,7 @@ export const DEFAULT_PERMISSIONS = { public_skills: false, notes: false, public_notes: false, + folders: false, public_chats: false, public_calendars: false }, @@ -46,6 +49,7 @@ export const DEFAULT_PERMISSIONS = { edit: true, share: true, export: true, + import: true, stt: true, tts: true, call: true, @@ -64,7 +68,8 @@ export const DEFAULT_PERMISSIONS = { code_interpreter: true, memories: true, automations: false, - calendar: true + calendar: true, + webhooks: false }, settings: { interface: true diff --git a/src/lib/i18n/locales/ar-BH/translation.json b/src/lib/i18n/locales/ar-BH/translation.json index 9abdb0c22d..a12c7cf811 100644 --- a/src/lib/i18n/locales/ar-BH/translation.json +++ b/src/lib/i18n/locales/ar-BH/translation.json @@ -20,6 +20,18 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_zero": "", + "{{count}} filters_one": "", + "{{count}} filters_two": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_zero": "", + "{{count}} groups_one": "", + "{{count}} groups_two": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_zero": "", @@ -37,12 +49,20 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_zero": "", + "{{count}} users_one": "", + "{{count}} users_two": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -50,8 +70,10 @@ "{{user}}'s Chats": "دردشات {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} مطلوب", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -69,6 +91,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "الحساب", @@ -84,6 +107,7 @@ "Activity": "", "Add": "أضف", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "أضف وصفا موجزا حول ما يفعله هذا النموذج", "Add a tag": "أضافة تاق", "Add a tag...": "", @@ -96,8 +120,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "إضافة ملفات", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -112,6 +138,7 @@ "Add to favorites": "", "Add User": "اضافة مستخدم", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -124,7 +151,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "لوحة التحكم", + "Admin Roles": "", "Admin Settings": "اعدادات المشرف", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "التعليمات المتقدمة", @@ -135,16 +164,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -164,9 +198,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "هل تملك حساب ؟", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -185,6 +221,7 @@ "API Base URL": "API الرابط الرئيسي", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API مفتاح", + "API Key / Token": "", "API Key created.": "API تم أنشاء المفتاح", "API Key Endpoint Restrictions": "", "API keys": "مفاتيح واجهة برمجة التطبيقات", @@ -214,13 +251,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -235,14 +277,20 @@ "Audio": "صوتي", "August": "أغسطس", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "النسخ التلقائي للاستجابة إلى الحافظة", - "Auto-playback response": "استجابة التشغيل التلقائي", + "Auto-Create Groups": "", + "Auto-Playback Response": "استجابة التشغيل التلقائي", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 الرابط الرئيسي", @@ -260,6 +308,7 @@ "Available Skills": "", "Available Tools": "", "available users": "المستخدمون المتاحون", + "Available variables": "", "available!": "متاح", "Away": "بعيد", "Awful": "", @@ -270,16 +319,17 @@ "Bad Response": "استجابة خطاء", "Banners": "لافتات", "Base Model (From)": "النموذج الأساسي (من)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "قبل", "Being lazy": "كون كسول", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -336,7 +386,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "اتجاه المحادثة", + "Chat Direction": "اتجاه المحادثة", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -408,6 +458,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "مجموعة", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -417,12 +468,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "الأوامر", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -448,6 +501,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -460,8 +514,16 @@ "Contact Admin for WebUI Access": "", "Content": "الاتصال", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "متابعة الرد", "Continue with {{provider}}": "", "Continue with Email": "", @@ -509,6 +571,7 @@ "Create new secret key": "عمل سر جديد", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "أنشئت في", @@ -526,6 +589,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -548,7 +612,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "النموذج الافتراضي", "Default model updated": "الإفتراضي تحديث الموديل", "Default permissions": "", @@ -558,6 +621,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "الإفتراضي صلاحيات المستخدم", + "Default webhook": "", "Defaults": "", "Delete": "حذف", "Delete {{name}}": "", @@ -618,6 +682,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "معطل", "Disconnect OAuth": "", "Discover a function": "", @@ -632,10 +698,10 @@ "Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة", + "Display the Username Instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -646,6 +712,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "المستند", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -701,12 +768,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "تعديل المستخدم", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -715,6 +784,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "البريد", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -723,6 +793,7 @@ "Embedding Model Engine": "تضمين محرك النموذج", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -730,22 +801,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "تمكين مشاركة المجتمع", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "تفعيل عمليات التسجيل الجديدة", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "ممكّن", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "تأكد من أن ملف CSV الخاص بك يتضمن 4 أعمدة بهذا الترتيب: Name, Email, Password, Role.", "Enter {{role}} message here": "أدخل رسالة {{role}} هنا", - "Enter a detail about yourself for your LLMs to recall": "ادخل معلومات عنك تريد أن يتذكرها الموديل", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -762,6 +838,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "أدخل الChunk Overlap", "Enter Chunk Size": "أدخل Chunk الحجم", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -799,8 +877,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "أدخل كود اللغة", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -820,6 +901,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "أدخل النتيجة", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -829,6 +911,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serpstack", "Enter server host": "", @@ -849,6 +932,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "أدخل Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "الرابط (e.g. http://127.0.0.1:7860/)", @@ -889,11 +974,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -921,12 +1010,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -944,6 +1039,7 @@ "Failed to create API Key.": "فشل في إنشاء مفتاح API.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -951,6 +1047,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -960,6 +1057,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "فشل في قراءة محتويات الحافظة", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -968,9 +1066,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -1003,6 +1103,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1025,6 +1127,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1055,6 +1158,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1087,7 +1191,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1099,6 +1206,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1129,6 +1237,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1154,6 +1264,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "تحديث مهم", @@ -1211,7 +1322,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "اختصارات لوحة المفاتيح", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1224,6 +1334,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1240,7 +1352,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1262,6 +1373,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "فاتح", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1285,6 +1397,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "من جهة اليسار إلى اليمين", "Made by Open WebUI Community": "OpenWebUI تم إنشاؤه بواسطة مجتمع ", "Make password visible in the user interface": "", @@ -1301,6 +1414,7 @@ "Manage Pipelines": "إدارة خطوط الأنابيب", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "مارس", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1328,6 +1442,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "نتيجة الردود المدمجة", "Message": "", @@ -1338,9 +1453,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "لن تتم مشاركة الرسائل التي ترسلها بعد إنشاء الرابط الخاص بك. سيتمكن المستخدمون الذين لديهم عنوان URL من عرض الدردشة المشتركة", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1393,6 +1511,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "المزيد", @@ -1410,6 +1529,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1439,6 +1559,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1451,8 +1572,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1480,6 +1603,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "لا توجد نتائج", "No results found": "لا توجد نتايج", "No search query generated": "لم يتم إنشاء استعلام بحث", @@ -1499,6 +1623,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "اي", + "Not configured": "", "Not factually correct": "ليس صحيحا من حيث الواقع", "Not helpful": "", "Not Registered": "", @@ -1514,20 +1639,25 @@ "Notifications": "إشعارات", "November": "نوفمبر", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "اكتوبر", "Off": "أغلاق", "Okay, Let's Go!": "حسنا دعنا نذهب!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED داكن", "Ollama": "Ollama", "Ollama API": "أولاما API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama الاصدار", + "Omit": "", "On": "تشغيل", "Once": "", "OneDrive": "", @@ -1598,6 +1728,7 @@ "Password": "الباسورد", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ملف (.pdf)", @@ -1606,18 +1737,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "قيد الانتظار", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "التخصيص", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1650,13 +1784,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "موقف ايجابي", @@ -1686,6 +1820,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com \"{{searchValue}}\" أسحب من ", "Pull a model from Ollama.com": "Ollama.com سحب الموديل من ", @@ -1703,21 +1839,33 @@ "Read": "", "Read Aloud": "أقراء لي", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "سجل صوت", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI إعادة توجيهك إلى مجتمع ", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_zero": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_two": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "رفض عندما لا ينبغي أن يكون", "Regenerate": "تجديد", "Regenerate Menu": "", @@ -1755,19 +1903,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "إعادة تقييم النموذج", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "إعادة تعيين الصورة", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1791,6 +1946,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "منصب", + "Roles Claim": "", "RTL": "من اليمين إلى اليسار", "Run": "", "Run All": "", @@ -1809,10 +1965,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "لم يعد حفظ سجلات الدردشة مباشرة في مساحة تخزين متصفحك مدعومًا. يرجى تخصيص بعض الوقت لتنزيل وحذف سجلات الدردشة الخاصة بك عن طريق النقر على الزر أدناه. لا تقلق، يمكنك بسهولة إعادة استيراد سجلات الدردشة الخاصة بك إلى الواجهة الخلفية من خلاله", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "البحث", "Search a model": "البحث عن موديل", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1822,6 +1980,7 @@ "Search Chats": "البحث في الدردشات", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1836,13 +1995,16 @@ "Search Models": "نماذج البحث", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "أبحث حث", "Search Result Count": "عدد نتائج البحث", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1858,7 +2020,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "حدد نموذجا أساسيا", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1896,18 +2057,25 @@ "semantic": "", "Send": "تم", "Send a Message": "يُرجى إدخال طلبك هنا", + "Send events for": "", "Send message": "يُرجى إدخال طلبك هنا.", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "سبتمبر", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "مفتاح واجهة برمجة تطبيقات سيربر", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "مفتاح واجهة برمجة تطبيقات Serpstack", "Server connection failed": "", "Server connection verified": "تم التحقق من اتصال الخادم", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "الافتراضي", "Set as Production": "", "Set embedding model": "", @@ -1935,15 +2103,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "OpenWebUI شارك في مجتمع", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "عرض", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1987,6 +2157,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "المصدر", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "{{error}} خطأ في التعرف على الكلام", "Speech-to-Text": "", @@ -2027,6 +2198,7 @@ "STT Settings": "STT اعدادات", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2051,8 +2223,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "النظام", + "System events only": "", "System Instructions": "", "System Prompt": "محادثة النظام", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2073,6 +2247,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "محرك تحويل النص إلى كلام", @@ -2088,7 +2268,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2110,6 +2289,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2150,7 +2330,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "اليوم", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2164,6 +2344,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2212,14 +2394,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "تحديث ونسخ الرابط", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "تحديث كلمة المرور", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2246,13 +2433,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "مستخدم", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2262,6 +2454,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "المستخدمين", "Uses DefaultAzureCredential to authenticate": "", @@ -2275,6 +2468,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "المتغير", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "إصدار", @@ -2304,11 +2498,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "بحث الويب", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "محرك بحث الويب", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook الرابط", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI اعدادات", @@ -2351,6 +2548,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "أمس", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "انت", @@ -2380,6 +2578,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/ar/translation.json b/src/lib/i18n/locales/ar/translation.json index 3c2cd715eb..dcbabc2e38 100644 --- a/src/lib/i18n/locales/ar/translation.json +++ b/src/lib/i18n/locales/ar/translation.json @@ -20,6 +20,18 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_zero": "", + "{{count}} filters_one": "", + "{{count}} filters_two": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_zero": "", + "{{count}} groups_one": "", + "{{count}} groups_two": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} سطر/أسطر مخفية", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_zero": "", @@ -37,12 +49,20 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_zero": "", + "{{count}} users_one": "", + "{{count}} users_two": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -50,8 +70,10 @@ "{{user}}'s Chats": "محادثات المستخدم {{user}}", "{{webUIName}} Backend Required": "يتطلب الخلفية الخاصة بـ {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*معرّف/معرّفات عقدة الموجه مطلوبة لتوليد الصور", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -69,6 +91,7 @@ "Access Control": "التحكم في الوصول", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "متاح لجميع المستخدمين", "Account": "الحساب", @@ -84,6 +107,7 @@ "Activity": "", "Add": "إضافة", "Add a model ID": "إضافة معرّف نموذج", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "أضف وصفًا قصيرًا لما يفعله هذا النموذج", "Add a tag": "أضف وسم", "Add a tag...": "", @@ -96,8 +120,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "إضافة ملفات", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -112,6 +138,7 @@ "Add to favorites": "", "Add User": "إضافة مستخدم", "Add User Group": "إضافة مجموعة مستخدمين", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -124,7 +151,9 @@ "Admin": "المسؤول", "Admin Contact Email": "", "Admin Panel": "لوحة المسؤول", + "Admin Roles": "", "Admin Settings": "إعدادات المسؤول", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "للمسؤولين الوصول إلى جميع الأدوات في جميع الأوقات؛ بينما يحتاج المستخدمون إلى تعيين أدوات لكل نموذج في مساحة العمل.", "Advanced": "", "Advanced Parameters": "المعلمات المتقدمة", @@ -135,16 +164,21 @@ "All": "الكل", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "تم حذف جميع النماذج بنجاح", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "السماح بوسائل التحكم في المحادثة", "Allow Chat Delete": "السماح بحذف المحادثة", "Allow Chat Edit": "السماح بتعديل المحادثة", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -164,9 +198,11 @@ "Allow User Location": "السماح بتحديد موقع المستخدم", "Allow Voice Interruption in Call": "السماح بانقطاع الصوت أثناء المكالمة", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "النقاط النهائية المسموح بها", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "هل لديك حساب بالفعل؟", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "بديل للـ top_p، ويهدف إلى ضمان توازن بين الجودة والتنوع. تمثل المعلمة p الحد الأدنى لاحتمالية اعتبار الرمز مقارنة باحتمالية الرمز الأكثر احتمالاً. على سبيل المثال، مع p=0.05 والرمز الأكثر احتمالاً لديه احتمال 0.9، يتم ترشيح القيم الأقل من 0.045.", "Always": "دائمًا", @@ -185,6 +221,7 @@ "API Base URL": "الرابط الأساسي لواجهة API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "مفتاح واجهة برمجة التطبيقات (API)", + "API Key / Token": "", "API Key created.": "تم إنشاء مفتاح واجهة API.", "API Key Endpoint Restrictions": "قيود نقاط نهاية مفتاح API", "API keys": "مفاتيح واجهة برمجة التطبيقات (API)", @@ -214,13 +251,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "هل أنت متأكد من رغبتك في حذف هذه الرسالة؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "هل أنت متأكد من رغبتك في إلغاء أرشفة جميع المحادثات المؤرشفة؟", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "نماذج الساحة", "Artifacts": "القطع الأثرية", "Asc": "", "Ask": "اسأل", "Ask a question": "اطرح سؤالاً", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "المساعد", "Async Embedding Processing": "", "At time of event": "", @@ -235,14 +277,20 @@ "Audio": "الصوت", "August": "أغسطس", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "توثيق", "Authentication": "المصادقة", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "نسخ الرد تلقائيًا إلى الحافظة", - "Auto-playback response": "تشغيل الرد تلقائيًا", + "Auto-Create Groups": "", + "Auto-Playback Response": "تشغيل الرد تلقائيًا", "Autocomplete Generation": "توليد الإكمال التلقائي", "Autocomplete Generation Input Max Length": "الحد الأقصى لطول مدخل توليد الإكمال التلقائي", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111 (أوتوماتيك 1111)", "AUTOMATIC1111 Api Auth String": "سلسلة توثيق API لـ AUTOMATIC1111", "AUTOMATIC1111 Base URL": "الرابط الأساسي لـ AUTOMATIC1111", @@ -260,6 +308,7 @@ "Available Skills": "", "Available Tools": "", "available users": "المستخدمون المتاحون", + "Available variables": "", "available!": "متاح!", "Away": "بعيد", "Awful": "فظيع", @@ -270,16 +319,17 @@ "Bad Response": "رد سيئ", "Banners": "لافتات", "Base Model (From)": "النموذج الأساسي (من)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "قبل", "Being lazy": "كونك كسولاً", - "Beta": "بيتا", "Bing": "", "Bing Search V7 Endpoint": "نقطة نهاية Bing Search V7", "Bing Search V7 Subscription Key": "مفتاح اشتراك Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "مفتاح API لـ Bocha Search", "Bold": "", @@ -336,7 +386,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "اتجاه المحادثة", + "Chat Direction": "اتجاه المحادثة", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -408,6 +458,7 @@ "Collaboration channel where people join as members": "", "Collapse": "طي", "Collection": "المجموعة", + "Collection Field": "", "Collections": "", "Color": "اللون", "ComfyUI": "ComfyUI", @@ -417,12 +468,14 @@ "ComfyUI Workflow": "سير عمل ComfyUI", "ComfyUI Workflow Nodes": "عقد سير عمل ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "الأمر", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "الإكمالات", "Compress Images in Channels": "", @@ -448,6 +501,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "اتصل بنقاط نهاية API المتوافقة مع OpenAI الخاصة بك.", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -460,8 +514,16 @@ "Contact Admin for WebUI Access": "اتصل بالمسؤول للوصول إلى واجهة الويب", "Content": "المحتوى", "Content Extraction Engine": "محرك استخراج المحتوى", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "متابعة الرد", "Continue with {{provider}}": "متابعة مع {{provider}}", "Continue with Email": "متابعة باستخدام البريد الإلكتروني", @@ -509,6 +571,7 @@ "Create new secret key": "إنشاء مفتاح سري جديد", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "تم الإنشاء في", @@ -526,6 +589,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "منطقة الخطر", @@ -548,7 +612,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "الوضع الافتراضي يعمل مع مجموعة أوسع من النماذج من خلال استدعاء الأدوات مرة واحدة قبل التنفيذ. أما الوضع الأصلي فيستخدم قدرات استدعاء الأدوات المدمجة في النموذج، لكنه يتطلب دعمًا داخليًا لهذه الميزة.", "Default Model": "النموذج الافتراضي", "Default model updated": "الإفتراضي تحديث الموديل", "Default permissions": "الأذونات الافتراضية", @@ -558,6 +621,7 @@ "Default to ALL": "الافتراضي هو الكل", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "الإفتراضي صلاحيات المستخدم", + "Default webhook": "", "Defaults": "", "Delete": "حذف", "Delete {{name}}": "", @@ -618,6 +682,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "معطّل", "Disconnect OAuth": "", "Discover a function": "اكتشف وظيفة", @@ -632,10 +698,10 @@ "Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج", "Discussion channel where access is based on groups and permissions": "", "Display": "العرض", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "عرض الرموز التعبيرية أثناء المكالمة", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة", + "Display the Username Instead of You in the Chat": "اعرض اسم المستخدم بدلاً منك في الدردشة", "Displays citations in the response": "عرض المراجع في الرد", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "انغمس في المعرفة", @@ -646,6 +712,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "المستند", + "Document ID Field": "", "Document Intelligence": "تحليل المستندات الذكي", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -701,12 +768,14 @@ "Edit Default Permissions": "تعديل الأذونات الافتراضية", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "تعديل الذاكرة", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "تعديل المستخدم", "Edit User Group": "تعديل مجموعة المستخدمين", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -715,6 +784,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "البريد", + "Email Claim": "", "Embark on adventures": "انطلق في مغامرات", "Embedding": "تضمين", "Embedding Batch Size": "حجم دفعة التضمين", @@ -723,6 +793,7 @@ "Embedding Model Engine": "تضمين محرك النموذج", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -730,22 +801,27 @@ "Enable Code Execution": "تفعيل تنفيذ الكود", "Enable Code Interpreter": "تفعيل مفسر الكود", "Enable Community Sharing": "تمكين مشاركة المجتمع", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "تفعيل قفل الذاكرة (mlock) لمنع إخراج بيانات النموذج من الذاكرة. يساعد هذا الخيار في الحفاظ على الأداء من خلال منع حدوث أخطاء في الوصول وضمان سرعة الوصول إلى البيانات.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "تفعيل تعيين الذاكرة (mmap) لتحميل بيانات النموذج. يسمح هذا الخيار للنظام باستخدام التخزين كامتداد للذاكرة RAM عن طريق معاملة ملفات القرص كما لو كانت في RAM. قد يحسن أداء النموذج، لكن قد لا يعمل بشكل صحيح مع جميع الأنظمة وقد يستهلك مساحة كبيرة من القرص.", "Enable Message Queue": "", "Enable Message Rating": "تفعيل تقييم الرسائل", "Enable Mirostat sampling for controlling perplexity.": "تفعيل أخذ عينات Mirostat للتحكم في درجة التعقيد.", "Enable New Sign Ups": "تفعيل عمليات التسجيل الجديدة", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "مفعل", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "تأكد من أن ملف CSV الخاص بك يتضمن 4 أعمدة بهذا الترتيب: Name, Email, Password, Role.", "Enter {{role}} message here": "أدخل رسالة {{role}} هنا", - "Enter a detail about yourself for your LLMs to recall": "ادخل معلومات عنك تريد أن يتذكرها الموديل", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -762,6 +838,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "أدخل الChunk Overlap", "Enter Chunk Size": "أدخل Chunk الحجم", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "أدخل أزواج \"الرمز:قيمة التحيز\" مفصولة بفواصل (مثال: 5432:100، 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -799,8 +877,11 @@ "Enter Jupyter URL": "أدخل عنوان Jupyter", "Enter Kagi Search API Key": "أدخل مفتاح API لـ Kagi Search", "Enter Key Behavior": "أدخل سلوك المفتاح", + "Enter language": "", "Enter language codes": "أدخل كود اللغة", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -820,6 +901,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "أدخل عنوان البروكسي (مثال: https://user:password@host:port)", "Enter reasoning effort": "أدخل مستوى الجهد في الاستدلال", + "Enter Redirect URI": "", "Enter Score": "أدخل النتيجة", "Enter SearchApi API Key": "أدخل مفتاح API لـ SearchApi", "Enter SearchApi Engine": "أدخل محرك SearchApi", @@ -829,6 +911,7 @@ "Enter SerpApi API Key": "أدخل مفتاح API لـ SerpApi", "Enter SerpApi Engine": "أدخل محرك SerpApi", "Enter Serper API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "أدخل مفتاح API لـ Serply", "Enter Serpstack API Key": "أدخل مفتاح واجهة برمجة تطبيقات Serpstack", "Enter server host": "أدخل مضيف الخادم", @@ -849,6 +932,8 @@ "Enter Tika Server URL": "أدخل رابط خادم Tika", "Enter timeout in seconds": "أدخل المهلة بالثواني", "Enter to Send": "اضغط Enter للإرسال", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "أدخل Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "الرابط (e.g. http://127.0.0.1:7860/)", @@ -889,11 +974,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "التقييمات", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "مفتاح API لـ Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "مثال: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "مثال: ALL", "Example: mail": "مثال: mail", @@ -921,12 +1010,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "تصدير إلى CSV", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -944,6 +1039,7 @@ "Failed to create API Key.": "فشل في إنشاء مفتاح API.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -951,6 +1047,7 @@ "Failed to fetch models": "فشل في جلب النماذج", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -960,6 +1057,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "فشل في قراءة محتويات الحافظة", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -968,9 +1066,11 @@ "Failed to save models configuration": "فشل في حفظ إعدادات النماذج", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "فشل في تحديث الإعدادات", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "فشل في رفع الملف.", "Features": "الميزات", "Features Permissions": "أذونات الميزات", @@ -1003,6 +1103,8 @@ "File uploaded successfully": "تم رفع الملف بنجاح", "Filename": "", "Files": "الملفات", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "تم الآن تعطيل الفلتر على مستوى النظام", "Filter is now globally enabled": "تم الآن تفعيل الفلتر على مستوى النظام", @@ -1025,6 +1127,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1055,6 +1158,7 @@ "Function is now globally enabled": "تم الآن تفعيل الوظيفة على مستوى النظام", "Function Name": "اسم الوظيفة", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "تم تحديث الوظيفة بنجاح", "Functions": "الوظائف", "Functions allow arbitrary code execution.": "الوظائف تتيح تنفيذ كود برمجي مخصص.", @@ -1087,7 +1191,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "تم إنشاء المجموعة بنجاح", "Group deleted successfully": "تم حذف المجموعة بنجاح", "Group Description": "وصف المجموعة", @@ -1099,6 +1206,7 @@ "H2": "", "H3": "", "Haptic Feedback": "الاهتزاز اللمسي", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1129,6 +1237,8 @@ "ID": "المعرّف", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1154,6 +1264,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "تحديث مهم", @@ -1211,7 +1322,6 @@ "Keep in Sidebar": "", "Key": "المفتاح", "Key is required": "", - "Keyboard shortcuts": "اختصارات لوحة المفاتيح", "Keyboard Shortcuts": "", "Knowledge": "المعرفة", "Knowledge Access": "الوصول إلى المعرفة", @@ -1224,6 +1334,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "تم تحديث المعرفة بنجاح", "Kokoro.js (Browser)": "Kokoro.js (المتصفح)", "Kokoro.js Dtype": "نوع بيانات Kokoro.js", @@ -1240,7 +1352,6 @@ "Last ran": "", "Last reply": "آخر رد", "LDAP": "LDAP", - "LDAP server updated": "تم تحديث خادم LDAP", "Leaderboard": "لوحة المتصدرين", "Learn more": "", "Learn More": "", @@ -1262,6 +1373,7 @@ "Legacy": "", "lexical": "", "License": "الترخيص", + "Lifecycle JSON": "", "Lift List": "", "Light": "فاتح", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1285,6 +1397,7 @@ "Location access not allowed": "لا يُسمح بالوصول إلى الموقع", "Lost": "ضائع", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "من جهة اليسار إلى اليمين", "Made by Open WebUI Community": "OpenWebUI تم إنشاؤه بواسطة مجتمع ", "Make password visible in the user interface": "", @@ -1301,6 +1414,7 @@ "Manage Pipelines": "إدارة خطوط الأنابيب", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "مارس", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1328,6 +1442,7 @@ "Memory cleared successfully": "تم مسح الذاكرة بنجاح", "Memory deleted successfully": "تم حذف الذاكرة بنجاح", "Memory updated successfully": "تم تحديث الذاكرة بنجاح", + "Merge Accounts by Email": "", "Merge Responses": "دمج الردود", "Merged Response": "نتيجة الردود المدمجة", "Message": "", @@ -1338,9 +1453,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "لن تتم مشاركة الرسائل التي ترسلها بعد إنشاء الرابط الخاص بك. سيتمكن المستخدمون الذين لديهم عنوان URL من عرض الدردشة المشتركة", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1393,6 +1511,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "مفتاح API لـ Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "المزيد", @@ -1410,6 +1529,7 @@ "Name your knowledge base": "قم بتسمية قاعدة معرفتك", "Name, prompt, and model are required": "", "Native": "أصلي", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1439,6 +1559,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1451,8 +1572,10 @@ "No data": "", "No data found": "", "No distance available": "لا توجد مسافة متاحة", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "لم يتم تحديد ملف", "No files found": "", @@ -1480,6 +1603,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "لا توجد نتائج", "No results found": "لا توجد نتايج", "No search query generated": "لم يتم إنشاء استعلام بحث", @@ -1499,6 +1623,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "اي", + "Not configured": "", "Not factually correct": "ليس صحيحا من حيث الواقع", "Not helpful": "غير مفيد", "Not Registered": "", @@ -1514,20 +1639,25 @@ "Notifications": "إشعارات", "November": "نوفمبر", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "معرّف OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "اكتوبر", "Off": "أغلاق", "Okay, Let's Go!": "حسنا دعنا نذهب!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED داكن", "Ollama": "Ollama", "Ollama API": "أولاما API", "Ollama API settings updated": "تم تحديث إعدادات واجهة Ollama API", "Ollama Cloud API Key": "", "Ollama Version": "Ollama الاصدار", + "Omit": "", "On": "تشغيل", "Once": "", "OneDrive": "OneDrive", @@ -1598,6 +1728,7 @@ "Password": "الباسورد", "Passwords do not match.": "", "Paste Large Text as File": "الصق نصًا كبيرًا كملف", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ملف (.pdf)", @@ -1606,18 +1737,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "قيد الانتظار", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "تم رفض الإذن عند محاولة الوصول إلى أجهزة الوسائط", "Permission denied when accessing microphone": "تم رفض الإذن عند محاولة الوصول إلى الميكروفون", "Permission denied when accessing microphone: {{error}}": "{{error}} تم رفض الإذن عند الوصول إلى الميكروفون ", "Permissions": "الأذونات", + "Permissions reset to defaults": "", "Perplexity API Key": "مفتاح API لـ Perplexity", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "التخصيص", + "Picture Claim": "", "Pin": "تثبيت", "Pin to Sidebar": "", "Pinned": "مثبت", @@ -1650,13 +1784,13 @@ "Please fill in all fields.": "الرجاء تعبئة جميع الحقول.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "الرجاء اختيار نموذج أولاً.", "Please select a model.": "الرجاء اختيار نموذج.", "Please select a reason": "الرجاء اختيار سبب", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "المنفذ", "Ports": "", "Positive attitude": "موقف ايجابي", @@ -1686,6 +1820,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com \"{{searchValue}}\" أسحب من ", "Pull a model from Ollama.com": "Ollama.com سحب الموديل من ", @@ -1703,21 +1839,33 @@ "Read": "قراءة", "Read Aloud": "أقراء لي", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "جهد الاستدلال", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "سجل صوت", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI إعادة توجيهك إلى مجتمع ", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "يقلل من احتمال توليد إجابات غير منطقية. القيم الأعلى (مثل 100) تعطي إجابات أكثر تنوعًا، بينما القيم الأدنى (مثل 10) تكون أكثر تحفظًا.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "أشر إلى نفسك باسم \"المستخدم\" (مثل: \"المستخدم يتعلم الإسبانية\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_zero": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_two": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "رفض عندما لا ينبغي أن يكون", "Regenerate": "تجديد", "Regenerate Menu": "", @@ -1755,19 +1903,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "إعادة ترتيب النماذج", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "الرد داخل سلسلة الرسائل", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "إعادة تقييم النموذج", + "Research Knowledge": "", "Reset": "إعادة تعيين", "Reset All Models": "إعادة تعيين جميع النماذج", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "إعادة تعيين الصورة", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "إعادة تعيين مجلد التحميل", "Reset Vector Storage/Knowledge": "إعادة تعيين تخزين المتجهات/المعرفة", "Reset view": "إعادة تعيين العرض", @@ -1791,6 +1946,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "إدخال نص منسق للمحادثة", "Role": "منصب", + "Roles Claim": "", "RTL": "من اليمين إلى اليسار", "Run": "تنفيذ", "Run All": "", @@ -1809,10 +1965,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "لم يعد حفظ سجلات الدردشة مباشرة في مساحة تخزين متصفحك مدعومًا. يرجى تخصيص بعض الوقت لتنزيل وحذف سجلات الدردشة الخاصة بك عن طريق النقر على الزر أدناه. لا تقلق، يمكنك بسهولة إعادة استيراد سجلات الدردشة الخاصة بك إلى الواجهة الخلفية من خلاله", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "البحث", "Search a model": "البحث عن موديل", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1822,6 +1980,7 @@ "Search Chats": "البحث في الدردشات", "Search Collection": "البحث في المجموعة", "Search Files": "", + "Search filters": "", "Search Filters": "مرشحات البحث", "search for archived chats": "", "search for folders": "", @@ -1836,13 +1995,16 @@ "Search Models": "نماذج البحث", "Search Notes": "", "Search options": "خيارات البحث", + "Search or add pattern": "", "Search Prompts": "أبحث حث", "Search Result Count": "عدد نتائج البحث", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "البحث في الإنترنت", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "أدوات البحث", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "مفتاح API لـ SearchApi", "SearchApi Engine": "محرك SearchApi", @@ -1858,7 +2020,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "حدد نموذجا أساسيا", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "اختر محركًا", @@ -1896,18 +2057,25 @@ "semantic": "", "Send": "تم", "Send a Message": "يُرجى إدخال طلبك هنا", + "Send events for": "", "Send message": "يُرجى إدخال طلبك هنا.", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "يرسل `stream_options: { include_usage: true }` في الطلب.\nالمزودون المدعومون سيُرجعون معلومات استخدام الرموز في الاستجابة عند التفعيل.", "September": "سبتمبر", "SerpApi API Key": "مفتاح API لـ SerpApi", "SerpApi Engine": "محرك SerpApi", "Serper API Key": "مفتاح واجهة برمجة تطبيقات سيربر", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "مفتاح API لـ Serply", "Serpstack API Key": "مفتاح واجهة برمجة تطبيقات Serpstack", "Server connection failed": "", "Server connection verified": "تم التحقق من اتصال الخادم", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "الافتراضي", "Set as Production": "", "Set embedding model": "تعيين نموذج التضمين", @@ -1935,15 +2103,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "OpenWebUI شارك في مجتمع", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "عرض", - "Show \"What's New\" modal on login": "عرض نافذة \"ما الجديد\" عند تسجيل الدخول", + "Show \"What's New\" Modal on Login": "عرض نافذة \"ما الجديد\" عند تسجيل الدخول", "Show Admin Details in Account Pending Overlay": "عرض تفاصيل المشرف في نافذة \"الحساب قيد الانتظار\"", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1987,6 +2157,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "المصدر", + "Specific users or groups": "", "Speech Playback Speed": "سرعة تشغيل الصوت", "Speech recognition error: {{error}}": "{{error}} خطأ في التعرف على الكلام", "Speech-to-Text": "", @@ -2027,6 +2198,7 @@ "STT Settings": "STT اعدادات", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2051,8 +2223,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "النظام", + "System events only": "", "System Instructions": "تعليمات النظام", "System Prompt": "محادثة النظام", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "إنشاء الوسوم", @@ -2073,6 +2247,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "تقسيم النص", "Text-to-Speech": "", "Text-to-Speech Engine": "محرك تحويل النص إلى كلام", @@ -2088,7 +2268,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "السمة LDAP التي تتوافق مع البريد الإلكتروني الذي يستخدمه المستخدمون لتسجيل الدخول.", "The LDAP attribute that maps to the username that users use to sign in.": "السمة LDAP التي تتوافق مع اسم المستخدم الذي يستخدمه المستخدمون لتسجيل الدخول.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "لوحة المتصدرين حالياً في وضع تجريبي، وقد نقوم بتعديل حسابات التصنيف أثناء تحسين الخوارزمية.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "الحد الأقصى لحجم الملف بالميغابايت. إذا تجاوز الملف هذا الحد، فلن يتم رفعه.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "الحد الأقصى لعدد الملفات التي يمكن استخدامها في المحادثة دفعة واحدة. إذا تجاوز العدد هذا الحد، فلن يتم رفع الملفات.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2110,6 +2289,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "هذه ميزة تجريبية، وقد لا تعمل كما هو متوقع وقد تتغير في أي وقت.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "هذا الخيار يحدد عدد الرموز التي يتم الاحتفاظ بها عند تحديث السياق. مثلاً، إذا تم ضبطه على 2، سيتم الاحتفاظ بآخر رمزين من السياق. الحفاظ على السياق يساعد في استمرارية المحادثة، لكنه قد يحد من التفاعل مع مواضيع جديدة.", @@ -2150,7 +2330,7 @@ "To learn more about available endpoints, visit our documentation.": "لمعرفة المزيد حول نقاط النهاية المتاحة، قم بزيارة الوثائق الخاصة بنا.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "لاختيار الأدوات هنا، أضفها أولاً إلى مساحة العمل \"الأدوات\".", - "Toast notifications for new updates": "إشعارات منبثقة للتحديثات الجديدة", + "Toast Notifications for New Updates": "إشعارات منبثقة للتحديثات الجديدة", "Today": "اليوم", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2164,6 +2344,8 @@ "Toggle whether current connection is active.": "", "Token": "رمز", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "مفرط في التفاصيل", @@ -2212,14 +2394,19 @@ "Unpin": "إزالة التثبيت", "Unpin from Sidebar": "", "Unravel secrets": "فكّ الأسرار", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "بدون وسوم", "Untitled": "", "Update": "تحديث", "Update and Copy Link": "تحديث ونسخ الرابط", + "Update Email": "", "Update for the latest features and improvements.": "حدّث للحصول على أحدث الميزات والتحسينات.", + "Update Name": "", "Update password": "تحديث كلمة المرور", + "Update Picture": "", "Update your status": "", "Updated": "تم التحديث", "Updated at": "تم التحديث في", @@ -2246,13 +2433,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "استخدم الرمز '#' في خانة التوجيه لتحميل وإدراج المعرفة الخاصة بك.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "مستخدم", "User": "مستخدم", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "تم استرجاع موقع المستخدم بنجاح.", @@ -2262,6 +2454,7 @@ "User Status": "", "User Webhooks": "", "Username": "اسم المستخدم", + "Username Claim": "", "users": "", "Users": "المستخدمين", "Uses DefaultAzureCredential to authenticate": "", @@ -2275,6 +2468,7 @@ "Valves updated": "تم تحديث الصمامات", "Valves updated successfully": "تم تحديث الصمامات بنجاح", "variable": "المتغير", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "إصدار", @@ -2304,11 +2498,14 @@ "Web API": "واجهة برمجة التطبيقات (API)", "Web Loader Engine": "", "Web Search": "بحث الويب", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "محرك بحث الويب", "Web Search in Chat": "بحث ويب داخل المحادثة", "Web Search Query Generation": "توليد استعلام بحث الويب", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook الرابط", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI اعدادات", @@ -2351,6 +2548,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "أمس", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "انت", @@ -2380,6 +2578,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "سيتم توجيه كامل مساهمتك مباشرة إلى مطور المكون الإضافي؛ لا تأخذ Open WebUI أي نسبة. ومع ذلك، قد تفرض منصة التمويل المختارة رسومًا خاصة بها.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "لغة YouTube", diff --git a/src/lib/i18n/locales/az-AZ/translation.json b/src/lib/i18n/locales/az-AZ/translation.json index 346686703c..518049bbee 100644 --- a/src/lib/i18n/locales/az-AZ/translation.json +++ b/src/lib/i18n/locales/az-AZ/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} fayl", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} gizli sətir", "{{COUNT}} members": "{{COUNT}} üzv", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} Mənbə", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} söz", "{{COUNT}}d_time_ago": "{{COUNT}} gün əvvəl", "{{COUNT}}h_time_ago": "{{COUNT}} saat əvvəl", "{{COUNT}}m_time_ago": "{{COUNT}} dəq əvvəl", "{{COUNT}}w_time_ago": "{{COUNT}} həftə əvvəl", "{{COUNT}}y_time_ago": "{{COUNT}} il əvvəl", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}}, saat {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} yüklənməsi ləğv edildi", "{{modelName}} profile image": "{{modelName}} profil şəkli", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} adlı istifadəçinin söhbətləri", "{{webUIName}} Backend Required": "{{webUIName}} üçün Backend tələb olunur", "*Prompt node ID(s) are required for image generation": "*Şəkil yaradılması üçün sorğu (prompt) qovşaq ID-ləri tələb olunur", + "1 group": "", "1 hour before": "", "1 Source": "1 Mənbə", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "1 dəq əvvəl", @@ -57,6 +67,7 @@ "Access Control": "Girişə nəzarət", "Access Grants": "Giriş icazələri", "Access List": "Giriş siyahısı", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Bütün istifadəçilər üçün əlçatandır", "Account": "Hesab", @@ -72,6 +83,7 @@ "Activity": "Fəaliyyət", "Add": "Əlavə et", "Add a model ID": "Model ID-si əlavə edin", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Bu modelin nə etdiyi barədə qısa təsvir əlavə edin", "Add a tag": "Teq əlavə et", "Add a tag...": "Teq əlavə et...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Fərdi prompt əlavə et", "Add description": "", "Add Details": "Detallar əlavə et", + "Add durable context for future chats": "", "Add Files": "Fayl əlavə et", "Add Image": "Şəkil əlavə et", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "Üzv əlavə et", "Add Members": "Üzvlər əlavə et", @@ -100,6 +114,7 @@ "Add to favorites": "Favoritlərə əlavə et", "Add User": "İstifadəçi əlavə et", "Add User Group": "İstifadəçi qrupu əlavə et", + "Add webhook": "", "Add webpage": "Veb səhifə əlavə et", "Add your Open Terminal URL and API key in Settings → Integrations.": "Ayarlar → İnteqrasiyalar bölməsində Open Terminal URL və API açarınızı əlavə edin.", "Additional Config": "Əlavə konfiqurasiya", @@ -112,7 +127,9 @@ "Admin": "Admin", "Admin Contact Email": "Admin əlaqə e-poçtu", "Admin Panel": "Admin Paneli", + "Admin Roles": "", "Admin Settings": "Admin Ayarları", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Adminlərin hər zaman bütün alətlərə çıxışı var; istifadəçilər üçün isə alətlər iş sahəsindəki hər bir modelə uyğun təyin edilməlidir.", "Advanced": "Təkmil", "Advanced Parameters": "Təkmil parametrlər", @@ -123,16 +140,21 @@ "All": "Hamısı", "All chats have been unarchived.": "Bütün çatlar arxivdən çıxarıldı.", "All day": "", + "All events": "", "All models are now hidden": "Bütün modellər indi gizlidir", "All models are now visible": "Bütün modellər indi görünür", "All models deleted successfully": "Bütün modellər uğurla silindi", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Bütün zamanlar", "All Users": "Bütün istifadəçilər", + "All users and system events": "", "Allow Call": "Zəngə icazə ver", "Allow Chat Controls": "Çat idarəetməsinə icazə ver", "Allow Chat Delete": "Çatın silinməsinə icazə ver", "Allow Chat Edit": "Çatın redaktəsinə icazə ver", "Allow Chat Export": "Çatın ixracına icazə ver", + "Allow Chat Import": "", "Allow Chat Params": "Çat parametrlərinə icazə ver", "Allow Chat Share": "Çatın paylaşılmasına icazə ver", "Allow Chat System Prompt": "Çat sistem göstərişinə (prompt) icazə ver", @@ -152,9 +174,11 @@ "Allow User Location": "İstifadəçi məkanına icazə ver", "Allow Voice Interruption in Call": "Zəng zamanı səslə müdaxiləyə icazə ver", "Allow Web Upload": "Veb yükləməyə icazə ver", + "Allowed Domains": "", "Allowed Endpoints": "İcazə verilən son nöqtələr (Endpoints)", "Allowed File Extensions": "İcazə verilən fayl uzantıları", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Yükləmə üçün icazə verilən fayl uzantıları. Birdən çox uzantını vergüllə ayırın. Bütün fayl növləri üçün boş saxlayın.", + "Allowed Roles": "", "Already have an account?": "Artıq hesabınız var?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Top_p-yə alternativdir və keyfiyyətlə müxtəliflik arasında balans təmin etmək məqsədi daşıyır. p parametri ən yüksək ehtimallı tokenin ehtimalına nisbətən nəzərə alınacaq minimum ehtimalı təmsil edir. Məsələn, p=0.05 olduqda və ən ehtimallı token 0.9 ehtimala malikdirsə, 0.045-dən kiçik dəyəri olan logit-lər kənarlaşdırılır.", "Always": "Həmişə", @@ -173,6 +197,7 @@ "API Base URL": "API Baza URL-i", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker xidməti üçün API Baza URL-i. Standart olaraq: https://www.datalab.to/api/v1/marker", "API Key": "API Açarı", + "API Key / Token": "", "API Key created.": "API açarı yaradıldı.", "API Key Endpoint Restrictions": "API Açarı Son Nöqtə (Endpoint) Məhdudiyyətləri", "API keys": "API açarları", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Bu mesajı silmək istədiyinizə əminsiniz?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Bu versiyanı silmək istədiyinizə əminsiniz? Alt versiyalar bu versiyanın valideyninə yenidən bağlanacaq.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Bunu silmək istədiyinizə əminsiniz?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Bütün arxivləşdirilmiş çatları arxivdən çıxarmaq istədiyinizə əminsiniz?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena Modelləri", "Artifacts": "Artefaktlar", "Asc": "Artan sıra", "Ask": "Soruş", "Ask a question": "Sual verin", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Köməkçi", "Async Embedding Processing": "Asinxron Yerləşdirmə (Embedding) Emalı", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "Avqust", "Auth": "Səlahiyyətləndirmə (Auth)", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentifikasiya et", "Authentication": "Autentifikasiya", "Auto": "Avtomatik", "Auto (Random)": "Avto (Təsadüfi)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Cavabı mübadilə buferinə avtomatik kopyala", - "Auto-playback response": "Cavabı avtomatik səsləndir", + "Auto-Create Groups": "", + "Auto-Playback Response": "Cavabı avtomatik səsləndir", "Autocomplete Generation": "Avtomatik tamamlama yaradılması", "Autocomplete Generation Input Max Length": "Avtomatik tamamlama girişinin maksimum uzunluğu", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Səlahiyyət Sətri", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Baza URL-i", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Mövcud alətlər", "available users": "mövcud istifadəçilər", + "Available variables": "", "available!": "mövcuddur!", "Away": "Uzaqda", "Awful": "Bərbad", @@ -258,16 +295,17 @@ "Bad Response": "Pis cavab", "Banners": "Bannerlər", "Base Model (From)": "Əsas Model (Mənbə)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Əsas model siyahısı keşlənməsi, modelləri yalnız sistem açılışında və ya ayarları yadda saxladıqda gətirərək girişi sürətləndirir — daha sürətlidir, lakin ən son model dəyişikliklərini dərhal göstərməyə bilər.", "Bearer": "Bearer (Daşıyıcı)", "before": "əvvəl", "Being lazy": "Tənbəllik edir", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 Son Nöqtəsi", "Bing Search V7 Subscription Key": "Bing Search V7 Abunəlik Açarı", "Bio": "Bioqrafiya (Bio)", "Birth Date": "Doğum Tarixi", + "Blocked Groups": "", "BM25 Weight": "BM25 Çəkisi", "Bocha Search API Key": "Bocha Search API Açarı", "Bold": "Qalın", @@ -324,7 +362,7 @@ "Chat Completions": "Çat tamamlamaları", "Chat Conversation": "Çat söhbəti", "Chat deleted.": "", - "Chat direction": "Çat istiqaməti", + "Chat Direction": "Çat istiqaməti", "Chat exported successfully": "Çat uğurla ixrac edildi", "Chat History": "Çat tarixçəsi", "Chat ID": "Çat ID-si", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "İnsanların üzv olaraq qoşulduğu əməkdaşlıq kanalı", "Collapse": "Bük / Yığcamlaşdır", "Collection": "Kolleksiya", + "Collection Field": "", "Collections": "Kolleksiyalar", "Color": "Rəng", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI iş axını (Workflow)", "ComfyUI Workflow Nodes": "ComfyUI iş axını düyünləri (Nodes)", "Comma separated Node Ids (e.g. 1 or 1,2)": "Vergüllə ayrılmış düyün ID-ləri (məsələn: 1 və ya 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "əmr", "Command": "Əmr", "Comment": "Şərh", "Commit Message": "Təsdiqləmə mesajı (Commit Message)", "Community Reviews": "İcma rəyləri", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Tamamlamalar", "Compress Images in Channels": "Kanallarda şəkilləri sıx", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Open Terminal instansiyalarına qoşulun. Bütün istifadəçilər bu serverlər vasitəsilə fayllara baxmaq və terminal alətlərindən istifadə etmək imkanına malik olacaqlar.", "Connect to your own OpenAI compatible API endpoints.": "Öz OpenAI uyğun API son nöqtələrinizə qoşulun.", "Connect to your own OpenAPI compatible external tool servers.": "Öz OpenAPI uyğun xarici alət serverlərinizə qoşulun.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Bağlantı uğursuz oldu", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUI girişi üçün administratorla əlaqə saxlayın", "Content": "Məzmun", "Content Extraction Engine": "Məzmun çıxarma mühərriki", + "Content Field": "", "Content lengths (character counts only)": "Məzmun uzunluğu (yalnız simvol sayı)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Cavabı davam etdir", "Continue with {{provider}}": "{{provider}} ilə davam et", "Continue with Email": "E-poçt ilə davam et", @@ -493,6 +543,7 @@ "Create new secret key": "Yeni gizli açar yarat", "Create note": "Qeyd yarat", "Create Note": "Qeyd Yarat", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Aşağıdakı 'plus' düyməsinə klikləyərək ilk qeydinizi yaradın.", "Created at": "Yaradılma vaxtı", @@ -510,6 +561,7 @@ "Custom Gender": "Fərdi cins", "Custom Parameter Name": "Fərdi parametr adı", "Custom Parameter Value": "Fərdi parametr dəyəri", + "Custom range": "", "Daily": "", "Daily Messages": "Gündəlik mesajlar", "Danger Zone": "Təhlükəli zona", @@ -532,7 +584,6 @@ "Default Features": "Standart funksiyalar", "Default Filters": "Standart filtrlər", "Default Group": "Standart qrup", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Standart rejim, icradan əvvəl alətləri bir dəfə çağıraraq daha geniş model diapazonu ilə işləyir. Yerli (Native) rejim modelin daxili alət çağırma imkanlarından istifadə edir, lakin bu, modelin bu funksiyanı təbii şəkildə dəstəkləməsini tələb edir.", "Default Model": "Standart model", "Default model updated": "Standart model yeniləndi", "Default permissions": "Standart icazələr", @@ -542,6 +593,7 @@ "Default to ALL": "Standart olaraq HAMISI", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Fokuslanmış və müvafiq məzmun çıxarılması üçün standart olaraq seqmentləşdirilmiş axtarışdan istifadə edin; bu, əksər hallar üçün tövsiyə olunur.", "Default User Role": "Standart istifadəçi rolu", + "Default webhook": "", "Defaults": "Standartlar", "Delete": "Sil", "Delete {{name}}": "{{name}} sil", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Kod tərcüməçisini (Interpreter) söndür", "Disable Image Extraction": "Şəkil çıxarılmasını söndür", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF-dən şəkil çıxarılmasını söndürün. 'LLM istifadə et' aktivdirsə, şəkillərə avtomatik altyazı veriləcək. Standart olaraq 'Xeyr' (False) təyin edilib.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Söndürülüb", "Disconnect OAuth": "", "Discover a function": "Funksiya kəşf edin", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Model ilkin ayarlarını (presets) kəşf edin, yükləyin və araşdırın", "Discussion channel where access is based on groups and permissions": "Girişin qruplara və icazələrə əsaslandığı müzakirə kanalı", "Display": "Görüntü", - "Display chat title in tab": "Çat başlığını tab-da göstər", + "Display Chat Title in Tab": "Çat başlığını tab-da göstər", "Display Emoji in Call": "Zəng zamanı emojiləri göstər", "Display Multi-model Responses in Tabs": "Çox-modelli cavabları tab-larda göstər", - "Display the username instead of You in the Chat": "Çatda 'Siz' əvəzinə istifadəçi adını göstər", + "Display the Username Instead of You in the Chat": "Çatda 'Siz' əvəzinə istifadəçi adını göstər", "Displays citations in the response": "Cavabda sitatları göstərir", "Displays status updates (e.g., web search progress) in the response": "Cavabda status yeniləmələrini (məs. veb axtarış gedişatı) göstərir", "Dive into knowledge": "Biliklərə dalın", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling parametrləri", "Docling Server URL required.": "Docling Server URL-i tələb olunur.", "Document": "Sənəd", + "Document ID Field": "", "Document Intelligence": "Sənəd intellekti (Document Intelligence)", "Document Intelligence endpoint required.": "Sənəd intellekti son nöqtəsi tələb olunur.", "Document Intelligence Model": "Sənəd intellekti modeli", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Standart icazələri redaktə et", "Edit Folder": "Qovluğu redaktə et", "Edit Image": "Şəkli redaktə et", + "Edit Knowledge Connection": "", "Edit Last Message": "Son mesajı redaktə et", "Edit Memory": "Yaddaşı redaktə et", "Edit Prompt": "Göstərişi redaktə et", "Edit Terminal Connection": "Terminal bağlantısını redaktə et", "Edit User": "İstifadəçini redaktə et", "Edit User Group": "İstifadəçi qrupunu redaktə et", + "Edit webhook": "", "Edit workflow.json content": "workflow.json məzmununu redaktə et", "edited": "redaktə edildi", "Edited": "Redaktə edildi", @@ -699,6 +756,7 @@ "Eject model": "Modeli yaddaşdan çıxar", "ElevenLabs": "ElevenLabs", "Email": "E-poçt", + "Email Claim": "", "Embark on adventures": "Macəralara atılın", "Embedding": "Yerləşdirmə (Embedding)", "Embedding Batch Size": "Yerləşdirmə paket ölçüsü", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Yerləşdirmə modeli mühərriki", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "Boş mesaj", "Enable All": "Hamısını aktiv et", "Enable API Keys": "API açarlarını aktiv et", @@ -714,22 +773,27 @@ "Enable Code Execution": "Kodun icrasını aktiv et", "Enable Code Interpreter": "Kod tərcüməçisini (Interpreter) aktiv et", "Enable Community Sharing": "İcma ilə paylaşımı aktiv et", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Model məlumatlarının RAM-dan diskə köçürülməsinin (swap) qarşısını almaq üçün Yaddaş Kilidləməni (mlock) aktiv edin. Bu seçim modelin işçi vərəqlərini RAM-da kilidləyərək onların diskə köçürülməyəcəyinə zəmanət verir. Bu, səhifə xətalarının qarşısını almaqla və məlumatlara sürətli girişi təmin etməklə performansı qorumağa kömək edir.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Model məlumatlarını yükləmək üçün Yaddaş Xəritələməsini (mmap) aktiv edin. Bu seçim sistemin disk fayllarını RAM-daymış kimi rəftar edərək disk sahəsindən RAM-ın davamı kimi istifadə etməsinə imkan verir. Bu, məlumatlara daha sürətli giriş təmin edərək model performansını artıra bilər. Lakin, bütün sistemlərdə düzgün işləməyə bilər və əhəmiyyətli dərəcədə disk sahəsi istifadə edə bilər.", "Enable Message Queue": "Mesaj növbəsini aktiv et", "Enable Message Rating": "Mesaj qiymətləndirməni aktiv et", "Enable Mirostat sampling for controlling perplexity.": "Qeyri-müəyyənliyi (perplexity) idarə etmək üçün Mirostat seçməsini aktiv edin.", "Enable New Sign Ups": "Yeni qeydiyyatları aktiv et", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Model tərəfindən istifadə olunan mühakimə (reasoning) etiketlərini aktivləşdirin, söndürün və ya fərdiləşdirin. \"Aktivdir\" standart etiketlərdən istifadə edir, \"Söndürülüb\" mühakimə etiketlərini bağlayır, \"Fərdi\" isə öz başlanğıc və son etiketlərinizi təyin etməyə imkan verir.", "Enabled": "Aktivdir", "End Tag": "Son etiketi", + "Endpoint": "", "Endpoint URL": "Son nöqtə (Endpoint) URL-i", "Enforce Temporary Chat": "Müvəqqəti çatı məcburi et", "Enhance": "Təkmilləşdir", "Enrich Hybrid Search Text": "Hibrid axtarış mətnini zənginləşdir", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV faylınızda bu ardıcıllıqla 4 sütun olduğundan əmin olun: Ad, E-poçt, Şifrə, Rol.", "Enter {{role}} message here": "{{role}} mesajını bura daxil edin", - "Enter a detail about yourself for your LLMs to recall": "LLM-lərinizin xatırlaması üçün özünüz haqqında bir detal daxil edin", "Enter a title for the pending user info overlay. Leave empty for default.": "Gözləyən istifadəçi məlumatı qatı üçün başlıq daxil edin. Standart başlıq üçün boş saxlayın.", "Enter a watermark for the response. Leave empty for none.": "Cavab üçün su nişanı (watermark) daxil edin. Heç biri üçün boş saxlayın.", "Enter additional headers in JSON format": "Əlavə başlıqları (headers) JSON formatında daxil edin", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Hissə (chunk) hədəf minimum ölçüsünü daxil edin", "Enter Chunk Overlap": "Hissələrin kəsişmə (overlap) ölçüsünü daxil edin", "Enter Chunk Size": "Hissə ölçüsünü daxil edin", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Vergüllə ayrılmış \"token:bias_value\" cütlərini daxil edin (məsələn: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Gözləyən istifadəçi məlumatı qatı üçün məzmun daxil edin. Standart məzmun üçün boş saxlayın.", "Enter coordinates (e.g. 51.505, -0.09)": "Koordinatları daxil edin (məs. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter URL-ini daxil edin", "Enter Kagi Search API Key": "Kagi Search API açarını daxil edin", "Enter Key Behavior": "Açar davranışını (Key Behavior) daxil edin", + "Enter language": "", "Enter language codes": "Dil kodlarını daxil edin", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "MinerU API açarını daxil edin", "Enter Mistral API Base URL": "Mistral API baza URL-ini daxil edin", "Enter Mistral API Key": "Mistral API açarını daxil edin", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Proksi URL-ini daxil edin (məs. https://istifadəçi:şifrə@host:port)", "Enter reasoning effort": "Mühakimə səyini (reasoning effort) daxil edin", + "Enter Redirect URI": "", "Enter Score": "Bal daxil edin", "Enter SearchApi API Key": "SearchApi API açarını daxil edin", "Enter SearchApi Engine": "SearchApi mühərrikini daxil edin", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API açarını daxil edin", "Enter SerpApi Engine": "SerpApi mühərrikini daxil edin", "Enter Serper API Key": "Serper API açarını daxil edin", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API açarını daxil edin", "Enter Serpstack API Key": "Serpstack API açarını daxil edin", "Enter server host": "Server hostunu daxil edin", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Tika server URL-ini daxil edin", "Enter timeout in seconds": "Vaxt aşımını saniyə ilə daxil edin", "Enter to Send": "Göndərmək üçün Enter", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K dəyərini daxil edin", "Enter Top K Reranker": "Top K Reranker dəyərini daxil edin", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL daxil edin (məs. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Xəta: '{{modelId}}' ID-li model artıq mövcuddur. Davam etmək üçün fərqli bir ID seçin.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Xəta: Model ID-si boş ola bilməz. Davam etmək üçün etibarlı bir ID daxil edin.", "Evaluations": "Qiymətləndirmələr", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API Açarı", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Nümunə: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Nümunə: ALL (HAMISI)", "Example: mail": "Nümunə: mail", @@ -905,12 +982,18 @@ "Export Config": "Konfiqurasiyanı İxrac Et", "Export Models": "Modelləri İxrac Et", "Export Prompts": "Göstərişləri İxrac Et", + "Export Skills": "", "Export to CSV": "CSV-yə ixrac et", "Export Tools": "Alətləri İxrac Et", "Export Users": "İstifadəçiləri İxrac Et", "External": "Xarici", + "External connection not found.": "", "External Document Loader URL required.": "Xarici sənəd yükləyici URL-i tələb olunur.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Xarici tapşırıq modeli", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Xarici veb yükləyici API açarı", "External Web Loader URL": "Xarici veb yükləyici URL-i", "External Web Search API Key": "Xarici veb axtarış API açarı", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API açarı yaradılmadı.", "Failed to delete calendar": "", "Failed to delete note": "Qeyd silinmədi", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "Şəkil yüklənmədi", "Failed to extract content from the file: {{error}}": "Fayldan məzmun çıxarıla bilmədi: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Modelləri gətirmək mümkün olmadı", "Failed to generate title": "Başlıq yaradılmadı", "Failed to import models": "Modellər idxal edilmədi", + "Failed to load chat": "", "Failed to load chat preview": "Çatın önizləməsi yüklənmədi", "Failed to load DOCX file. Please try downloading it instead.": "DOCX faylı yüklənmədi. Zəhmət olmasa, onu yükləməyə çalışın.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV faylı yüklənmədi. Zəhmət olmasa, onu yükləməyə çalışın.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Çatı köçürmək mümkün olmadı", "Failed to process URL: {{url}}": "URL emal edilmədi: {{url}}", "Failed to read clipboard contents": "Mübadilə buferi oxuna bilmədi", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Üzv çıxarıla bilmədi", "Failed to render diagram": "Diaqram yaradılmadı", "Failed to render visualization": "Vizuallaşdırma yaradılmadı", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Modellərin konfiqurasiyası yadda saxlanılmadı", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "Terminal serverlərini yadda saxlamaq mümkün olmadı", + "Failed to save webhook": "", "Failed to unshare chat.": "Çatın paylaşımı dayandırıla bilmədi.", "Failed to update settings": "Ayarlar yenilənmədi", "Failed to update status": "Status yenilənmədi", + "Failed to update webhook": "", "Failed to upload file.": "Fayl yüklənmədi.", "Features": "Özəlliklər", "Features Permissions": "Özəllik icazələri", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Fayl uğurla yükləndi", "Filename": "Fayl adı", "Files": "Fayllar", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Süzgəc (Filter)", "Filter is now globally disabled": "Süzgəc hazırda qlobal olaraq söndürülüb", "Filter is now globally enabled": "Süzgəc hazırda qlobal olaraq aktivdir", @@ -1009,6 +1099,7 @@ "Folder options": "Qovluq seçimləri", "Folder updated successfully": "Qovluq uğurla yeniləndi", "Folders": "Qovluqlar", + "Folders Sharing": "", "Follow up": "Davam sualı", "Follow Up Generation": "Davam suallarının yaradılması", "Follow Up Generation Prompt": "Davam sualı yaratma göstərişi", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funksiya hazırda qlobal olaraq aktivdir", "Function Name": "Funksiya adı", "Function Name Filter List": "Funksiya adı süzgəc siyahısı", + "Function starter": "", "Function updated successfully": "Funksiya uğurla yeniləndi", "Functions": "Funksiyalar", "Functions allow arbitrary code execution.": "Funksiyalar ixtiyari kodun icrasına icazə verir.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Tor (Grid)", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Qrup kanalı", + "Group Claim": "", "Group created successfully": "Qrup uğurla yaradıldı", "Group deleted successfully": "Qrup uğurla silindi", "Group Description": "Qrup təsviri", @@ -1083,6 +1178,7 @@ "H2": "Başlıq 2", "H3": "Başlıq 3", "Haptic Feedback": "Haptik rəy (Titrəyiş)", + "Header variables": "", "Headers": "Başlıqlar (Headers)", "Headers must be a valid JSON object": "Başlıqlar etibarlı bir JSON obyekti olmalıdır", "Height": "Hündürlük", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID-də \":\" və ya \"|\" simvolları ola bilməz", "ID copied to clipboard": "ID mübadilə buferinə kopyalandı", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox: Formalara icazə ver", "iframe Sandbox Allow Same Origin": "iframe Sandbox: Eyni mənbəyə (Same Origin) icazə ver", @@ -1138,6 +1236,7 @@ "Import From Link": "Linkdən idxal et", "Import Models": "Modelləri idxal et", "Import Prompts": "Göstərişləri idxal et", + "Import Skills": "", "Import successful": "İdxal uğurludur", "Import Tools": "Alətləri idxal et", "Important Update": "Vacib yeniləmə", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Yan paneldə saxla", "Key": "Açar", "Key is required": "Açar tələb olunur", - "Keyboard shortcuts": "Klaviatura qısayolları", "Keyboard Shortcuts": "Klaviatura Qısayolları", "Knowledge": "Bilik", "Knowledge Access": "Bilik bazasına giriş", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Bilik adı", "Knowledge Public Sharing": "Biliyin ictimai paylaşımı", "Knowledge Sharing": "Biliyin paylaşılması", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Bilik uğurla yeniləndi", "Kokoro.js (Browser)": "Kokoro.js (Brauzer)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Son cavab", "LDAP": "LDAP", - "LDAP server updated": "LDAP serveri yeniləndi", "Leaderboard": "Liderlər cədvəli", "Learn more": "Daha çox öyrən", "Learn More": "Daha Çox Öyrən", @@ -1246,6 +1345,7 @@ "Legacy": "Köhnə versiya (Legacy)", "lexical": "leksik", "License": "Lisenziya", + "Lifecycle JSON": "", "Lift List": "Qaldırma siyahısı (Lift List)", "Light": "Açıq (Light)", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Eyni vaxtda aparılan axtarış sorğularını məhdudlaşdırın. 0 = limitsiz (standart). Ardıcıl icra üçün 1 təyin edin.", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Məkan girişinə icazə verilmir", "Lost": "İtirildi", "Low": "Aşağı", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "Soldan sağa (LTR)", "Made by Open WebUI Community": "Open WebUI İcması tərəfindən hazırlanıb", "Make password visible in the user interface": "Şifrəni interfeysdə görünən et", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Pipeline-ları idarə et", "Manage Tool Servers": "Alət serverlərini idarə et", "Manage your account information.": "Hesab məlumatlarınızı idarə edin.", + "Mapped Source": "", "March": "Mart", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown başlıq mətni bölücüsü", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Yaddaş uğurla təmizləndi", "Memory deleted successfully": "Yaddaş uğurla silindi", "Memory updated successfully": "Yaddaş uğurla yeniləndi", + "Merge Accounts by Email": "", "Merge Responses": "Cavabları birləşdir", "Merged Response": "Birləşdirilmiş cavab", "Message": "Mesaj", @@ -1322,9 +1425,12 @@ "messages": "mesajlar", "Messages": "Mesajlar", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Linki yaratdıqdan sonra göndərdiyiniz mesajlar paylaşılmayacaq. URL-ə sahib olan istifadəçilər paylaşılan çata baxa biləcəklər.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (şəxsi)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (iş/məktəb)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Bulud API rejimi üçün MinerU API açarı tələb olunur.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Modellərin paylaşılması", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Axtarış API Açarı", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Daha çox", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Bilik bazanızı adlandırın", "Name, prompt, and model are required": "", "Native": "Yerli (Native)", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "Yeni", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "Giriş icazəsi yoxdur. Sizin üçün özəldir.", "No activity data": "Fəaliyyət məlumatı yoxdur", + "No additional headers are sent unless configured.": "", "No authentication": "Autentifikasiya yoxdur", "No automations found": "", "No chats found": "Heç bir çat tapılmadı", @@ -1435,8 +1544,10 @@ "No data": "Məlumat yoxdur", "No data found": "Məlumat tapılmadı", "No distance available": "Məsafə məlumatı yoxdur", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "Müddətin bitməməsi təhlükəsizlik riski yarada bilər.", + "No external knowledge sources configured.": "", "No feedback found": "Rəy tapılmadı", "No file selected": "Fayl seçilməyib", "No files found": "Fayl tapılmadı", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "Bərkidilmiş mesaj yoxdur", "No prompts found": "Göstəriş tapılmadı", + "No Repeat": "", "No results": "Nəticə yoxdur", "No results found": "Nəticə tapılmadı", "No search query generated": "Axtarış sorğusu yaradılmadı", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Hələ ki webhook yoxdur", "Node Ids": "Düyün (Node) ID-ləri", "None": "Heç biri", + "Not configured": "", "Not factually correct": "Faktiki olaraq doğru deyil", "Not helpful": "Faydalı deyil", "Not Registered": "Qeydiyyatdan keçməyib", @@ -1498,20 +1611,25 @@ "Notifications": "Bildirişlər", "November": "Noyabr", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktyabr", "Off": "Bağlı", "Okay, Let's Go!": "Yaxşı, başlayaq!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Qara", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API ayarları yeniləndi", "Ollama Cloud API Key": "Ollama Cloud API Açarı", "Ollama Version": "Ollama Versiyası", + "Omit": "", "On": "Açıq", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Şifrə", "Passwords do not match.": "Şifrələr uyğun gəlmir.", "Paste Large Text as File": "Böyük mətni fayl kimi yapışdır", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF sənədi (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "gözləmədə", "Pending": "Gözləmədə", + "Pending Accounts": "", "Pending User Overlay Content": "Gözləyən istifadəçi örtük məzmunu", "Pending User Overlay Title": "Gözləyən istifadəçi örtük başlığı", "Permission denied when accessing media devices": "Media cihazlarına giriş zamanı icazə rədd edildi", "Permission denied when accessing microphone": "Mikrofona giriş zamanı icazə rədd edildi", "Permission denied when accessing microphone: {{error}}": "Mikrofona giriş zamanı icazə rədd edildi: {{error}}", "Permissions": "İcazələr", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API Açarı", "Perplexity Model": "Perplexity Modeli", "Perplexity Search API URL": "Perplexity Axtarış API URL-i", "Perplexity Search Context Usage": "Perplexity Axtarış Kontekst İstifadəsi", "Persistent": "", "Personalization": "Fərdiləşdirmə", + "Picture Claim": "", "Pin": "Bərkit", "Pin to Sidebar": "", "Pinned": "Bərkidilib", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Zəhmət olmasa bütün sahələri doldurun.", "Please register the OAuth client": "Zəhmət olmasa OAuth klientini qeydiyyatdan keçirin", "Please save the connection to persist the OAuth client information and do not change the ID": "Zəhmət olmasa OAuth klient məlumatlarını qalıcı etmək üçün bağlantını yadda saxlayın və ID-ni dəyişməyin", - "Please select a model first.": "Zəhmət olmasa əvvəlcə model seçin.", "Please select a model.": "Zəhmət olmasa bir model seçin.", "Please select a reason": "Zəhmət olmasa bir səbəb seçin", "Please select a valid JSON file": "Zəhmət olmasa etibarlı bir JSON faylı seçin", "Please select at least one user for Direct Message channel.": "Zəhmət olmasa birbaşa mesaj kanalı üçün ən azı bir istifadəçi seçin.", "Please wait until all files are uploaded.": "Zəhmət olmasa bütün fayllar yüklənənə qədər gözləyin.", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "Portlar", "Positive attitude": "Müsbət yanaşma", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Göstərişlərin ictimai paylaşımı", "Prompts Sharing": "Göstərişlərin paylaşılması", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "İctimai", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com-dan \"{{searchValue}}\" modelini çək", "Pull a model from Ollama.com": "Ollama.com-dan bir model çək", @@ -1687,21 +1811,29 @@ "Read": "Oxu", "Read Aloud": "Səsli oxu", "Read more →": "Daha çox oxu →", + "Read only": "", "Read Only": "Yalnız oxunabilən", "Read-Only Access": "Yalnız oxuma icazəsi", "Reason": "Səbəb", "Reasoning Effort": "Mühakimə səyi", "Reasoning Tags": "Mühakimə etiketləri", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Yaz (səs)", "Record voice": "Səsi yaz", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Open WebUI İcmasına yönləndirilirsiniz", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Mənasız mətnlərin yaradılma ehtimalını azaldır. Daha yüksək dəyər (məs. 100) daha müxtəlif cavablar verəcək, daha aşağı dəyər (məs. 10) isə daha mühafizəkar olacaq.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Özünüzü \"İstifadəçi\" kimi təqdim edin (məs. \"İstifadəçi İspan dilini öyrənir\")", "Reference Chats": "İstinad çatları", "Refresh": "Yenilə", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "İmtina edilməməli olduğu halda imtina etdi", "Regenerate": "Yenidən yarat", "Regenerate Menu": "Yenidən yaratma menyusu", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "Önizləmələrdə Markdown-u emal et", "Render Markdown in User Messages": "", "Reorder Models": "Modelləri yenidən sırala", + "Repeat": "", "Repeats": "", "Reply": "Cavabla", "Reply in Thread": "Mövzu daxilində cavabla", "Reply to thread...": "Mövzuya cavab yaz...", "Replying to {{NAME}}": "{{NAME}} adlı istifadəçiyə cavab verilir", + "Require users to confirm before using Web Search.": "", "required": "tələb olunur", "Reranking Batch Size": "", "Reranking Engine": "Yenidən sıralama mühərriki", "Reranking Model": "Yenidən sıralama modeli", + "Research Knowledge": "", "Reset": "Sıfırla", "Reset All Models": "Bütün modelləri sıfırla", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Şəkli sıfırla", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Yükləmə kataloqunu sıfırla", "Reset Vector Storage/Knowledge": "Vektor yaddaşını/Biliyi sıfırla", "Reset view": "Görünüşü sıfırla", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 mənbə gətirildi", "Rich Text Input for Chat": "Çat üçün zəngin mətn girişi", "Role": "Rol", + "Roles Claim": "", "RTL": "Sağdan sola (RTL)", "Run": "İcra et", "Run All": "Hamısını icra et", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Çat tarixçəsinin birbaşa brauzer yaddaşına saxlanılması artıq dəstəklənmir. Zəhmət olmasa, aşağıdakı düyməyə klikləyərək çat jurnalını yükləyin və silin. Narahat olmayın, çat jurnalınızı arxa plana (backend) asanlıqla yenidən idxal edə bilərsiniz:", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Şaxə dəyişdikdə sürüşdür", "Scroll to Top": "", "Search": "Axtar", "Search a model": "Model axtar", + "Search actions": "", "Search all emojis": "Bütün emojilərdə axtar", "Search and manage user memories": "İstifadəçi yaddaşını axtarın və idarə edin", "Search and view user chat history": "İstifadəçi çat tarixçəsini axtarın və baxın", @@ -1798,6 +1940,7 @@ "Search Chats": "Çatları axtar", "Search Collection": "Kolleksiyada axtar", "Search Files": "Faylları axtar", + "Search filters": "", "Search Filters": "Filtrləri axtar", "search for archived chats": "arxivləşdirilmiş çatları axtar", "search for folders": "qovluqları axtar", @@ -1812,13 +1955,16 @@ "Search Models": "Modelləri axtar", "Search Notes": "Qeydləri axtar", "Search options": "Axtarış seçimləri", + "Search or add pattern": "", "Search Prompts": "Axtarış göstərişləri", "Search Result Count": "Axtarış nəticələrinin sayı", + "Search skills": "", "Search Skills": "Axtarış bacarıqları", - "Search skills...": "", "Search the internet": "İnternetdə axtar", "Search the web and fetch URLs": "Vebdə axtar və URL-ləri gətir", + "Search tools": "", "Search Tools": "Axtarış alətləri", + "Search users or groups": "", "Search, view, and manage user notes": "İstifadəçi qeydlərini axtarın, baxın və idarə edin", "SearchApi API Key": "SearchApi API Açarı", "SearchApi Engine": "SearchApi Mühərriki", @@ -1834,7 +1980,6 @@ "Seed": "Seed (toxum)", "Select": "Seç", "Select {{modelName}} model": "{{modelName}} modelini seç", - "Select a base model": "Əsas model seçin", "Select a base model (e.g. llama3, gpt-4o)": "Əsas model seçin (məs. llama3, gpt-4o)", "Select a conversation to preview": "Önizləmə üçün bir söhbət seçin", "Select a engine": "Mühərrik seçin", @@ -1872,18 +2017,25 @@ "semantic": "semantik", "Send": "Göndər", "Send a Message": "Mesaj Göndər", + "Send events for": "", "Send message": "Mesaj göndər", "Send now": "İndi göndər", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Sorğuda `stream_options: { include_usage: true }` göndərir. Aktiv edildikdə, dəstəklənən təminatçılar cavabda token istifadə məlumatlarını qaytaracaq.", "September": "Sentyabr", "SerpApi API Key": "SerpApi API Açarı", "SerpApi Engine": "SerpApi Mühərriki", "Serper API Key": "Serper API Açarı", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API Açarı", "Serpstack API Key": "Serpstack API Açarı", "Server connection failed": "", "Server connection verified": "Server bağlantısı təsdiqləndi", + "Service Account": "", "Session": "Sessiya", + "Session expired. Please sign in again.": "", "Set as default": "Standart olaraq təyin et", "Set as Production": "İstehsal (Production) kimi təyin et", "Set embedding model": "Yerləşdirmə modelini təyin et", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Paylaşım linki mübadilə buferinə kopyalandı.", "Share to Open WebUI Community": "Open WebUI İcması ilə paylaş", "Share your background and interests": "Keçmişiniz və maraqlarınız haqqında məlumat paylaşın", + "Shared": "", "Shared Chats": "Paylaşılan Çatlar", "Shared with you": "Sizinlə paylaşılanlar", "Sharing Permissions": "Paylaşım İcazələri", "Show": "Göstər", - "Show \"What's New\" modal on login": "Giriş zamanı \"Yeniliklər\" pəncərəsini göstər", + "Show \"What's New\" Modal on Login": "Giriş zamanı \"Yeniliklər\" pəncərəsini göstər", "Show Admin Details in Account Pending Overlay": "Hesab gözləmə qatında admin məlumatlarını göstər", "Show All": "Hamısını Göstər", "Show all ({{COUNT}} characters)": "Hamısını göstər ({{COUNT}} simvol)", "Show Files": "Faylları Göstər", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Formatlama alətlər panelini göstər", "Show image preview": "Şəkil önizləməsini göstər", "Show Model": "Modeli Göstər", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Mənbə", + "Specific users or groups": "", "Speech Playback Speed": "Səsləndirmə sürəti", "Speech recognition error: {{error}}": "Səsin tanınması xətası: {{error}}", "Speech-to-Text": "Səsdən Mətnə (STT)", @@ -1999,6 +2154,7 @@ "STT Settings": "STT Ayarları", "Stylized PDF Export": "Stil verilmiş PDF ixracı", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "Sualı göndər", "Submit suggestion": "Təklifi göndər", "Subtitle": "Altyazı", @@ -2023,8 +2179,10 @@ "Syncing...": "Sinxronizasiya olunur...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Yalnız son sinxronizasiyadan sonra yenilənən çatları sinxronizasiya edir. Bütün çatları yenidən sinxronizasiya etmək üçün bunu söndürün.", "System": "Sistem", + "System events only": "", "System Instructions": "Sistem təlimatları", "System Prompt": "Sistem göstərişi (Prompt)", + "Table": "", "Tag": "Etiket", "Tags": "Etiketlər", "Tags Generation": "Etiketlərin yaradılması", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Standart olaraq müvəqqəti çat", "Terminal": "Terminal", "Terminal servers saved": "Terminal serverləri yadda saxlanıldı", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Mətn bölücü", "Text-to-Speech": "Mətndən səsə (TTS)", "Text-to-Speech Engine": "Mətndən səsə mühərriki", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Daxil edilən audionun dili. Giriş dilini ISO-639-1 (məs. az) formatında təqdim etmək dəqiqliyi artıracaq və gecikməni azaldacaq. Dilin avtomatik təyin edilməsi üçün boş saxlayın.", "The LDAP attribute that maps to the mail that users use to sign in.": "İstifadəçilərin daxil olmaq üçün istifadə etdiyi e-poçta uyğun gələn LDAP atributu.", "The LDAP attribute that maps to the username that users use to sign in.": "İstifadəçilərin daxil olmaq üçün istifadə etdiyi istifadəçi adına uyğun gələn LDAP atributu.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Liderlər cədvəli hazırda beta mərhələsindədir və alqoritmi təkmilləşdirdikcə reytinq hesablamalarına düzəlişlər edə bilərik.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "MB ilə maksimum fayl ölçüsü. Fayl bu limiti keçərsə, yüklənilməyəcək.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Çatda eyni anda istifadə edilə bilən maksimum fayl sayı. Fayl sayı bu limiti keçərsə, yüklənilməyəcək.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Mətn üçün çıxış formatı. 'json', 'markdown' və ya 'html' ola bilər. Standart olaraq 'markdown' seçilib.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Bu qovluq boşdur", "This is a default user permission and will remain enabled.": "Bu, standart istifadəçi icazəsidir və aktiv qalacaq.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Bu, eksperimental funksiyadır, gözlənildiyi kimi işləməyə bilər və istənilən vaxt dəyişdirilə bilər.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Bu model ictimaiyyət üçün açıq deyil. Lütfən, başqa model seçin.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Bu seçim sorğudan sonra modelin yaddaşda nə qədər qalacağına nəzarət edir (standart: 5dəq)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Bu seçim kontekst yenilənərkən neçə tokenin qorunacağına nəzarət edir. Məsələn, 2 təyin edilərsə, söhbət kontekstinin son 2 tokeni saxlanılacaq. Konteksti qorumaq söhbətin davamlılığını saxlamağa kömək edir, lakin yeni mövzulara cavab vermə qabiliyyətini azalda bilər.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Mövcud son nöqtələr (endpoints) haqqında daha çox öyrənmək üçün sənədlərimizə baxın.", "To select skills here, add them to the \"Skills\" workspace first.": "Bura bacarıqlar seçmək üçün əvvəlcə onları \"Bacarıqlar\" (Skills) iş sahəsinə əlavə edin.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Bura alət dəstləri seçmək üçün əvvəlcə onları \"Alətlər\" (Tools) iş sahəsinə əlavə edin.", - "Toast notifications for new updates": "Yeni yeniləmələr üçün bildirişlər", + "Toast Notifications for New Updates": "Yeni yeniləmələr üçün bildirişlər", "Today": "Bu gün", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Bu gün saat {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Hazırkı bağlantının aktiv olub-olmadığını dəyişdirin.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Token sayları təxminidir və faktiki API istifadəsini əks etdirməyə bilər", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokenlər", "Tokens": "Tokenlər", "Too verbose": "Çox təfərrüatlı", @@ -2184,14 +2350,19 @@ "Unpin": "Sabitlənmişdən çıxar", "Unpin from Sidebar": "", "Unravel secrets": "Gizlinləri üzə çıxarın", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Çatı paylaşımı dayandır", "Unsupported file type.": "Dəstəklənməyən fayl növü.", "Untagged": "Etiketsiz", "Untitled": "Adsız", "Update": "Yenilə", "Update and Copy Link": "Yenilə və linki kopyala", + "Update Email": "", "Update for the latest features and improvements.": "Ən son funksiyalar və təkmilləşdirmələr üçün yeniləyin.", + "Update Name": "", "Update password": "Şifrəni yenilə", + "Update Picture": "", "Update your status": "Statusunuzu yeniləyin", "Updated": "Yeniləndi", "Updated at": "Yenilənmə vaxtı", @@ -2218,13 +2389,18 @@ "Use": "İstifadə et", "Use '#' in the prompt input to load and include your knowledge.": "Biliyinizi yükləmək və daxil etmək üçün göstəriş hissəsində '#' işarəsindən istifadə edin.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Potensial olaraq daha yaxşı dəqiqlik üçün /v1/audio/transcriptions əvəzinə /v1/chat/completions son nöqtəsindən istifadə edin.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Chat Completions API-dan istifadə edin", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "İstifadəçilərinizi təşkil etmək və icazələr təyin etmək üçün qruplardan istifadə edin.", "Use LLM": "LLM istifadə et", "Use no proxy to fetch page contents.": "Səhifə məzmununu gətirmək üçün proksi istifadə etməyin.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Səhifə məzmununu gətirmək üçün http_proxy və https_proxy mühit dəyişənləri tərəfindən təyin edilmiş proksidən istifadə edin.", + "Use Web Search?": "", "user": "istifadəçi", "User": "İstifadəçi", + "User Access": "", "User Activity": "İstifadəçi fəallığı", "User Groups": "İstifadəçi qrupları", "User location successfully retrieved.": "İstifadəçi yeri uğurla müəyyən edildi.", @@ -2234,6 +2410,7 @@ "User Status": "İstifadəçi statusu", "User Webhooks": "İstifadəçi Webhook-ları", "Username": "İstifadəçi adı", + "Username Claim": "", "users": "istifadəçilər", "Users": "İstifadəçilər", "Uses DefaultAzureCredential to authenticate": "Autentifikasiya üçün DefaultAzureCredential istifadə edir", @@ -2247,6 +2424,7 @@ "Valves updated": "Valves yeniləndi", "Valves updated successfully": "Valves uğurla yeniləndi", "variable": "dəyişən", + "Vector Field": "", "Verify Connection": "Bağlantını yoxla", "Verify SSL Certificate": "SSL Sertifikatını yoxla", "Version": "Versiya", @@ -2276,11 +2454,14 @@ "Web API": "Veb API", "Web Loader Engine": "Veb yükləyici mühərrik", "Web Search": "Veb axtarış", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Veb axtarış mühərriki", "Web Search in Chat": "Söhbətdə veb axtarış", "Web Search Query Generation": "Veb axtarış sorğusunun yaradılması", + "Webhook deleted": "", "Webhook Name": "Webhook adı", - "Webhook URL": "Webhook URL-i", + "Webhook saved": "", "Webhooks": "Webhook-lar", "Webpage URLs": "Veb səhifə URL-ləri", "WebUI Settings": "WebUI ayarları", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex Veb Axtarış API açarı", "Yandex Web Search config": "Yandex Veb Axtarış konfiqurasiyası", "Yandex Web Search URL": "Yandex Veb Axtarış URL-i", + "Yearly": "", "Yesterday": "Dünən", "Yesterday at {{LOCALIZED_TIME}}": "Dünən saat {{LOCALIZED_TIME}}", "You": "Siz", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Brauzeriniz video etiketini dəstəkləmir.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "İanənizin tamamı birbaşa plagin tərtibatçısına gedəcək; Open WebUI heç bir faiz tutmur. Lakin seçilmiş maliyyələşdirmə platformasının öz komissiyaları ola bilər.", "Your message text or inputs": "Mesaj mətniniz və ya girişləriniz", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "İstifadə statistikanız uğurla sinxronizasiya edildi.", "YouTube": "YouTube", "Youtube Language": "YouTube dili", diff --git a/src/lib/i18n/locales/bg-BG/translation.json b/src/lib/i18n/locales/bg-BG/translation.json index 5759c6d8b3..0312e685f6 100644 --- a/src/lib/i18n/locales/bg-BG/translation.json +++ b/src/lib/i18n/locales/bg-BG/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}'s чатове", "{{webUIName}} Backend Required": "{{webUIName}} Изисква се Бекенд", "*Prompt node ID(s) are required for image generation": "*Идентификатор(ите) на възел-а се изисква(т) за генериране на изображения", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Контрол на достъпа", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Достъпно за всички потребители", "Account": "Акаунт", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Добавяне", "Add a model ID": "Добавете ID на модела", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Добавете кратко описание за това какво прави този модел", "Add a tag": "Добавяне на таг", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Добавяне на Файлове", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Добавяне на потребител", "Add User Group": "Добавяне на потребителска група", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Администратор", "Admin Contact Email": "", "Admin Panel": "Панел на Администратор", + "Admin Roles": "", "Admin Settings": "Настройки на администратора", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Администраторите имат достъп до всички инструменти по всяко време; потребителите се нуждаят от инструменти, присвоени за всеки модел в работното пространство.", "Advanced": "", "Advanced Parameters": "Разширени параметри", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Всички модели са изтрити успешно", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Разреши контроли на чата", "Allow Chat Delete": "Разреши изтриване на чат", "Allow Chat Edit": "Разреши редактиране на чат", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Разреши местоположението на потребителя", "Allow Voice Interruption in Call": "Разреши прекъсване на гласа по време на разговор", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Разрешени крайни точки", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Вече имате акаунт?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Винаги", @@ -173,6 +197,7 @@ "API Base URL": "API Базов URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API Ключ", + "API Key / Token": "", "API Key created.": "API Ключ създаден.", "API Key Endpoint Restrictions": "Ограничения на крайните точки за API Ключ", "API keys": "API Ключове", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Сигурни ли сте, че искате да изтриете това съобщение?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Сигурни ли сте, че искате да разархивирате всички архивирани чатове?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Арена Модели", "Artifacts": "Артефакти", "Asc": "", "Ask": "Питай", "Ask a question": "Задайте въпрос", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Асистент", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Аудио", "August": "Август", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Удостоверяване", "Authentication": "Автентикация", "Auto": "Авто", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Автоматично копиране на отговор в клипборда", - "Auto-playback response": "Автоматично възпроизвеждане на отговора", + "Auto-Create Groups": "", + "Auto-Playback Response": "Автоматично възпроизвеждане на отговора", "Autocomplete Generation": "Генериране на автоматично довършване", "Autocomplete Generation Input Max Length": "Максимална дължина на входа за генериране на автоматично довършване", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth низ", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Базов URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Налични инструменти", "available users": "Налични потребители", + "Available variables": "", "available!": "наличен!", "Away": "Отсъства", "Awful": "Ужасно", @@ -258,16 +295,17 @@ "Bad Response": "Невалиден отговор от API", "Banners": "Банери", "Base Model (From)": "Базов модел (от)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "преди", "Being lazy": "Мързелив е", - "Beta": "Бета", "Bing": "", "Bing Search V7 Endpoint": "Крайна точка за Bing Search V7", "Bing Search V7 Subscription Key": "Абонаментен ключ за Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "API ключ за Bocha Search", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Направление на чата", + "Chat Direction": "Направление на чата", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Колекция", + "Collection Field": "", "Collections": "", "Color": "Цвят", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI Работен поток", "ComfyUI Workflow Nodes": "Възли на ComfyUI работен поток", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Команда", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Довършвания", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Свържете се със собствени крайни точки на API, съвместими с OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Свържете се с администратор за достъп до WebUI", "Content": "Съдържание", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Продължи отговора", "Continue with {{provider}}": "Продължете с {{provider}}", "Continue with Email": "Продължете с имейл", @@ -493,6 +543,7 @@ "Create new secret key": "Създаване на нов секретен ключ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Създадено на", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Режимът по подразбиране работи с по-широк набор от модели, като извиква инструменти веднъж преди изпълнение. Нативният режим използва вградените възможности за извикване на инструменти на модела, но изисква моделът да поддържа тази функция по същество.", "Default Model": "Модел по подразбиране", "Default model updated": "Моделът по подразбиране е обновен", "Default permissions": "Разрешения по подразбиране", @@ -542,6 +593,7 @@ "Default to ALL": "По подразбиране за ВСИЧКИ", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Ролята на потребителя по подразбиране", + "Default webhook": "", "Defaults": "", "Delete": "Изтриване", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Деактивирано", "Disconnect OAuth": "", "Discover a function": "Открийте функция", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели", "Discussion channel where access is based on groups and permissions": "", "Display": "Показване", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Показване на емотикони в обаждането", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Показване на потребителското име вместо Вие в чата", + "Display the Username Instead of You in the Chat": "Показване на потребителското име вместо Вие в чата", "Displays citations in the response": "Показвам цитати в отговора", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Потопете се в знанието", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Документ", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Редактиране на разрешения по подразбиране", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Редактиране на памет", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Редактиране на потребител", "Edit User Group": "Редактиране на потребителска група", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Имейл", + "Email Claim": "", "Embark on adventures": "Отправете се на приключения", "Embedding": "", "Embedding Batch Size": "Размер на партидата за вграждане", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Двигател на модела за вграждане", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "Активиране на интерпретатор на код", "Enable Community Sharing": "Разрешаване на споделяне в общност", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Активиране на заключване на паметта (mlock), за да се предотврати изваждането на данните на модела от RAM. Тази опция заключва работния набор от страници на модела в RAM, гарантирайки, че няма да бъдат изхвърлени на диска. Това може да помогне за поддържане на производителността, като се избягват грешки в страниците и се осигурява бърз достъп до данните.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Активиране на мапиране на паметта (mmap) за зареждане на данни на модела. Тази опция позволява на системата да използва дисковото пространство като разширение на RAM, третирайки дисковите файлове, сякаш са в RAM. Това може да подобри производителността на модела, като позволява по-бърз достъп до данните. Въпреки това, може да не работи правилно с всички системи и може да консумира значително количество дисково пространство.", "Enable Message Queue": "", "Enable Message Rating": "Активиране на оценяване на съобщения", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Включване на нови регистрации", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Активирано", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Уверете се, че вашият CSV файл включва 4 колони в следния ред: Име, Имейл, Парола, Роля.", "Enter {{role}} message here": "Въведете съобщение за {{role}} тук", - "Enter a detail about yourself for your LLMs to recall": "Въведете подробности за себе си, за да ги запомнят вашите LLMs", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Въведете припокриване на чънкове", "Enter Chunk Size": "Въведете размер на чънк", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Въведете URL адрес за Jupyter", "Enter Kagi Search API Key": "Въведете API ключ за Kagi Search", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Въведете кодове на езика", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Въведете URL адрес на прокси (напр. https://user:password@host:port)", "Enter reasoning effort": "Въведете усилие за разсъждение", + "Enter Redirect URI": "", "Enter Score": "Въведете оценка", "Enter SearchApi API Key": "Въведете API ключ за SearchApi", "Enter SearchApi Engine": "Въведете двигател за SearchApi", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Въведете API ключ за SerpApi", "Enter SerpApi Engine": "Въведете двигател за SerpApi", "Enter Serper API Key": "Въведете API ключ за Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Въведете API ключ за Serply", "Enter Serpstack API Key": "Въведете API ключ за Serpstack", "Enter server host": "Въведете хост на сървъра", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Въведете URL адрес на Tika сървър", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Въведете Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Въведете URL (напр. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Оценки", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "API ключ за Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Пример: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Пример: ВСИЧКИ", "Example: mail": "Пример: поща", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Експортиране в CSV", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Неуспешно създаване на API ключ.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Неуспешно извличане на модели", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Грешка при четене на съдържанието от клипборда", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Неуспешно запазване на конфигурацията на моделите", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Неуспешно актуализиране на настройките", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Неуспешно качване на файл.", "Features": "Функции", "Features Permissions": "Разрешения за функции", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Файлът е качен успешно", "Filename": "", "Files": "Файлове", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Филтърът вече е глобално деактивиран", "Filter is now globally enabled": "Филтърът вече е глобално активиран", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Функцията вече е глобално активирана", "Function Name": "Име на функцията", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Функцията е актуализирана успешно", "Functions": "Функции", "Functions allow arbitrary code execution.": "Функциите позволяват произволно изпълнение на кода.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Групата е създадена успешно", "Group deleted successfully": "Групата е изтрита успешно", "Group Description": "Описание на групата", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Тактилна обратна връзка", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Важна актуализация", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Ключ", "Key is required": "", - "Keyboard shortcuts": "Клавиши за бърз достъп", "Keyboard Shortcuts": "", "Knowledge": "Знания", "Knowledge Access": "Достъп до знания", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Знанието е актуализирано успешно", "Kokoro.js (Browser)": "Kokoro.js (Браузър)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Последен отговор", "LDAP": "LDAP", - "LDAP server updated": "LDAP сървърът е актуализиран", "Leaderboard": "Класация", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Лиценз", + "Lifecycle JSON": "", "Lift List": "", "Light": "Светъл", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "Изгубено", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Направено от OpenWebUI общността", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Управление на пайплайни", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Март", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Паметта е изчистена успешно", "Memory deleted successfully": "Паметта е изтрита успешно", "Memory updated successfully": "Паметта е актуализирана успешно", + "Merge Accounts by Email": "", "Merge Responses": "Обединяване на отговори", "Merged Response": "Обединен отговор", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Съобщенията, които изпращате след създаването на връзката, няма да бъдат споделяни. Потребителите с URL адреса ще могат да видят споделения чат.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "API ключ за Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Повече", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Именувайте вашата база от знания", "Name, prompt, and model are required": "", "Native": "Нативен", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Няма налично разстояние", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Не е избран файл", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Няма намерени резултати", "No results found": "Няма намерени резултати", "No search query generated": "Не е генерирана заявка за търсене", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Никой", + "Not configured": "", "Not factually correct": "Не е фактологически правилно", "Not helpful": "Не е полезно", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Известия", "November": "Ноември", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ID на OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Октомври", "Off": "Изкл.", "Okay, Let's Go!": "ОК, Нека започваме!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED тъмно", "Ollama": "Ollama", "Ollama API": "API на Ollama", "Ollama API settings updated": "Настройките на Ollama API са актуализирани", "Ollama Cloud API Key": "", "Ollama Version": "Ollama Версия", + "Omit": "", "On": "Вкл.", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Парола", "Passwords do not match.": "", "Paste Large Text as File": "Поставете голям текст като файл", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF документ (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "в очакване", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Отказан достъп при опит за достъп до медийни устройства", "Permission denied when accessing microphone": "Отказан достъп при опит за достъп до микрофона", "Permission denied when accessing microphone: {{error}}": "Отказан достъп при опит за достъп до микрофона: {{error}}", "Permissions": "Разрешения", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Персонализация", + "Picture Claim": "", "Pin": "Закачи", "Pin to Sidebar": "", "Pinned": "Закачено", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Моля, попълнете всички полета.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Моля, първо изберете модела.", "Please select a model.": "Моля, изберете модел.", "Please select a reason": "Моля, изберете причина", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Порт", "Ports": "", "Positive attitude": "Позитивно отношение", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Публично споделяне на промптове", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Публично", "Pull \"{{searchValue}}\" from Ollama.com": "Извади \"{{searchValue}}\" от Ollama.com", "Pull a model from Ollama.com": "Издърпайте модела от Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Четене", "Read Aloud": "Прочети на глас", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Усилие за разсъждение", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Запиши", "Record voice": "Записване на глас", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Пренасочване към OpenWebUI общността", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Отнасяйте се към себе си като \"Потребител\" (напр. \"Потребителят учи испански\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Отказано, когато не трябва да бъде", "Regenerate": "Регенериране", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Преорганизиране на моделите", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Отговори в тред", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Двигател за пренареждане", "Reranking Model": "Модел за преподреждане", + "Research Knowledge": "", "Reset": "Нулиране", "Reset All Models": "Нулиране на всички модели", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Нулиране на изображението", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Нулиране на директорията за качване", "Reset Vector Storage/Knowledge": "Нулиране на векторното хранилище/знания", "Reset view": "Нулиране на изгледа", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Богат текстов вход за чат", "Role": "Роля", + "Roles Claim": "", "RTL": "RTL", "Run": "Изпълни", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Запазването на чат логове директно в хранилището на вашия браузър вече не се поддържа. Моля, отделете малко време, за да изтеглите и изтриете чат логовете си, като щракнете върху бутона по-долу. Не се притеснявайте, можете лесно да импортирате отново чат логовете си в бекенда чрез", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Търси", "Search a model": "Търси модел", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Търсене на чатове", "Search Collection": "Търсене в колекция", "Search Files": "", + "Search filters": "", "Search Filters": "Филтри за търсене", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Търсене на модели", "Search Notes": "", "Search options": "Опции за търсене", + "Search or add pattern": "", "Search Prompts": "Търси Промптове", "Search Result Count": "Брой резултати от търсенето", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Търсене в интернет", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Инструменти за търсене", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "API ключ за SearchApi", "SearchApi Engine": "Двигател на SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "Начално число", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Изберете базов модел", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Изберете двигател", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Изпрати", "Send a Message": "Изпращане на Съобщение", + "Send events for": "", "Send message": "Изпращане на съобщение", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Септември", "SerpApi API Key": "API ключ за SerpApi", "SerpApi Engine": "Двигател на SerpApi", "Serper API Key": "Serper API ключ", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "API ключ за Serply", "Serpstack API Key": "Serpstack API ключ", "Server connection failed": "", "Server connection verified": "Връзката със сървъра е потвърдена", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Задай по подразбиране", "Set as Production": "", "Set embedding model": "Задай модел за вграждане", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Споделете с OpenWebUI Общността", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Права за споделяне", "Show": "Покажи", - "Show \"What's New\" modal on login": "Покажи модалния прозорец \"Какво е ново\" при вписване", + "Show \"What's New\" Modal on Login": "Покажи модалния прозорец \"Какво е ново\" при вписване", "Show Admin Details in Account Pending Overlay": "Покажи детайлите на администратора в наслагването на изчакващ акаунт", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Покажи модел", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Източник", + "Specific users or groups": "", "Speech Playback Speed": "Скорост на възпроизвеждане на речта", "Speech recognition error: {{error}}": "Грешка при разпознаване на речта: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT Настройки", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Система", + "System events only": "", "System Instructions": "Системни инструкции", "System Prompt": "Системен Промпт", + "Table": "", "Tag": "", "Tags": "Тагове", "Tags Generation": "Генериране на тагове", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Разделител на текст", "Text-to-Speech": "", "Text-to-Speech Engine": "Двигател за преобразуване на текст в реч", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP атрибутът, който съответства на имейла, който потребителите използват за вписване.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP атрибутът, който съответства на потребителското име, което потребителите използват за вписване.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Класацията в момента е в бета версия и може да коригираме изчисленията на рейтинга, докато усъвършенстваме алгоритъма.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Максималният размер на файла в MB. Ако размерът на файла надвишава този лимит, файлът няма да бъде качен.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Максималният брой файлове, които могат да се използват едновременно в чата. Ако броят на файловете надвишава този лимит, файловете няма да бъдат качени.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Това е експериментална функция, може да не работи според очакванията и подлежи на промяна по всяко време.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "За да научите повече за наличните крайни точки, посетете нашата документация.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "За да изберете инструменти тук, първо ги добавете към работното пространство \"Инструменти\".", - "Toast notifications for new updates": "Изскачащи известия за нови актуализации", + "Toast Notifications for New Updates": "Изскачащи известия за нови актуализации", "Today": "Днес", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Токен", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Прекалено многословно", @@ -2184,14 +2350,19 @@ "Unpin": "Откачи", "Unpin from Sidebar": "", "Unravel secrets": "Разгадай тайни", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Без етикет", "Untitled": "Неозаглавен", "Update": "Актуализиране", "Update and Copy Link": "Обнови и копирай връзката", + "Update Email": "", "Update for the latest features and improvements.": "Актуализирайте за най-новите функции и подобрения.", + "Update Name": "", "Update password": "Обновяване на парола", + "Update Picture": "", "Update your status": "", "Updated": "Актуализирано", "Updated at": "Актуализирано на", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Използвайте '#' в полето за въвеждане, за да заредите и включите вашите знания.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "потребител", "User": "Потребител", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Местоположението на потребителя е успешно извлечено.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "Потребителско име", + "Username Claim": "", "users": "", "Users": "Потребители", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Клапаните са актуализирани", "Valves updated successfully": "Клапаните са актуализирани успешно", "variable": "променлива", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Версия", @@ -2276,11 +2454,14 @@ "Web API": "Уеб API", "Web Loader Engine": "", "Web Search": "Търсене в уеб", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Уеб търсачка", "Web Search in Chat": "Уеб търсене в чата", "Web Search Query Generation": "Генериране на заявки за уеб търсене", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Уебхук URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI Настройки", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "вчера", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Вие", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Цялата ви вноска ще отиде директно при разработчика на плъгина; Open WebUI не взима никакъв процент. Въпреки това, избраната платформа за финансиране може да има свои собствени такси.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube език", diff --git a/src/lib/i18n/locales/bn-BD/translation.json b/src/lib/i18n/locales/bn-BD/translation.json index 1aca769344..4b94fc6a54 100644 --- a/src/lib/i18n/locales/bn-BD/translation.json +++ b/src/lib/i18n/locales/bn-BD/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}র চ্যাটস", "{{webUIName}} Backend Required": "{{webUIName}} ব্যাকএন্ড আবশ্যক", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "একাউন্ট", @@ -72,6 +83,7 @@ "Activity": "", "Add": "যোগ করুন", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "এই মডেলটি কী করে সে সম্পর্কে একটি সংক্ষিপ্ত বিবরণ যুক্ত করুন", "Add a tag": "একটি ট্যাগ যোগ করুন", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "ফাইল যোগ করুন", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "ইউজার যোগ করুন", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "এডমিন প্যানেল", + "Admin Roles": "", "Admin Settings": "এডমিন সেটিংস", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "এডভান্সড প্যারামিটার্স", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "আগে থেকেই একাউন্ট আছে?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "এপিআই বেজ ইউআরএল", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "এপিআই কোড", + "API Key / Token": "", "API Key created.": "একটি এপিআই কোড তৈরি করা হয়েছে.", "API Key Endpoint Restrictions": "", "API keys": "এপিআই কোডস", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "অডিও", "August": "আগস্ট", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "রেসপন্সগুলো স্বয়ংক্রিভাবে ক্লিপবোর্ডে কপি হবে", - "Auto-playback response": "রেসপন্স অটো-প্লেব্যাক", + "Auto-Create Groups": "", + "Auto-Playback Response": "রেসপন্স অটো-প্লেব্যাক", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 বেজ ইউআরএল", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "উপলব্ধ ব্যবহারকারী", + "Available variables": "", "available!": "উপলব্ধ!", "Away": "অনুপস্থিত", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "খারাপ প্রতিক্রিয়া", "Banners": "ব্যানার", "Base Model (From)": "বেস মডেল (থেকে)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "পূর্ববর্তী", "Being lazy": "অলস হওয়া", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "চ্যাট দিকনির্দেশ", + "Chat Direction": "চ্যাট দিকনির্দেশ", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "সংগ্রহ", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "কমান্ড", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "বিষয়বস্তু", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "যাচাই করুন", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "একটি নতুন সিক্রেট কী তৈরি করুন", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "নির্মানকাল", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "ডিফল্ট মডেল", "Default model updated": "ডিফল্ট মডেল আপডেট হয়েছে", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "ইউজারের ডিফল্ট পদবি", + "Default webhook": "", "Defaults": "", "Delete": "মুছে ফেলুন", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "নিষ্ক্রিয়", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান", + "Display the Username Instead of You in the Chat": "চ্যাটে 'আপনি'-র পরবর্তে ইউজারনেম দেখান", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "ডকুমেন্ট", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ইউজার এডিট করুন", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "ইমেইল", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "ইমেজ ইমেবডিং মডেল ইঞ্জিন", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "সম্প্রদায় শেয়ারকরণ সক্ষম করুন", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "নতুন সাইনআপ চালু করুন", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "সক্রিয়", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "আপনার সিএসভি ফাইলটিতে এই ক্রমে 4 টি কলাম অন্তর্ভুক্ত রয়েছে তা নিশ্চিত করুন: নাম, ইমেল, পাসওয়ার্ড, ভূমিকা।.", "Enter {{role}} message here": "{{role}} মেসেজ এখানে লিখুন", - "Enter a detail about yourself for your LLMs to recall": "আপনার এলএলএমগুলি স্মরণ করার জন্য নিজের সম্পর্কে একটি বিশদ লিখুন", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "চাঙ্ক ওভারল্যাপ লিখুন", "Enter Chunk Size": "চাংক সাইজ লিখুন", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "ল্যাঙ্গুয়েজ কোড লিখুন", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "স্কোর দিন", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Serper API কী লিখুন", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "Serpstack API কী লিখুন", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K লিখুন", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "ইউআরএল দিন (যেমন http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API Key তৈরি করা যায়নি।", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ক্লিপবোর্ডের বিষয়বস্তু পড়া সম্ভব হয়নি", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "গুরুত্বপূর্ণ আপডেট", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "কিবোর্ড শর্টকাটসমূহ", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "লাইট", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "OpenWebUI কমিউনিটিকর্তৃক নির্মিত", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "পাইপলাইন পরিচালনা করুন", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "মার্চ", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "একত্রিত প্রতিক্রিয়া ফলাফল", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "আপনার লিঙ্ক তৈরি করার পরে আপনার পাঠানো বার্তাগুলি শেয়ার করা হবে না। ইউআরএল ব্যবহারকারীরা শেয়ার করা চ্যাট দেখতে পারবেন।", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "আরো", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "কোন ফলাফল পাওয়া যায়নি", "No results found": "কোন ফলাফল পাওয়া যায়নি", "No search query generated": "কোনও অনুসন্ধান ক্যোয়ারী উত্পন্ন হয়নি", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "কোনোটিই নয়", + "Not configured": "", "Not factually correct": "তথ্যগত দিক থেকে সঠিক নয়", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "নোটিফিকেশনসমূহ", "November": "নভেম্বর", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "অক্টোবর", "Off": "বন্ধ", "Okay, Let's Go!": "ঠিক আছে, চলুন যাই!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED ডার্ক", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama ভার্সন", + "Omit": "", "On": "চালু", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "পাসওয়ার্ড", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ডকুমেন্ট (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "অপেক্ষমান", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "মাইক্রোফোন ব্যবহারের অনুমতি পাওয়া যায়নি: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "ডিজিটাল বাংলা", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "পজিটিভ আক্রমণ", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com থেকে \"{{searchValue}}\" টানুন", "Pull a model from Ollama.com": "Ollama.com থেকে একটি টেনে আনুন আনুন", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "পড়াশোনা করুন", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "ভয়েস রেকর্ড করুন", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "আপনাকে OpenWebUI কমিউনিটিতে পাঠানো হচ্ছে", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "যদি উপযুক্ত নয়, তবে রেজিগেনেট করা হচ্ছে", "Regenerate": "রেজিগেনেট করুন", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "রির্যাক্টিং মডেল", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "ছবি রিসেট করুন", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "পদবি", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "মাধ্যমে", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "অনুসন্ধান", "Search a model": "মডেল অনুসন্ধান করুন", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "চ্যাট অনুসন্ধান করুন", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "অনুসন্ধান মডেল", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "প্রম্পটসমূহ অনুসন্ধান করুন", "Search Result Count": "অনুসন্ধানের ফলাফল গণনা", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "সীড", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "একটি বেস মডেল নির্বাচন করুন", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "পাঠান", "Send a Message": "একটি মেসেজ পাঠান", + "Send events for": "", "Send message": "মেসেজ পাঠান", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "সেপ্টেম্বর", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API Key", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "Serpstack API Key", "Server connection failed": "", "Server connection verified": "সার্ভার কানেকশন যাচাই করা হয়েছে", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "ডিফল্ট হিসেবে নির্ধারণ করুন", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "OpenWebUI কমিউনিটিতে শেয়ার করুন", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "দেখান", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "উৎস", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "স্পিচ রিকগনিশনে সমস্যা: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT সেটিংস", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "সিস্টেম", + "System events only": "", "System Instructions": "", "System Prompt": "সিস্টেম প্রম্পট", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "টেক্সট-টু-স্পিচ ইঞ্জিন", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "আজ", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "আপডেট এবং লিংক কপি করুন", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "পাসওয়ার্ড আপডেট করুন", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "ব্যবহারকারী", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "ব্যাবহারকারীগণ", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "ভেরিয়েবল", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "ভার্সন", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "ওয়েব অনুসন্ধান", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "ওয়েব সার্চ ইঞ্জিন", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "ওয়েবহুক URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI সেটিংসমূহ", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "আগামী", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "আপনি", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/bo-TB/translation.json b/src/lib/i18n/locales/bo-TB/translation.json index 2b286b9fbc..02d33df7f5 100644 --- a/src/lib/i18n/locales/bo-TB/translation.json +++ b/src/lib/i18n/locales/bo-TB/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "", "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "ཡིག་ཕྲེང་ {{COUNT}} སྦས་ཡོད།", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "{{user}} ཡི་ཁ་བརྡ།", "{{webUIName}} Backend Required": "{{webUIName}} རྒྱབ་སྣེ་དགོས།", "*Prompt node ID(s) are required for image generation": "*པར་བཟོའི་ཆེད་དུ་འགུལ་སློང་མདུད་ཚེག་གི་ ID(s) དགོས།", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -54,6 +61,7 @@ "Access Control": "འཛུལ་སྤྱོད་ཚོད་འཛིན།", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "བེད་སྤྱོད་མཁན་ཡོངས་ལ་འཛུལ་སྤྱོད་ཆོག་པ།", "Account": "རྩིས་ཁྲ།", @@ -69,6 +77,7 @@ "Activity": "", "Add": "སྣོན་པ།", "Add a model ID": "དཔེ་དབྱིབས་ཀྱི་ ID ཞིག་སྣོན་པ།", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "དཔེ་དབྱིབས་འདིས་ཅི་ཞིག་བྱེད་མིན་སྐོར་གྱི་འགྲེལ་བཤད་ཐུང་ངུ་ཞིག་སྣོན་པ།", "Add a tag": "རྟགས་ཤིག་སྣོན་པ།", "Add a tag...": "", @@ -81,8 +90,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "ཡིག་ཆ་སྣོན་པ།", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -97,6 +108,7 @@ "Add to favorites": "", "Add User": "བེད་སྤྱོད་མཁན་སྣོན་པ།", "Add User Group": "བེད་སྤྱོད་མཁན་ཚོགས་པ་སྣོན་པ།", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -109,7 +121,9 @@ "Admin": "དོ་དམ་པ།", "Admin Contact Email": "", "Admin Panel": "དོ་དམ་པའི་ལྟ་སྟེགས།", + "Admin Roles": "", "Admin Settings": "དོ་དམ་པའི་སྒྲིག་འགོད།", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "དོ་དམ་པས་དུས་རྟག་ཏུ་ལག་ཆ་ཡོངས་ལ་འཛུལ་སྤྱོད་བྱེད་ཆོག བེད་སྤྱོད་མཁན་གྱིས་ལས་ཡུལ་ནང་དཔེ་དབྱིབས་རེ་རེར་བཀོད་པའི་ལག་ཆ་དགོས་མཁོ་ཡོད།", "Advanced": "", "Advanced Parameters": "མཐོ་རིམ་ཞུགས་གྲངས།", @@ -120,16 +134,21 @@ "All": "ཡོངས།", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "དཔེ་དབྱིབས་ཡོངས་རྫོགས་ལེགས་པར་བསུབས་ཟིན།", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "ཁ་བརྡའི་ཚོད་འཛིན་ལ་གནང་བ་སྤྲོད་པ།", "Allow Chat Delete": "ཁ་བརྡ་བསུབ་པར་གནང་བ་སྤྲོད་པ།", "Allow Chat Edit": "ཁ་བརྡ་ཞུ་དག་ལ་གནང་བ་སྤྲོད་པ།", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -149,9 +168,11 @@ "Allow User Location": "བེད་སྤྱོད་མཁན་གནས་ཡུལ་ལ་གནང་བ་སྤྲོད་པ།", "Allow Voice Interruption in Call": "སྐད་འབོད་ནང་གི་སྐད་ཆའི་བར་ཆད་ལ་གནང་བ་སྤྲོད་པ།", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "གནང་བ་ཐོབ་པའི་མཇུག་མཐུད།", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "རྩིས་ཁྲ་ཡོད་ཟིན་ནམ།", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p ཡི་ཚབ་བྱེད། སྤུས་ཚད་དང་སྣ་ཚོགས་ཀྱི་དོ་མཉམ་འགན་ལེན་བྱ་རྒྱུར་དམིགས་པ། ཞུགས་གྲངས་ p ཡིས་མཚོན་བྱེད་ནི། ཆེས་འབྱུང་སྲིད་པའི་ཊོཀ་ཀེན་གྱི་ཆགས་ཚུལ་དང་བསྡུར་ན། བསམ་ཞིབ་བྱེད་དགོས་པའི་ཊོཀ་ཀེན་གྱི་ཆགས་ཚུལ་ཉུང་ཤོས་ཡིན། དཔེར་ན། p=0.05 དང་ཆེས་འབྱུང་སྲིད་པའི་ཊོཀ་ཀེན་གྱི་ཆགས་ཚུལ་ 0.9 ཡིན་ན། 0.045 ལས་ཆུང་བའི་རིན་ཐང་ཅན་གྱི་ལོ་ཇི་ཁེ་སི་དག་ཕྱིར་འཚག་བྱེད་ངེས།", "Always": "རྟག་ཏུ།", @@ -170,6 +191,7 @@ "API Base URL": "API གཞི་རྩའི་ URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API ལྡེ་མིག", + "API Key / Token": "", "API Key created.": "API ལྡེ་མིག་བཟོས་ཟིན།", "API Key Endpoint Restrictions": "API ལྡེ་མིག་མཇུག་མཐུད་ཚད་བཀག", "API keys": "API ལྡེ་མིག", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "འཕྲིན་འདི་བསུབ་འདོད་ངེས་ཡིན་ནམ།", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "ཁྱེད་ཀྱིས་ཡིག་མཛོད་དུ་བཞག་པའི་ཁ་བརྡ་ཡོངས་རྫོགས་ཕྱིར་འདོན་འདོད་ངེས་ཡིན་ནམ།", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena དཔེ་དབྱིབས།", "Artifacts": "རྫས་རྟེན།", "Asc": "", "Ask": "འདྲི་བ།", "Ask a question": "དྲི་བ་ཞིག་འདྲི་བ།", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "ལག་རོགས་པ།", "Async Embedding Processing": "", "At time of event": "", @@ -220,14 +247,20 @@ "Audio": "སྒྲ།", "August": "ཟླ་བརྒྱད་པ།", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "དངོས་ར་སྤྲོད་པ།", "Authentication": "དངོས་ར་སྤྲོད་པ།", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "ལན་རང་འགུལ་གྱིས་སྦྱར་སྡེར་དུ་འདྲ་བཤུས་བྱེད་པ།", - "Auto-playback response": "ལན་རང་འགུལ་གྱིས་གཏོང་བ།", + "Auto-Create Groups": "", + "Auto-Playback Response": "ལན་རང་འགུལ་གྱིས་གཏོང་བ།", "Autocomplete Generation": "རང་འཚང་བཟོ་སྐྲུན།", "Autocomplete Generation Input Max Length": "རང་འཚང་བཟོ་སྐྲུན་ནང་འཇུག་གི་རིང་ཚད་ཆེ་ཤོས།", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth ཡིག་ཕྲེང་།", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 གཞི་རྩའི་ URL", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "", "available users": "ཡོད་པའི་སྤྱོད་མཁན", + "Available variables": "", "available!": "ཡོད།", "Away": "མི་འདུག", "Awful": "ཧ་ཅང་སྡུག", @@ -255,16 +289,17 @@ "Bad Response": "ལན་ངན་པ།", "Banners": "དར་ཆ།", "Base Model (From)": "གཞི་རྩའི་དཔེ་དབྱིབས། (ནས།)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "སྔོན།", "Being lazy": "ལེ་ལོ་བྱེད་པ།", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 མཇུག་མཐུད།", "Bing Search V7 Subscription Key": "Bing Search V7 མངགས་ཉོ་ལྡེ་མིག", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Bocha Search API ལྡེ་མིག", "Bold": "", @@ -321,7 +356,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "ཁ་བརྡའི་ཁ་ཕྱོགས།", + "Chat Direction": "ཁ་བརྡའི་ཁ་ཕྱོགས།", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "", "Collapse": "བསྐུམ་པ།", "Collection": "བསྡུ་གསོག", + "Collection Field": "", "Collections": "", "Color": "ཚོན་མདོག", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "ComfyUI ལས་ཀའི་རྒྱུན་རིམ།", "ComfyUI Workflow Nodes": "ComfyUI ལས་ཀའི་རྒྱུན་རིམ་མདུད་ཚེག", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "བཀའ་བརྡ།", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "འགྲུབ་པ།", "Compress Images in Channels": "", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "ཁྱེད་རང་གི་ OpenAI དང་མཐུན་པའི་ API མཇུག་མཐུད་ལ་སྦྲེལ་བ།", "Connect to your own OpenAPI compatible external tool servers.": "ཁྱེད་རང་གི་ OpenAPI དང་མཐུན་པའི་ཕྱི་རོལ་ལག་ཆའི་སར་བར་ལ་སྦྲེལ་བ།", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "WebUI འཛུལ་སྤྱོད་ཆེད་དུ་དོ་དམ་པ་དང་འབྲེལ་གཏུག་བྱེད་པ།", "Content": "ནང་དོན།", "Content Extraction Engine": "ནང་དོན་འདོན་སྤེལ་འཕྲུལ་འཁོར།", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ལན་མུ་མཐུད་པ།", "Continue with {{provider}}": "{{provider}} དང་མཉམ་དུ་མུ་མཐུད་པ།", "Continue with Email": "ཡིག་ཟམ་དང་མཉམ་དུ་མུ་མཐུད་པ།", @@ -489,6 +536,7 @@ "Create new secret key": "གསང་བའི་ལྡེ་མིག་གསར་པ་བཟོ་བ།", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "གསར་བཟོ་བྱེད་དུས།", @@ -506,6 +554,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "ཉེན་ཁའི་ས་ཁུལ།", @@ -528,7 +577,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "སྔོན་སྒྲིག་མ་དཔེ་ནི་ལག་བསྟར་མ་བྱས་སྔོན་དུ་ལག་ཆ་ཐེངས་གཅིག་འབོད་ནས་དཔེ་དབྱིབས་རྒྱ་ཆེ་བའི་ཁྱབ་ཁོངས་དང་མཉམ་ལས་བྱེད་ཐུབ། ས་སྐྱེས་མ་དཔེ་ཡིས་དཔེ་དབྱིབས་ཀྱི་ནང་འདྲེས་ལག་ཆ་འབོད་པའི་ནུས་པ་སྤྱོད་ཀྱི་ཡོད་མོད། འོན་ཀྱང་དཔེ་དབྱིབས་དེས་ཁྱད་ཆོས་འདི་ལ་ངོ་བོའི་ཐོག་ནས་རྒྱབ་སྐྱོར་བྱེད་དགོས།", "Default Model": "སྔོན་སྒྲིག་དཔེ་དབྱིབས།", "Default model updated": "སྔོན་སྒྲིག་དཔེ་དབྱིབས་གསར་སྒྱུར་བྱས།", "Default permissions": "སྔོན་སྒྲིག་དབང་ཚད།", @@ -538,6 +586,7 @@ "Default to ALL": "སྔོན་སྒྲིག་ཏུ་ཡོངས་རྫོགས།", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "དམིགས་ཚད་དང་འབྲེལ་ཡོད་ནང་དོན་འདོན་སྤེལ་གྱི་ཆེད་དུ་སྔོན་སྒྲིག་ཏུ་དུམ་བུ་ལེན་ཚུར་སྒྲུབ་བྱེད་པ། འདི་ནི་གནས་སྟངས་མང་ཆེ་བའི་ཆེད་དུ་འོས་སྦྱོར་བྱེད།", "Default User Role": "སྔོན་སྒྲིག་བེད་སྤྱོད་མཁན་གྱི་གནས་ཚད།", + "Default webhook": "", "Defaults": "", "Delete": "བསུབ་པ།", "Delete {{name}}": "", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "ནུས་མེད།", "Disconnect OAuth": "", "Discover a function": "ལས་འགན་ཞིག་རྙེད་པ།", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "དཔེ་དབྱིབས་སྔོན་སྒྲིག་རྙེད་པ། ཕབ་ལེན་བྱེད་པ། དང་བརྟག་ཞིབ་བྱེད་པ།", "Discussion channel where access is based on groups and permissions": "", "Display": "འཆར་སྟོན།", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "སྐད་འབོད་ནང་ Emoji འཆར་སྟོན་བྱེད་པ།", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "ཁ་བརྡའི་ནང་ 'ཁྱེད་' ཀྱི་ཚབ་ཏུ་བེད་སྤྱོད་མིང་འཆར་སྟོན་བྱེད་པ།", + "Display the Username Instead of You in the Chat": "ཁ་བརྡའི་ནང་ 'ཁྱེད་' ཀྱི་ཚབ་ཏུ་བེད་སྤྱོད་མིང་འཆར་སྟོན་བྱེད་པ།", "Displays citations in the response": "ལན་ནང་ལུང་འདྲེན་འཆར་སྟོན་བྱེད་པ།", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "ཤེས་བྱའི་ནང་འཛུལ་བ།", @@ -626,6 +677,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Docling སར་བར་གྱི་ URL དགོས་ངེས།", "Document": "ཡིག་ཆ།", + "Document ID Field": "", "Document Intelligence": "ཡིག་ཆའི་རིག་ནུས།", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -681,12 +733,14 @@ "Edit Default Permissions": "སྔོན་སྒྲིག་དབང་ཚད་ཞུ་དག", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "དྲན་ཤེས་ཞུ་དག", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "བེད་སྤྱོད་མཁན་ཞུ་དག", "Edit User Group": "བེད་སྤྱོད་མཁན་ཚོགས་པ་ཞུ་དག", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -695,6 +749,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "ཡིག་ཟམ།", + "Email Claim": "", "Embark on adventures": "ཉེན་བརྟུལ་གྱི་འགྲུལ་བཞུད་ལ་འཇུག་པ།", "Embedding": "ཚུད་འཇུག", "Embedding Batch Size": "ཚུད་འཇུག་ཚན་ཆུང་གི་ཆེ་ཆུང་།", @@ -703,6 +758,7 @@ "Embedding Model Engine": "ཚུད་འཇུག་དཔེ་དབྱིབས་འཕྲུལ་འཁོར།", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -710,22 +766,27 @@ "Enable Code Execution": "ཀོཌ་ལག་བསྟར་སྒུལ་བསྐྱོད་བྱེད་པ།", "Enable Code Interpreter": "ཀོཌ་འགྲེལ་བཤད་སྒུལ་བསྐྱོད་བྱེད་པ།", "Enable Community Sharing": "སྤྱི་ཚོགས་མཉམ་སྤྱོད་སྒུལ་བསྐྱོད་བྱེད་པ།", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "དཔེ་དབྱིབས་ཀྱི་གནས་ཚུལ་ RAM ནས་ཕྱིར་བརྗེ་བར་སྔོན་འགོག་བྱེད་པའི་ཆེད་དུ་དྲན་ཤེས་ཟྭ་རྒྱག་ (mlock) སྒུལ་བསྐྱོད་བྱེད་པ། འདེམས་ཀ་འདིས་དཔེ་དབྱིབས་ཀྱི་ལས་ཀའི་ཤོག་ངོས་ཚོགས་སྡེ་ RAM ནང་ཟྭ་རྒྱག་སྟེ། དེ་དག་ཌིསཀ་ལ་ཕྱིར་བརྗེ་མི་འགྲོ་བ་འགན་ལེན་བྱེད། འདིས་ཤོག་ངོས་ནོར་འཁྲུལ་ལས་གཡོལ་བ་དང་གནས་ཚུལ་མྱུར་པོར་འཛུལ་སྤྱོད་ཐུབ་པའི་འགན་ལེན་བྱས་ནས་ལས་ཆོད་རྒྱུན་སྲུང་བྱེད་པར་རོགས་པ་བྱེད་ཐུབ།", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "དཔེ་དབྱིབས་ཀྱི་གནས་ཚུལ་ནང་འཇུག་བྱེད་པའི་ཆེད་དུ་དྲན་ཤེས་ས་ཁྲ་འགོད་པ་ (mmap) སྒུལ་བསྐྱོད་བྱེད་པ། འདེམས་ཀ་འདིས་མ་ལག་ལ་ཌིསཀ་ཡིག་ཆ་ RAM ནང་ཡོད་པ་ལྟར་བརྩིས་ནས། ཌིསཀ་གསོག་ཆས་ RAM གྱི་རྒྱ་བསྐྱེད་དུ་བེད་སྤྱོད་གཏོང་བའི་གནང་བ་སྤྲོད། འདིས་གནས་ཚུལ་མྱུར་པོར་འཛུལ་སྤྱོད་ཆོག་པར་བཏང་ནས་དཔེ་དབྱིབས་ཀྱི་ལས་ཆོད་ལེགས་སུ་གཏོང་ཐུབ། འོན་ཀྱང་། འདི་མ་ལག་ཡོངས་ལ་ཡང་དག་པར་ལས་ཀ་བྱེད་མི་སྲིད། དེ་མིན་ཌིསཀ་གི་བར་སྟོང་མང་པོ་ཟ་སྲིད།", "Enable Message Queue": "", "Enable Message Rating": "འཕྲིན་ལ་སྐར་མ་སྤྲོད་པ་སྒུལ་བསྐྱོད་བྱེད་པ།", "Enable Mirostat sampling for controlling perplexity.": "རྙོག་འཛིང་ཚད་ཚོད་འཛིན་གྱི་ཆེད་དུ་ Mirostat མ་དཔེ་འདེམས་པ་སྒུལ་བསྐྱོད་བྱེད་པ།", "Enable New Sign Ups": "ཐོ་འགོད་གསར་པ་སྒུལ་བསྐྱོད་བྱེད་པ།", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "སྒུལ་བསྐྱོད་བྱས་ཡོད།", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "གནས་སྐབས་ཁ་བརྡ་བཙན་བཀོལ་བྱེད་པ།", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ཁྱེད་ཀྱི་ CSV ཡིག་ཆར་གོ་རིམ་འདི་ལྟར། མིང་། ཡིག་ཟམ། གསང་གྲངས། གནས་ཚད། སྟར་པ་ ༤ ཚུད་ཡོད་པ་ཁག་ཐེག་བྱེད་རོགས།", "Enter {{role}} message here": "{{role}} ཡི་འཕྲིན་འདིར་འཇུག་པ།", - "Enter a detail about yourself for your LLMs to recall": "ཁྱེད་ཀྱི་ LLMs ཡིས་ཕྱིར་དྲན་ཆེད་དུ་ཁྱེད་རང་གི་སྐོར་གྱི་ཞིབ་ཕྲ་ཞིག་འཇུག་པ།", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "དུམ་བུ་བསྣོལ་བ་འཇུག་པ།", "Enter Chunk Size": "དུམ་བུའི་ཆེ་ཆུང་འཇུག་པ།", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "ཚེག་བསྐུངས་ཀྱིས་ལོགས་སུ་བཀར་བའི་ \"ཊོཀ་ཀེན།:ཕྱོགས་ཞེན་རིན་ཐང་།\" ཆ་འཇུག་པ། (དཔེར། 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "Jupyter URL འཇུག་པ།", "Enter Kagi Search API Key": "Kagi Search API ལྡེ་མིག་འཇུག་པ།", "Enter Key Behavior": "ལྡེ་མིག་གི་བྱེད་སྟངས་འཇུག་པ།", + "Enter language": "", "Enter language codes": "སྐད་ཡིག་གི་ཨང་རྟགས་འཇུག་པ།", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -800,6 +866,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Proxy URL འཇུག་པ། (དཔེར་ན། https://user:password@host:port)", "Enter reasoning effort": "རྒྱུ་མཚན་འདྲེན་པའི་འབད་བརྩོན་འཇུག་པ།", + "Enter Redirect URI": "", "Enter Score": "སྐར་མ་འཇུག་པ།", "Enter SearchApi API Key": "SearchApi API ལྡེ་མིག་འཇུག་པ།", "Enter SearchApi Engine": "SearchApi Engine འཇུག་པ།", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "SerpApi API ལྡེ་མིག་འཇུག་པ།", "Enter SerpApi Engine": "SerpApi Engine འཇུག་པ།", "Enter Serper API Key": "Serper API ལྡེ་མིག་འཇུག་པ།", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API ལྡེ་མིག་འཇུག་པ།", "Enter Serpstack API Key": "Serpstack API ལྡེ་མིག་འཇུག་པ།", "Enter server host": "སར་བར་གྱི་ Host འཇུག་པ།", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "Tika Server URL འཇུག་པ།", "Enter timeout in seconds": "སྐར་ཆའི་ནང་དུས་ཚོད་བཀག་པ་འཇུག་པ།", "Enter to Send": "Enter གཏོང་བ།", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K འཇུག་པ།", "Enter Top K Reranker": "Top K Reranker འཇུག་པ།", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL འཇུག་པ། (དཔེར་ན། http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "གདེང་འཇོག", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API ལྡེ་མིག", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "དཔེར་ན། (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "དཔེར་ན། ALL", "Example: mail": "དཔེར་ན། mail", @@ -901,12 +975,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CSV ལ་ཕྱིར་གཏོང་།", "Export Tools": "", "Export Users": "", "External": "ཕྱི་རོལ།", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "API ལྡེ་མིག་བཟོ་མ་ཐུབ།", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -931,6 +1012,7 @@ "Failed to fetch models": "དཔེ་དབྱིབས་ལེན་པར་མ་ཐུབ།", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -940,6 +1022,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "སྦྱར་སྡེར་གྱི་ནང་དོན་ཀློག་མ་ཐུབ།", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "དཔེ་དབྱིབས་སྒྲིག་འགོད་ཉར་ཚགས་བྱེད་མ་ཐུབ།", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "སྒྲིག་འགོད་གསར་སྒྱུར་བྱེད་མ་ཐུབ།", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "ཡིག་ཆ་སྤར་མ་ཐུབ།", "Features": "ཁྱད་ཆོས།", "Features Permissions": "ཁྱད་ཆོས་ཀྱི་དབང་ཚད།", @@ -983,6 +1068,8 @@ "File uploaded successfully": "ཡིག་ཆ་ལེགས་པར་སྤར་ཟིན།", "Filename": "", "Files": "ཡིག་ཆ།", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "འཚག་མ་དེ་ད་ལྟ་འཛམ་གླིང་ཡོངས་ནས་ནུས་མེད་བཏང་ཡོད།", "Filter is now globally enabled": "འཚག་མ་དེ་ད་ལྟ་འཛམ་གླིང་ཡོངས་ནས་སྒུལ་བསྐྱོད་བྱས་ཡོད།", @@ -1005,6 +1092,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "ལས་འགན་དེ་ད་ལྟ་འཛམ་གླིང་ཡོངས་ནས་སྒུལ་བསྐྱོད་བྱས་ཡོད།", "Function Name": "ལས་འགན་གྱི་མིང་།", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "ལས་འགན་ལེགས་པར་གསར་སྒྱུར་བྱས་ཟིན།", "Functions": "ལས་འགན།", "Functions allow arbitrary code execution.": "ལས་འགན་གྱིས་གང་འདོད་ཀྱི་ཀོཌ་ལག་བསྟར་ལ་གནང་བ་སྤྲོད།", @@ -1067,7 +1156,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "ཚོགས་པ་ལེགས་པར་བཟོས་ཟིན།", "Group deleted successfully": "ཚོགས་པ་ལེགས་པར་བསུབས་ཟིན།", "Group Description": "ཚོགས་པའི་འགྲེལ་བཤད།", @@ -1079,6 +1171,7 @@ "H2": "", "H3": "", "Haptic Feedback": "འདར་འཕྲུལ་གྱི་བསམ་འཆར།", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1134,6 +1229,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "གལ་ཆེ་པའི་གསར་སྒྱུར་", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "", "Key": "ལྡེ་མིག", "Key is required": "", - "Keyboard shortcuts": "མཐེབ་གནོན་མྱུར་ལམ།", "Keyboard Shortcuts": "", "Knowledge": "ཤེས་བྱ།", "Knowledge Access": "ཤེས་བྱར་འཛུལ་སྤྱོད།", @@ -1204,6 +1299,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "ཤེས་བྱ་སྤྱི་སྤྱོད་མཉམ་སྤྱོད།", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "ཤེས་བྱ་ལེགས་པར་གསར་སྒྱུར་བྱས་ཟིན།", "Kokoro.js (Browser)": "Kokoro.js (བརྡ་འཚོལ་ཆས།)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1220,7 +1317,6 @@ "Last ran": "", "Last reply": "ལན་མཐའ་མ།", "LDAP": "LDAP", - "LDAP server updated": "LDAP སར་བར་གསར་སྒྱུར་བྱས།", "Leaderboard": "འགྲན་རེས་རེའུ་མིག", "Learn more": "", "Learn More": "", @@ -1242,6 +1338,7 @@ "Legacy": "", "lexical": "", "License": "ཆོག་མཆན།", + "Lifecycle JSON": "", "Lift List": "", "Light": "དཀར་པོ།", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1265,6 +1362,7 @@ "Location access not allowed": "གནས་ཡུལ་འཛུལ་སྤྱོད་ལ་གནང་བ་མ་སྤྲད།", "Lost": "བརླགས།", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Open WebUI སྤྱི་ཚོགས་ཀྱིས་བཟོས།", "Make password visible in the user interface": "", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "རྒྱུ་ལམ་དོ་དམ།", "Manage Tool Servers": "ལག་ཆའི་སར་བར་དོ་དམ།", "Manage your account information.": "", + "Mapped Source": "", "March": "ཟླ་བ་གསུམ་པ།", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "དྲན་ཤེས་ལེགས་པར་གཙང་སེལ་བྱས་ཟིན།", "Memory deleted successfully": "དྲན་ཤེས་ལེགས་པར་བསུབས་ཟིན།", "Memory updated successfully": "དྲན་ཤེས་ལེགས་པར་གསར་སྒྱུར་བྱས་ཟིན།", + "Merge Accounts by Email": "", "Merge Responses": "ལན་ཟླ་སྒྲིལ།", "Merged Response": "བསྡུར་མཐུན་གྱི་ལན་གསལ་གནས་ཡོད།", "Message": "", @@ -1318,9 +1418,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ཁྱེད་ཀྱི་སྦྲེལ་ཐག་བཟོས་རྗེས་ཁྱེད་ཀྱིས་བསྐུར་བའི་འཕྲིན་དག་མཉམ་སྤྱོད་བྱེད་མི་འགྱུར། URL ཡོད་པའི་བེད་སྤྱོད་མཁན་ཚོས་མཉམ་སྤྱོད་ཁ་བརྡ་ལྟ་ཐུབ་ངེས།", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1373,6 +1476,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search API ལྡེ་མིག", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "མང་བ།", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "ཁྱེད་ཀྱི་ཤེས་བྱའི་རྟེན་གཞི་ལ་མིང་ཐོགས།", "Name, prompt, and model are required": "", "Native": "ས་སྐྱེས།", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1419,6 +1524,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1431,8 +1537,10 @@ "No data": "", "No data found": "", "No distance available": "ཐག་རིང་ཚད་མེད།", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "ཡིག་ཆ་གདམ་ག་མ་བྱས།", "No files found": "", @@ -1460,6 +1568,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "འབྲས་བུ་མ་རྙེད།", "No results found": "འབྲས་བུ་མ་རྙེད།", "No search query generated": "འཚོལ་བཤེར་འདྲི་བ་བཟོས་མེད།", @@ -1479,6 +1588,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "གཅིག་ཀྱང་མེད།", + "Not configured": "", "Not factually correct": "དོན་དངོས་དང་མི་མཐུན།", "Not helpful": "ཕན་ཐོགས་མེད།", "Not Registered": "", @@ -1494,20 +1604,25 @@ "Notifications": "བརྡ་ཁྱབ།", "November": "ཟླ་བ་བཅུ་གཅིག་པ།", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "ཟླ་བ་བཅུ་པ།", "Off": "ཁ་རྒྱག་པ།", "Okay, Let's Go!": "འགྲིག་སོང་། འགྲོ།", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED ནག་པོ།", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API སྒྲིག་འགོད་གསར་སྒྱུར་བྱས།", "Ollama Cloud API Key": "", "Ollama Version": "Ollama པར་གཞི།", + "Omit": "", "On": "ཁ་ཕྱེ་བ།", "Once": "", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "གསང་གྲངས།", "Passwords do not match.": "", "Paste Large Text as File": "ཡིག་རྐྱང་ཆེན་པོ་ཡིག་ཆ་ལྟར་སྦྱོར་བ།", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ཡིག་ཆ། (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "སྒུག་བཞིན་པ།", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "བརྒྱུད་ལམ་སྒྲིག་ཆས་འཛུལ་སྤྱོད་སྐབས་དབང་ཚད་ཁས་མ་བླངས།", "Permission denied when accessing microphone": "སྐད་སྒྲ་འཛིན་ཆས་འཛུལ་སྤྱོད་སྐབས་དབང་ཚད་ཁས་མ་བླངས།", "Permission denied when accessing microphone: {{error}}": "སྐད་སྒྲ་འཛིན་ཆས་འཛུལ་སྤྱོད་སྐབས་དབང་ཚད་ཁས་མ་བླངས།: {{error}}", "Permissions": "དབང་ཚད།", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API ལྡེ་མིག", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "སྒེར་སྤྱོད་ཅན།", + "Picture Claim": "", "Pin": "གདབ་པ།", "Pin to Sidebar": "", "Pinned": "གདབ་ཟིན།", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "ཁོངས་ཡོངས་རྫོགས་ཁ་སྐོང་རོགས།", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "ཐོག་མར་དཔེ་དབྱིབས་ཤིག་གདམ་ག་བྱེད་རོགས།", "Please select a model.": "དཔེ་དབྱིབས་ཤིག་གདམ་ག་བྱེད་རོགས།", "Please select a reason": "རྒྱུ་མཚན་ཞིག་གདམ་ག་བྱེད་རོགས།", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "ལྟ་སྟངས་དགེ་མཚན།", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "འགུལ་སློང་སྤྱི་སྤྱོད་མཉམ་སྤྱོད།", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "སྤྱི་སྤྱོད།", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com ནས་ \"{{searchValue}}\" འཐེན་པ།", "Pull a model from Ollama.com": "Ollama.com ནས་དཔེ་དབྱིབས་ཤིག་འཐེན་པ།", @@ -1683,21 +1804,28 @@ "Read": "ཀློག་པ།", "Read Aloud": "སྐད་གསལ་པོས་ཀློག་པ།", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "རྒྱུ་མཚན་འདྲེན་པའི་འབད་བརྩོན།", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "སྐད་སྒྲ་ཕབ་པ།", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "ཁྱེད་ Open WebUI སྤྱི་ཚོགས་ལ་ཁ་ཕྱོགས་སྒྱུར་བཞིན་པ།", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "དོན་མེད་བཟོ་བའི་ཆགས་ཚུལ་ཉུང་དུ་གཏོང་བ། རིན་ཐང་མཐོ་བ་ (དཔེར་ན། ༡༠༠) ཡིས་ལན་སྣ་ཚོགས་ཆེ་བ་སྤྲོད་ངེས། དེ་བཞིན་དུ་རིན་ཐང་དམའ་བ་ (དཔེར་ན། ༡༠) ཡིས་སྲུང་འཛིན་ཆེ་བ་ཡོང་ངེས།", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "ཁྱེད་རང་ལ་ \"བེད་སྤྱོད་མཁན་\" ཞེས་འབོད་པ། (དཔེར་ན། \"བེད་སྤྱོད་མཁན་གྱིས་སི་པན་གྱི་སྐད་ཡིག་སྦྱོང་བཞིན་པ།\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "མི་དགོས་དུས་ཁས་མ་བླངས།", "Regenerate": "བསྐྱར་བཟོ།", "Regenerate Menu": "", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "དཔེ་དབྱིབས་བསྐྱར་སྒྲིག", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "བརྗོད་གཞིའི་ནང་ལན་འདེབས།", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "བསྐྱར་སྒྲིག་དཔེ་དབྱིབས།", + "Research Knowledge": "", "Reset": "སླར་སྒྲིག", "Reset All Models": "དཔེ་དབྱིབས་ཡོངས་རྫོགས་སླར་སྒྲིག", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "བརྙན་རིས་བསྐྱར་སྒྲིག", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "སྤར་བའི་ཐོ་འཚོལ་སླར་སྒྲིག", "Reset Vector Storage/Knowledge": "ཚད་བརྡའི་གསོག་ཆས།/ཤེས་བྱ་སླར་སྒྲིག", "Reset view": "མཐོང་སྣང་སླར་སྒྲིག", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "ཁ་བརྡའི་ཆེད་དུ་ཡིག་རྐྱང་ཕུན་སུམ་ཚོགས་པའི་ནང་འཇུག", "Role": "གནས་ཚད།", + "Roles Claim": "", "RTL": "RTL", "Run": "ལག་བསྟར།", "Run All": "", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "ཁ་བརྡའི་ཟིན་ཐོ་ཐད་ཀར་ཁྱེད་ཀྱི་བརྡ་འཚོལ་ཆས་ཀྱི་གསོག་ཆས་སུ་ཉར་ཚགས་བྱེད་པར་ད་ནས་བཟུང་རྒྱབ་སྐྱོར་མེད། གཤམ་གྱི་མཐེབ་གནོན་མནན་ནས་ཁྱེད་ཀྱི་ཁ་བརྡའི་ཟིན་ཐོ་ཕབ་ལེན་དང་བསུབ་པར་དུས་ཚོད་ཅུང་ཟད་བླང་རོགས། སེམས་ཁྲལ་མེད། ཁྱེད་ཀྱིས་སྟབས་བདེ་པོར་ཁྱེད་ཀྱི་ཁ་བརྡའི་ཟིན་ཐོ་རྒྱབ་སྣེ་ལ་བསྐྱར་དུ་ནང་འདྲེན་བྱེད་ཐུབ།", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "འཚོལ་བཤེར།", "Search a model": "དཔེ་དབྱིབས་ཤིག་འཚོལ་བ།", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1792,6 +1930,7 @@ "Search Chats": "ཁ་བརྡ་འཚོལ་བཤེར།", "Search Collection": "བསྡུ་གསོག་འཚོལ་བཤེར།", "Search Files": "", + "Search filters": "", "Search Filters": "འཚོལ་བཤེར་འཚག་མ།", "search for archived chats": "", "search for folders": "", @@ -1806,13 +1945,16 @@ "Search Models": "དཔེ་དབྱིབས་འཚོལ་བཤེར།", "Search Notes": "", "Search options": "འཚོལ་བཤེར་འདེམས་ཀ", + "Search or add pattern": "", "Search Prompts": "འགུལ་སློང་འཚོལ་བཤེར།", "Search Result Count": "འཚོལ་བཤེར་འབྲས་བུའི་གྲངས།", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "དྲ་རྒྱ་འཚོལ་བཤེར།", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "ལག་ཆ་འཚོལ་བཤེར།", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API ལྡེ་མིག", "SearchApi Engine": "SearchApi Engine", @@ -1828,7 +1970,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "གཞི་རྩའི་དཔེ་དབྱིབས་ཤིག་གདམ་པ།", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "འཕྲུལ་འཁོར་ཞིག་གདམ་པ།", @@ -1866,18 +2007,25 @@ "semantic": "", "Send": "གཏོང་བ།", "Send a Message": "འཕྲིན་ཞིག་གཏོང་བ།", + "Send events for": "", "Send message": "འཕྲིན་གཏོང་བ།", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "རེ་ཞུའི་ནང་ `stream_options: { include_usage: true }` གཏོང་བ།\nབཀོད་སྒྲིག་བྱས་ཚེ། རྒྱབ་སྐྱོར་ཡོད་པའི་མཁོ་སྤྲོད་པས་ལན་ནང་ཊོཀ་ཀེན་བེད་སྤྱོད་ཀྱི་གནས་ཚུལ་ཕྱིར་སློག་བྱེད་ངེས།", "September": "ཟླ་བ་དགུ་པ།", "SerpApi API Key": "SerpApi API ལྡེ་མིག", "SerpApi Engine": "SerpApi Engine", "Serper API Key": "Serper API ལྡེ་མིག", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API ལྡེ་མིག", "Serpstack API Key": "Serpstack API ལྡེ་མིག", "Server connection failed": "", "Server connection verified": "སར་བར་སྦྲེལ་མཐུད་ར་སྤྲོད་བྱས།", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "སྔོན་སྒྲིག་ཏུ་འཇོག་པ།", "Set as Production": "", "Set embedding model": "ཚུད་འཇུག་དཔེ་དབྱིབས་འཇོག་པ།", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Open WebUI སྤྱི་ཚོགས་ལ་མཉམ་སྤྱོད།", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "མཉམ་སྤྱོད་དབང་ཚད།", "Show": "སྟོན་པ།", - "Show \"What's New\" modal on login": "ནང་འཛུལ་སྐབས་ \"གསར་པ་ཅི་ཡོད\" modal སྟོན་པ།", + "Show \"What's New\" Modal on Login": "ནང་འཛུལ་སྐབས་ \"གསར་པ་ཅི་ཡོད\" modal སྟོན་པ།", "Show Admin Details in Account Pending Overlay": "རྩིས་ཁྲ་སྒུག་བཞིན་པའི་གཏོགས་ངོས་སུ་དོ་དམ་པའི་ཞིབ་ཕྲ་སྟོན་པ།", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "དཔེ་དབྱིབས་སྟོན་པ།", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "འབྱུང་ཁུངས།", + "Specific users or groups": "", "Speech Playback Speed": "གཏམ་བཤད་ཕྱིར་གཏོང་གི་མྱུར་ཚད།", "Speech recognition error: {{error}}": "གཏམ་བཤད་ངོས་འཛིན་ནོར་འཁྲུལ།: {{error}}", "Speech-to-Text": "", @@ -1992,6 +2143,7 @@ "STT Settings": "STT སྒྲིག་འགོད།", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2016,8 +2168,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "མ་ལག", + "System events only": "", "System Instructions": "མ་ལག་གི་ལམ་སྟོན།", "System Prompt": "མ་ལག་གི་འགུལ་སློང་།", + "Table": "", "Tag": "", "Tags": "རྟགས།", "Tags Generation": "རྟགས་བཟོ་སྐྲུན།", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "ཡིག་རྐྱང་བགོ་བྱེད།", "Text-to-Speech": "", "Text-to-Speech Engine": "ཡིག་རྐྱང་ནས་གཏམ་བཤད་ཀྱི་འཕྲུལ་འཁོར།", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "བེད་སྤྱོད་མཁན་ཚོས་ནང་འཛུལ་བྱེད་སྐབས་བེད་སྤྱོད་གཏོང་བའི་ཡིག་ཟམ་ལ་སྦྲེལ་བའི་ LDAP ཁྱད་ཆོས།", "The LDAP attribute that maps to the username that users use to sign in.": "བེད་སྤྱོད་མཁན་ཚོས་ནང་འཛུལ་བྱེད་སྐབས་བེད་སྤྱོད་གཏོང་བའི་བེད་སྤྱོད་མིང་ལ་སྦྲེལ་བའི་ LDAP ཁྱད་ཆོས།", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "འགྲན་རེས་རེའུ་མིག་དེ་ད་ལྟ་ Beta པར་གཞི་ཡིན། ང་ཚོས་ཨང་རྩིས་དེ་ཞིབ་ཚགས་སུ་གཏོང་སྐབས་སྐར་མའི་རྩིས་རྒྱག་ལེགས་སྒྲིག་བྱེད་སྲིད།", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "MB ནང་གི་ཡིག་ཆའི་ཆེ་ཆུང་མང་ཤོས། གལ་ཏེ་ཡིག་ཆའི་ཆེ་ཆུང་ཚད་བཀག་འདི་ལས་བརྒལ་ན། ཡིག་ཆ་དེ་སྤར་མི་འགྱུར།", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "ཁ་བརྡའི་ནང་ཐེངས་གཅིག་ལ་བེད་སྤྱོད་གཏོང་ཐུབ་པའི་ཡིག་ཆའི་གྲངས་མང་ཤོས། གལ་ཏེ་ཡིག་ཆའི་གྲངས་ཚད་བཀག་འདི་ལས་བརྒལ་ན། ཡིག་ཆ་དག་སྤར་མི་འགྱུར།", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2075,6 +2234,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "འདི་ནི་ཚོད་ལྟའི་རང་བཞིན་གྱི་ཁྱད་ཆོས་ཤིག་ཡིན། དེ་རེ་སྒུག་ལྟར་ལས་ཀ་བྱེད་མི་སྲིད། དེ་མིན་དུས་ཚོད་གང་རུང་ལ་འགྱུར་བ་འགྲོ་སྲིད།", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "འདེམས་ཀ་འདིས་ནང་དོན་གསར་སྒྱུར་བྱེད་སྐབས་ཊོཀ་ཀེན་ག་ཚོད་ཉར་ཚགས་བྱེད་དགོས་ཚོད་འཛིན་བྱེད། དཔེར་ན། གལ་ཏེ་ ༢ ལ་བཀོད་སྒྲིག་བྱས་ན། ཁ་བརྡའི་ནང་དོན་གྱི་ཊོཀ་ཀེན་མཐའ་མ་ ༢ ཉར་ཚགས་བྱེད་ངེས། ནང་དོན་ཉར་ཚགས་བྱས་ན་ཁ་བརྡའི་རྒྱུན་མཐུད་རང་བཞིན་རྒྱུན་སྲུང་བྱེད་པར་རོགས་པ་བྱེད་ཐུབ། འོན་ཀྱང་དེས་བརྗོད་གཞི་གསར་པར་ལན་འདེབས་བྱེད་པའི་ནུས་པ་ཉུང་དུ་གཏོང་སྲིད།", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "ཡོད་པའི་མཇུག་མཐུད་སྐོར་མང་ཙམ་ཤེས་པར། ང་ཚོའི་ཡིག་ཆ་ལ་ལྟ་བ།", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "ལག་ཆའི་ཚོགས་སྡེ་འདིར་གདམ་ག་བྱེད་པར། ཐོག་མར་དེ་དག་ \"ལག་ཆའི་\" ལས་ཡུལ་དུ་སྣོན་པ།", - "Toast notifications for new updates": "གསར་སྒྱུར་གསར་པའི་ཆེད་དུ་ Toast བརྡ་ཁྱབ།", + "Toast Notifications for New Updates": "གསར་སྒྱུར་གསར་པའི་ཆེད་དུ་ Toast བརྡ་ཁྱབ།", "Today": "དེ་རིང་།", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "", "Token": "ཊོཀ་ཀེན།", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "རིང་དྲགས།", @@ -2177,14 +2339,19 @@ "Unpin": "ཕྱིར་འདོན།", "Unpin from Sidebar": "", "Unravel secrets": "གསང་བ་གྲོལ་བ།", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "རྟགས་མེད།", "Untitled": "", "Update": "གསར་སྒྱུར།", "Update and Copy Link": "གསར་སྒྱུར་དང་སྦྲེལ་ཐག་འདྲ་བཤུས།", + "Update Email": "", "Update for the latest features and improvements.": "ཁྱད་ཆོས་དང་ལེགས་བཅོས་གསར་ཤོས་ཀྱི་ཆེད་དུ་གསར་སྒྱུར་བྱེད་པ།", + "Update Name": "", "Update password": "གསང་གྲངས་གསར་སྒྱུར།", + "Update Picture": "", "Update your status": "", "Updated": "གསར་སྒྱུར་བྱས།", "Updated at": "གསར་སྒྱུར་བྱེད་དུས།", @@ -2211,13 +2378,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "འགུལ་སློང་ནང་འཇུག་ཏུ་ '#' བེད་སྤྱོད་ནས་ཁྱེད་ཀྱི་ཤེས་བྱ་ནང་འཇུག་དང་ཚུད་པ།", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "བེད་སྤྱོད་མཁན།", "User": "བེད་སྤྱོད་མཁན།", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "བེད་སྤྱོད་མཁན་གནས་ཡུལ་ལེགས་པར་ལེན་ཚུར་སྒྲུབ་བྱས།", @@ -2227,6 +2399,7 @@ "User Status": "", "User Webhooks": "བེད་སྤྱོད་མཁན་གྱི་ Webhooks", "Username": "བེད་སྤྱོད་མིང་།", + "Username Claim": "", "users": "", "Users": "བེད་སྤྱོད་མཁན།", "Uses DefaultAzureCredential to authenticate": "", @@ -2240,6 +2413,7 @@ "Valves updated": "Valves གསར་སྒྱུར་བྱས།", "Valves updated successfully": "Valves ལེགས་པར་གསར་སྒྱུར་བྱས།", "variable": "འགྱུར་ཚད།", + "Vector Field": "", "Verify Connection": "སྦྲེལ་མཐུད་ར་སྤྲོད།", "Verify SSL Certificate": "", "Version": "པར་གཞི།", @@ -2269,11 +2443,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "དྲ་བའི་འཚོལ་བཤེར།", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "དྲ་བའི་འཚོལ་བཤེར་འཕྲུལ་འཁོར།", "Web Search in Chat": "ཁ་བརྡའི་ནང་དྲ་བའི་འཚོལ་བཤེར།", "Web Search Query Generation": "དྲ་བའི་འཚོལ་བཤེར་འདྲི་བ་བཟོ་སྐྲུན།", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI སྒྲིག་འགོད།", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "ཁ་ས།", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "ཁྱེད།", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "ཁྱེད་ཀྱི་ཞལ་འདེབས་ཆ་ཚང་ཐད་ཀར་ plugin གསར་སྤེལ་བ་ལ་འགྲོ་ངེས། Open WebUI ཡིས་བརྒྱ་ཆ་གང་ཡང་མི་ལེན། འོན་ཀྱང་། གདམ་ཟིན་པའི་མ་དངུལ་གཏོང་བའི་སྟེགས་བུ་ལ་དེའི་རང་གི་འགྲོ་གྲོན་ཡོད་སྲིད།", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube སྐད་ཡིག", diff --git a/src/lib/i18n/locales/bs-BA/translation.json b/src/lib/i18n/locales/bs-BA/translation.json index e657b57166..5a770cfec0 100644 --- a/src/lib/i18n/locales/bs-BA/translation.json +++ b/src/lib/i18n/locales/bs-BA/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_few": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Razgovori korisnika {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Backend je potreban", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Račun", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Dodaj", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Dodajte kratak opis funkcija ovog modela", "Add a tag": "Dodaj oznaku", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Dodaj datoteke", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Dodaj korisnika", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Admin ploča", + "Admin Roles": "", "Admin Settings": "Admin postavke", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Admini imaju pristup svim alatima u svako doba; korisninicima je dat pristup alatima u zavisnosti od modela u radnoj povrsini", "Advanced": "", "Advanced Parameters": "Napredni parametri", @@ -126,16 +146,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Svi modeli su uspjesno izbrisani", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Dozvoli poziv", "Allow Chat Controls": "Dozvoli kontrolu razgovora", "Allow Chat Delete": "Dozvoli brisanaje razgovora", "Allow Chat Edit": "Dozvoli uredjivanje razgovora", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "Dozvoli dijeljenje razgovora", "Allow Chat System Prompt": "Dozvoli Chat System Promt", @@ -155,9 +180,11 @@ "Allow User Location": "Dozvoli User Lokacije", "Allow Voice Interruption in Call": "Dozvoli Prekidanje Govora u Pozivu", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Već imate račun?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -176,6 +203,7 @@ "API Base URL": "Osnovni URL API-ja", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API ključ", + "API Key / Token": "", "API Key created.": "API ključ je stvoren.", "API Key Endpoint Restrictions": "", "API keys": "API ključevi", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "Pitaj", "Ask a question": "Pitaj pitanje", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistent", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Avgust", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatsko kopiranje odgovora u međuspremnik", - "Auto-playback response": "Automatska reprodukcija odgovora", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatska reprodukcija odgovora", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 osnovni URL", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "", "available users": "dostupni korisnici", + "Available variables": "", "available!": "dostupno!", "Away": "Odsutan", "Awful": "", @@ -261,16 +301,17 @@ "Bad Response": "Loš odgovor", "Banners": "Baneri", "Base Model (From)": "Osnovni model (Od)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "prije", "Being lazy": "Biti lijen", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Razgovor - smijer", + "Chat Direction": "Razgovor - smijer", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Kolekcija", + "Collection Field": "", "Collections": "", "Color": "Boja", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Naredba", "Comment": "Komentar", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Konekcija nije uspjela", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Kontaktirajte admina za WebUI pristup", "Content": "Sadržaj", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Nastavi odgovor", "Continue with {{provider}}": "", "Continue with Email": "", @@ -497,6 +550,7 @@ "Create new secret key": "Stvori novi tajni ključ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Stvoreno", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Zadani model", "Default model updated": "Zadani model ažuriran", "Default permissions": "", @@ -546,6 +600,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Zadana korisnička uloga", + "Default webhook": "", "Defaults": "", "Delete": "Izbriši", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Onemogućeno", "Disconnect OAuth": "", "Discover a function": "", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru", + "Display the Username Instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Uredi korisnika", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "Embedding - Veličina batch-a", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Embedding model pogon", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "Omogući Code Execution", "Enable Code Interpreter": "", "Enable Community Sharing": "Omogući zajedničko korištenje zajednice", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Omogući nove prijave", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Omogućeno", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Provjerite da vaša CSV datoteka uključuje 4 stupca u ovom redoslijedu: Name, Email, Password, Role.", "Enter {{role}} message here": "Unesite {{role}} poruku ovdje", - "Enter a detail about yourself for your LLMs to recall": "Unesite pojedinosti o sebi da bi učitali memoriju u LLM", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Unesite preklapanje dijelova", "Enter Chunk Size": "Unesite veličinu dijela", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Unesite kodove jezika", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Unesite ocjenu", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Unesite Serper API ključ", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Unesite Serply API ključ", "Enter Serpstack API Key": "Unesite Serpstack API ključ", "Enter server host": "", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Unesite Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Unesite URL (npr. http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Neuspješno stvaranje API ključa.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Neuspješno čitanje sadržaja međuspremnika", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Greška kod ažuriranja postavki", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -991,6 +1082,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1142,6 +1243,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Važno ažuriranje", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Tipkovnički prečaci", "Keyboard Shortcuts": "", "Knowledge": "Znanje", "Knowledge Access": "", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Svijetlo", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Izradio OpenWebUI Community", "Make password visible in the user interface": "", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Upravljanje cjevovodima", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Mart", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Spojeni odgovor", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Poruke koje pošaljete nakon stvaranja veze neće se dijeliti. Korisnici s URL-om moći će vidjeti zajednički chat.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Više", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Nema rezultata", "No results found": "Nema rezultata", "No search query generated": "Nije generiran upit za pretraživanje", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Ništa", + "Not configured": "", "Not factually correct": "Nije činjenično točno", "Not helpful": "", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Obavijesti", "November": "Novembar", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktobar", "Off": "Isključeno", "Okay, Let's Go!": "U redu, idemo!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Tamno", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama verzija", + "Omit": "", "On": "Uključeno", "Once": "", "OneDrive": "", @@ -1586,6 +1707,7 @@ "Password": "Lozinka", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokument (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "u tijeku", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Dopuštenje je odbijeno prilikom pristupa medijskim uređajima", "Permission denied when accessing microphone": "Dopuštenje je odbijeno prilikom pristupa mikrofonu", "Permission denied when accessing microphone: {{error}}": "Pristup mikrofonu odbijen: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Prilagodba", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Pozitivan stav", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Povucite \"{{searchValue}}\" s Ollama.com", "Pull a model from Ollama.com": "Povucite model s Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "", "Read Aloud": "Čitaj naglas", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Snimanje glasa", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Preusmjeravanje na OpenWebUI zajednicu", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Nazivajte se \"Korisnik\" (npr. \"Korisnik uči španjolski\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Odbijen kada nije trebao biti", "Regenerate": "Regeneriraj", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Model za ponovno rangiranje", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetiraj sliku", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Poništi upload direktorij", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Uloga", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Spremanje zapisnika razgovora izravno u pohranu vašeg preglednika više nije podržano. Molimo vas da odvojite trenutak za preuzimanje i brisanje zapisnika razgovora klikom na gumb ispod. Ne brinite, možete lako ponovno uvesti zapisnike razgovora u backend putem", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Pretraga", "Search a model": "Pretraži model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Pretraži razgovore", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Pretražite modele", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Pretraga prompta", "Search Result Count": "Broj rezultata pretraživanja", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Alati za pretraživanje", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1840,7 +1990,6 @@ "Seed": "Sjeme", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Odabir osnovnog modela", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Odaberite pogon", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Pošalji", "Send a Message": "Pošaljite poruku", + "Send events for": "", "Send message": "Pošalji poruku", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Septembar", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API ključ", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API ključ", "Serpstack API Key": "Serpstack API API ključ", "Server connection failed": "", "Server connection verified": "Veza s poslužiteljem potvrđena", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Postavi kao zadano", "Set as Production": "", "Set embedding model": "", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Podijeli u OpenWebUI zajednici", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Pokaži", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Izvor", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Pogreška prepoznavanja govora: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "STT postavke", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sustav", + "System events only": "", "System Instructions": "", "System Prompt": "Sistemski prompt", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Stroj za pretvorbu teksta u govor", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ovo je eksperimentalna značajka, možda neće funkcionirati prema očekivanjima i podložna je promjenama u bilo kojem trenutku.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Danas", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2191,14 +2361,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "Ažuriraj i kopiraj vezu", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "Ažuriraj lozinku", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "korisnik", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Korisnici", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "varijabla", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Verzija", @@ -2283,11 +2465,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "Internet pretraga", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Web tražilica", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL webkuke", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI postavke", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Jučer", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vi", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index 61899e8141..149f870d2e 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -9,31 +9,42 @@ "[Today at] h:mm A": "[Avui a les] h:mm A", "[Yesterday at] h:mm A": "[Ahir a les] h:mm A", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Skills": "", + "{{COUNT}} Available Skills": "{{COUNT}} habilitats disponibles", "{{COUNT}} Available Tools": "{{COUNT}} eines disponibles", "{{COUNT}} characters": "{{COUNT}} caràcters", "{{COUNT}} extracted lines": "{{COUNT}} línies extretes", "{{COUNT}} files": "{{COUNT}} arxius", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "{{count}} fitxer seleccionat. Només es penjaran els fitxers nous i modificats. Els fitxers suprimits s'eliminaran. L'estructura de carpetes es duplicarà. Continuar?", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "{{count}} fitxers seleccionats. Només es penjaran els fitxers nous i modificats. Els fitxers suprimits s'eliminaran. L'estructura de carpetes es duplicarà. Continuar?", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "{{count}} fitxers seleccionats. Només es penjaran els fitxers nous i modificats. Els fitxers suprimits s'eliminaran. L'estructura de carpetes es duplicarà. Continuar?", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} línies ocultes", "{{COUNT}} members": "{{COUNT}} membres", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_many": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}} de {{total}} accessible", + "{{count}} of {{total}} accessible_many": "{{count}} de {{total}} accessibles", + "{{count}} of {{total}} accessible_other": "{{count}} de {{total}} accessibles", "{{COUNT}} Replies": "{{COUNT}} respostes", "{{COUNT}} Rows": "{{COUNT}} files", "{{count}} selected_one": "{{count}} seleccionat", "{{count}} selected_many": "{{count}} seleccionats", "{{count}} selected_other": "{{count}} seleccionats", "{{COUNT}} Sources": "{{COUNT}} fonts", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} paraules", "{{COUNT}}d_time_ago": "{{COUNT}}d", "{{COUNT}}h_time_ago": "{{COUNT}}h", "{{COUNT}}m_time_ago": "{{COUNT}}m", "{{COUNT}}w_time_ago": "{{COUNT}}s", "{{COUNT}}y_time_ago": "{{COUNT}}a", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} a les {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "La descàrrega del model {{model}} s'ha cancel·lat", "{{modelName}} profile image": "Imatge del perfil {{modelName}}", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Els xats de {{user}}", "{{webUIName}} Backend Required": "El Backend de {{webUIName}} és necessari", "*Prompt node ID(s) are required for image generation": "*Els identificadors de nodes d'indicacions són necessaris per a la generació d'imatges", + "1 group": "", "1 hour before": "1 hora abans", "1 Source": "1 font", + "1 user": "", "10 minutes before": "10 minuts abans", "15 minutes before": "15 minuts abans", "1m_time_ago": "1m", @@ -60,6 +73,7 @@ "Access Control": "Control d'accés", "Access Grants": "Assignacions d'accés", "Access List": "Llista d'accés", + "Access prohibited": "", "Access updated": "Accés actualitzat", "Accessible to all users": "Accessible a tots els usuaris", "Account": "Compte", @@ -75,6 +89,7 @@ "Activity": "Activitat", "Add": "Afegir", "Add a model ID": "Afegir un ID de model", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Afegeix una breu descripció sobre què fa aquest model", "Add a tag": "Afegir una etiqueta", "Add a tag...": "Afegir una etiqueta...", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Afegir indicació personalitzada", "Add description": "Afegir descripció", "Add Details": "Afegir detalls", + "Add durable context for future chats": "", "Add Files": "Afegir arxius", "Add Image": "Afegir imatge", + "Add Knowledge Connection": "", "Add location": "Afegir ubicació", "Add Member": "Afegir membre", "Add Members": "Afegir membres", @@ -103,6 +120,7 @@ "Add to favorites": "Afegir als favorits", "Add User": "Afegir un usuari", "Add User Group": "Afegir grup d'usuaris", + "Add webhook": "", "Add webpage": "Afegir pàgina web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Afegeix l'URL i la clau API de l'Open Terminal a Configuració → Integracions.", "Additional Config": "Configuració addicional", @@ -115,7 +133,9 @@ "Admin": "Administrador", "Admin Contact Email": "Afegir correu electrònic de contacte", "Admin Panel": "Panell d'administració", + "Admin Roles": "", "Admin Settings": "Preferències d'administració", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Els administradors tenen accés a totes les eines en tot moment; els usuaris necessiten eines assignades per model a l'espai de treball.", "Advanced": "Avançat", "Advanced Parameters": "Paràmetres avançats", @@ -126,16 +146,21 @@ "All": "Tots", "All chats have been unarchived.": "Tots els xats han estat desarxivats.", "All day": "Tot el dia", + "All events": "", "All models are now hidden": "Tots els models estan amagats, ara", "All models are now visible": "Tots els models són visibles, ara", "All models deleted successfully": "Tots els models s'han eliminat correctament", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Sempre", "All Users": "Tots els usuaris", + "All users and system events": "", "Allow Call": "Permetre la trucada", "Allow Chat Controls": "Permetre els controls de xat", "Allow Chat Delete": "Permetre eliminar el xat", "Allow Chat Edit": "Permetre editar el xat", "Allow Chat Export": "Permetre exportar el xat", + "Allow Chat Import": "", "Allow Chat Params": "Permetre els paràmetres de xat", "Allow Chat Share": "Permetre compartir el xat", "Allow Chat System Prompt": "Permet la indicació de sistema al xat", @@ -155,9 +180,11 @@ "Allow User Location": "Permetre la ubicació de l'usuari", "Allow Voice Interruption in Call": "Permetre la interrupció de la veu en una trucada", "Allow Web Upload": "Permetre la pujada web", + "Allowed Domains": "", "Allowed Endpoints": "Punts d'accés permesos", "Allowed File Extensions": "Extensions de fitxer permeses", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Extensions de fitxer permeses per a la càrrega. Separa múltiples extensions amb comes. Deixa buit per a tots els tipus de fitxer.", + "Allowed Roles": "", "Already have an account?": "Ja tens un compte?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa al top_p, i pretén garantir un equilibri de qualitat i varietat. El paràmetre p representa la probabilitat mínima que es consideri un token, en relació amb la probabilitat del token més probable. Per exemple, amb p=0,05 i el token més probable amb una probabilitat de 0,9, es filtren els logits amb un valor inferior a 0,045.", "Always": "Sempre", @@ -176,6 +203,7 @@ "API Base URL": "URL Base de l'API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL base de l'API per al servei de marcadors de Datalab. Per defecte: https://www.datalab.to/api/v1/marker", "API Key": "clau API", + "API Key / Token": "", "API Key created.": "clau API creada.", "API Key Endpoint Restrictions": "Restriccions del punt d'accés de la Clau API", "API keys": "Claus de l'API", @@ -201,17 +229,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "Estàs segur que vols suprimir tots els xats? Aquesta acció no es pot desfer.", "Are you sure you want to delete this channel?": "Estàs segur que vols eliminar aquest canal?", "Are you sure you want to delete this connection? This action cannot be undone.": "Estàs segur que vols suprimir aquesta connexió? Aquesta acció no es pot desfer.", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "Estàs segur que vols suprimir aquest directori?", "Are you sure you want to delete this memory? This action cannot be undone.": "Estàs segur que vols suprimir aquest record? Aquesta acció no es pot desfer.", "Are you sure you want to delete this message?": "Estàs segur que vols eliminar aquest missatge?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Estàs segur que vols suprimir aquesta versió? Les versions filles es tornaran a enllaçar amb la versió principal d'aquesta versió.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Estàs segur que vols eliminar això", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Estàs segur que vols desarxivar tots els xats arxivats?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Models de l'Arena", "Artifacts": "Artefactes", "Asc": "Ascendent", "Ask": "Preguntar", "Ask a question": "Fer una pregunta", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "Procés d'incrustat asíncron", "At time of event": "Al moment de l'esdeveniment", @@ -226,14 +259,20 @@ "Audio": "Àudio", "August": "Agost", "Auth": "Autenticació", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autenticar", "Authentication": "Autenticació", "Auto": "Automàtic", "Auto (Random)": "Automàtic (aleatori)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copiar la resposta automàticament al porta-retalls", - "Auto-playback response": "Reproduir la resposta automàticament", + "Auto-Create Groups": "", + "Auto-Playback Response": "Reproduir la resposta automàticament", "Autocomplete Generation": "Generació automàtica", "Autocomplete Generation Input Max Length": "Entrada màxima de la generació automàtica", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Cadena d'autenticació de l'API d'AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL Base d'AUTOMATIC1111", @@ -248,9 +287,10 @@ "Automations": "Automatització", "Available list": "Llista de disponibles", "Available models": "Models disponibles", - "Available Skills": "", + "Available Skills": "Habilitats disponibles", "Available Tools": "Eines disponibles", "available users": "usuaris disponibles", + "Available variables": "", "available!": "disponible!", "Away": "Absent", "Awful": "Terrible", @@ -261,16 +301,17 @@ "Bad Response": "Resposta errònia", "Banners": "Banners", "Base Model (From)": "Model base (des de)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "La memòria cau de la llista de models base accelera l'accés obtenint els models base només a l'inici o en desar la configuració; és més ràpid, però és possible que no mostri els canvis recents del model base.", "Bearer": "Bearer", "before": "abans", "Being lazy": "Essent mandrós", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Punt de connexió a Bing Search V7", "Bing Search V7 Subscription Key": "Clau de subscripció a Bing Search V7", "Bio": "Bio", "Birth Date": "Data de naixement", + "Blocked Groups": "", "BM25 Weight": "Pes BM25", "Bocha Search API Key": "Clau API de Bocha Search", "Bold": "Negreta", @@ -327,7 +368,7 @@ "Chat Completions": "Completacions de xat", "Chat Conversation": "Conversa de xat", "Chat deleted.": "Xat eliminat.", - "Chat direction": "Direcció del xat", + "Chat Direction": "Direcció del xat", "Chat exported successfully": "El xat s'ha exportat correctament", "Chat History": "Historial de xats", "Chat ID": "ID del xat", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Canal de col·laboració on la gent s'uneix com a membres", "Collapse": "Col·lapsar", "Collection": "Col·lecció", + "Collection Field": "", "Collections": "Col·lecccions", "Color": "Color", "ComfyUI": "ComfyUI", @@ -408,18 +450,20 @@ "ComfyUI Workflow": "Flux de treball de ComfyUI", "ComfyUI Workflow Nodes": "Nodes del flux de treball de ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "Identificadors de node separats per comes (p. ex. 1 o 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Llista separada per comes d'extensions de fitxer que MinerU gestionarà (per exemple, pdf, docx, pptx, xlsx)", "command": "comanda", "Command": "Comanda", "Comment": "Comentari", "Commit Message": "Enviar el missatge", "Community Reviews": "Comentaris de la comunitat", - "Comparing with knowledge base...": "", + "Compacting context": "", + "Comparing with knowledge base...": "Comparant amb la base de coneixement...", "Completions": "Completaments", "Compress Images in Channels": "Comprimir imatges en els canals", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_many": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Càlcul de sumes de verificació ({{count}} fitxer)", + "Computing checksums ({{count}} files)_many": "Càlcul de sumes de verificació ({{count}} fitxers)", + "Computing checksums ({{count}} files)_other": "Càlcul de sumes de verificació ({{count}} fitxers)", "Concurrent Requests": "Peticions simultànies", "Config": "Configuració", "Config imported successfully": "Configuració importada correctament", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Connecta't a instàncies d'Open Terminal. Tots els usuaris tindran accés a la navegació de fitxers i a les eines del terminal a través d'aquests servidors.", "Connect to your own OpenAI compatible API endpoints.": "Connecta als teus propis punts de connexió de l'API compatible amb OpenAI", "Connect to your own OpenAPI compatible external tool servers.": "Connecta als teus propis servidors d'eines externs compatibles amb OpenAPI", + "Connected": "", "Connected ({{type}})": "Connectat ({{type}})", "Connection failed": "La connexió ha fallat", "Connection lost. Reconnecting...": "Connexió perduda. Reconnectant...", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Posa't en contacte amb l'administrador per accedir a WebUI", "Content": "Contingut", "Content Extraction Engine": "Motor d'extracció de contingut", + "Content Field": "", "Content lengths (character counts only)": "Mida del contingut (només els caràcters)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Tokens de context", + "Continue": "", "Continue Response": "Continuar la resposta", "Continue with {{provider}}": "Continuar amb {{provider}}", "Continue with Email": "Continuar amb el correu", @@ -497,6 +550,7 @@ "Create new secret key": "Crear una nova clau secreta", "Create note": "Crear una nota", "Create Note": "Crea nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Crea sol·licituds programades que s'executin automàticament de manera recurrent.", "Create your first note by clicking on the plus button below.": "Crea la teva primera nota prement sobre el botó 'més' inferior", "Created at": "Creat el", @@ -514,6 +568,7 @@ "Custom Gender": "Gènere personalitzat", "Custom Parameter Name": "Nom del paràmetre personalitzat", "Custom Parameter Value": "Valor del paràmetre personalitzat", + "Custom range": "", "Daily": "Cada dia", "Daily Messages": "Missatges diaris", "Danger Zone": "Zona de perill", @@ -536,7 +591,6 @@ "Default Features": "Característiques per defecte", "Default Filters": "Filres per defecte", "Default Group": "Grup per defecte", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "El mode predeterminat funciona amb una gamma més àmplia de models cridant a les eines una vegada abans de l'execució. El mode natiu aprofita les capacitats de crida d'eines integrades del model, però requereix que el model admeti aquesta funció de manera inherent.", "Default Model": "Model per defecte", "Default model updated": "Model per defecte actualitzat", "Default permissions": "Permisos per defecte", @@ -546,20 +600,21 @@ "Default to ALL": "Per defecte TOTS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Per defecte, Segmented Retrieval per a l'extracció de contingut rellevant, es recomana en la majoria dels casos.", "Default User Role": "Rol d'usuari per defecte", + "Default webhook": "", "Defaults": "Valors per defecte", "Delete": "Eliminar", "Delete {{name}}": "Eliminar {{name}}", "Delete a model": "Eliminar un model", "Delete All": "Eliminar tot", "Delete All Chats": "Eliminar tots els xats", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Eliminar tot el contingut d'aquesta carpeta", "Delete all contents inside this folder": "Eliminar tot el contingut d'aquesta carpeta", "Delete automation?": "Eliminar l'automatització", "Delete calendar": "Eliminar el calendari", "Delete Calendar": "Eliminar el calendari", "Delete Chat": "Eliminar xat", "Delete chat?": "Eliminar el xat?", - "Delete directory?": "", + "Delete directory?": "Eliminar la carpeta?", "Delete Event": "Eliminar l'esdeveniment", "Delete File": "Eliminar el fitxer", "Delete folder?": "Eliminar la carpeta?", @@ -596,16 +651,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Les connexions directes permeten als usuaris connectar-se als seus propis endpoints d'API compatibles amb OpenAI.", "Direct Message": "Missatge directe", "Direct Tool Servers": "Servidors d'eines directes", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Carpeta creada", + "Directory deleted.": "Carpeta eliminada", + "Directory moved.": "Carpeta desada", + "Directory name": "Nom de la carpeta", + "Directory renamed.": "Carpeta reanomenada", "Directory selection was cancelled": "La selecció de directori s'ha cancel·lat", "Disable All": "Deshabilitar tot", "Disable Code Interpreter": "Deshabilitar l'interpret de codi", "Disable Image Extraction": "Deshabilitar l'extracció d'imatges", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Desactiva l'extracció d'imatges del PDF. Si Utilitza LLM està habilitat, les imatges es descriuran automàticament. Per defecte és Fals.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Deshabilitat", "Disconnect OAuth": "Desconnectar OAuth", "Discover a function": "Descobrir una funció", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Descobrir, descarregar i explorar models preconfigurats", "Discussion channel where access is based on groups and permissions": "Canal de discussió on l'accés es basa en grups i permisos", "Display": "Mostrar", - "Display chat title in tab": "Mostrar el títol del xat a la pestanya", + "Display Chat Title in Tab": "Mostrar el títol del xat a la pestanya", "Display Emoji in Call": "Mostrar emojis a la trucada", "Display Multi-model Responses in Tabs": "Mostrar respostes multi-model a les pestanyes", - "Display the username instead of You in the Chat": "Mostrar el nom d'usuari en lloc de 'Tu' al xat", + "Display the Username Instead of You in the Chat": "Mostrar el nom d'usuari en lloc de 'Tu' al xat", "Displays citations in the response": "Mostra les referències a la resposta", "Displays status updates (e.g., web search progress) in the response": "Mostra actualitzacions d'estat (per exemple, progrés de la cerca web) a la resposta", "Dive into knowledge": "Aprofundir en el coneixement", @@ -634,6 +691,7 @@ "Docling Parameters": "Paràmetres de Docling", "Docling Server URL required.": "La URL del servidor Docling és necessària", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Es necessita un punt de connexió de Document Intelligence", "Document Intelligence Model": "Model de Document Intelligence", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Editar el permisos per defecte", "Edit Folder": "Editar la carpeta", "Edit Image": "Editar la imatge", + "Edit Knowledge Connection": "", "Edit Last Message": "Editar el darrer missatge", "Edit Memory": "Editar la memòria", "Edit Prompt": "Editar la indicació", "Edit Terminal Connection": "Editar la connexió al terminal", "Edit User": "Editar l'usuari", "Edit User Group": "Editar el grup d'usuaris", + "Edit webhook": "", "Edit workflow.json content": "Editar el contingut de workflow.json", "edited": "editat", "Edited": "Editat", @@ -703,14 +763,16 @@ "Eject model": "Expulsar el model", "ElevenLabs": "ElevenLabs", "Email": "Correu electrònic", + "Email Claim": "", "Embark on adventures": "Embarcar en aventures", "Embedding": "Incrustació", "Embedding Batch Size": "Mida del lot d'incrustació", "Embedding Concurrent Requests": "Peticions concurrents d'incrustació", "Embedding Model": "Model d'incrustació", "Embedding Model Engine": "Motor de model d'incrustació", - "Emoji": "", + "Emoji": "Emoji", "Emojis": "Emojis", + "Empty": "", "Empty message": "Missatge buit", "Enable All": "Habilitar tot", "Enable API Keys": "Permetre claus API", @@ -718,22 +780,27 @@ "Enable Code Execution": "Permetre l'execució de codi", "Enable Code Interpreter": "Activar l'intèrpret de codi", "Enable Community Sharing": "Activar l'ús compartit amb la comunitat", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Activar el bloqueig de memòria (mlock) per evitar que les dades del model s'intercanviïn fora de la memòria RAM. Aquesta opció bloqueja el conjunt de pàgines de treball del model a la memòria RAM, assegurant-se que no s'intercanviaran al disc. Això pot ajudar a mantenir el rendiment evitant errors de pàgina i garantint un accés ràpid a les dades.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Activar l'assignació de memòria (mmap) per carregar les dades del model. Aquesta opció permet que el sistema utilitzi l'emmagatzematge en disc com a extensió de la memòria RAM tractant els fitxers de disc com si estiguessin a la memòria RAM. Això pot millorar el rendiment del model permetent un accés més ràpid a les dades. Tanmateix, és possible que no funcioni correctament amb tots els sistemes i pot consumir una quantitat important d'espai en disc.", "Enable Message Queue": "Activar la cua de missatges", "Enable Message Rating": "Permetre la qualificació de missatges", "Enable Mirostat sampling for controlling perplexity.": "Permetre el mostreig de Mirostat per controlar la perplexitat", "Enable New Sign Ups": "Permetre nous registres", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Activar, desactivar o personalitzar les etiquetes de raonament que utilitza el model. \"Activat\" utilitza etiquetes predeterminades, \"Desactivat\" desactiva les etiquetes de raonament i \"Personalitzat\" permet especificar les etiquetes d'inici i finalització.", "Enabled": "Habilitat", "End Tag": "Etiqueta de finalització", + "Endpoint": "", "Endpoint URL": "URL de connexió", "Enforce Temporary Chat": "Forçar els xats temporals", "Enhance": "Millorar", "Enrich Hybrid Search Text": "Enriquir el text de cerca híbrid", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que els teus fitxers CSV inclouen 4 columnes en aquest ordre: Nom, Correu electrònic, Contrasenya, Rol.", "Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}", - "Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu què els teus models de llenguatge puguin recordar", "Enter a title for the pending user info overlay. Leave empty for default.": "Introdueix un títol per a la finestra de dades d'usuari pendent. Deixa buit per a valor per defecte.", "Enter a watermark for the response. Leave empty for none.": "Introdueix una marca d'aigua per a la resposta. Deixa-ho buit per a cap.", "Enter additional headers in JSON format": "Introdueix capçaleres addicionals en format JSON", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Introdueix la mida mínima del bloc objectiu", "Enter Chunk Overlap": "Introdueix la mida de solapament de blocs", "Enter Chunk Size": "Introdueix la mida del bloc", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Introdueix parelles de \"token:valor de biaix\" separats per comes (exemple: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Introdueix el contingut per a la finestra de dades d'usuari pendent. Deixa-ho buit per a valor per defecte.", "Enter coordinates (e.g. 51.505, -0.09)": "Entra les coordenades (p. ex. 51.505, -0.09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Introdueix la URL de Jupyter", "Enter Kagi Search API Key": "Introdueix la clau API de Kagi Search", "Enter Key Behavior": "Introdueix el comportament de clau", + "Enter language": "", "Enter language codes": "Introdueix els codis de llenguatge", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Entra la clau API per a Linkup", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Introdueix la clau API de MinerU", "Enter Mistral API Base URL": "Entra la URL Base de l'API de Mistral", "Enter Mistral API Key": "Entra la clau API de Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "Introdueix el prompt aquí.", "Enter proxy URL (e.g. https://user:password@host:port)": "Entra la URL (p. ex. https://user:password@host:port)", "Enter reasoning effort": "Introdueix l'esforç de raonament", + "Enter Redirect URI": "", "Enter Score": "Introdueix la puntuació", "Enter SearchApi API Key": "Introdueix la clau API SearchApi", "Enter SearchApi Engine": "Introdueix el motor SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Introdueix la clau API SerpApi", "Enter SerpApi Engine": "Introdueix el motor API SerpApi", "Enter Serper API Key": "Introdueix la clau API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Introdueix la clau API Serply", "Enter Serpstack API Key": "Introdueix la clau API Serpstack", "Enter server host": "Introdueix el servidor", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Introdueix la URL del servidor Tika", "Enter timeout in seconds": "Entra el temps d'espera en segons", "Enter to Send": "Enter per enviar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Introdueix Top K", "Enter Top K Reranker": "Introdueix el Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix la URL (p. ex. http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Error: Ja existeix un model amb l'ID '{{modelId}}'. Selecciona un ID diferent per continuar.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Error: ID de model no pot ser buit. Entra un ID de model vàlid per continuar.", "Evaluations": "Avaluacions", + "Event": "", "Event created": "Esdeveniment creat", "Event deleted": "Esdeveniment eliminat", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Títol de l'esdeveniment", "Event updated": "Esdeveniment actualitzat", + "Events": "", "Exa API Key": "Clau API d'EXA", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemple: TOTS", "Example: mail": "Exemple: mail", @@ -909,12 +989,18 @@ "Export Config": "Exportar la configuració", "Export Models": "Exportar els models", "Export Prompts": "Exportar les indicacions", + "Export Skills": "", "Export to CSV": "Exportar a CSV", "Export Tools": "Exportar les eines", "Export Users": "Exportar els usuaris", "External": "Extern", + "External connection not found.": "", "External Document Loader URL required.": "Fa falta la URL per a Document Loader", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Model de tasques extern", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Clau API d'External Web Loader", "External Web Loader URL": "URL d'External Web Loader", "External Web Search API Key": "Clau API d'External Web Search", @@ -925,13 +1011,14 @@ "Failed to archive chat.": "No s'ha pogut arxivar el xat", "Failed to attach file": "No s'ha pogut adjuntar l'arxiu", "Failed to clear status": "No s'ha pogut esborar l'estat", - "Failed to compare files.": "", + "Failed to compare files.": "No s'han pogut comparar els arxius.", "Failed to connect to {{URL}} OpenAPI tool server": "No s'ha pogut connecta al servidor d'eines OpenAPI {{URL}}", "Failed to connect to {{URL}} terminal server": "No s'ha pogut connecta al servidor de terminal {{URL}}", "Failed to copy link": "No s'ha pogut copiar l'enllaç", "Failed to create API Key.": "No s'ha pogut crear la clau API.", "Failed to delete calendar": "No s'ha pogut eliminar el calendari", "Failed to delete note": "No s'ha pogut eliminar la nota", + "Failed to delete webhook": "", "Failed to disconnect": "No s'ha pogut desconnectar", "Failed to download image": "No s'ha pogut descarregar la imatge", "Failed to extract content from the file: {{error}}": "No s'ha pogut extreure el contingut del fitxer: {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "No s'han pogut obtenir els models", "Failed to generate title": "No s'ha pogut generar el títol", "Failed to import models": "No s'han pogut importar el models", + "Failed to load chat": "", "Failed to load chat preview": "No s'ha pogut carregar la previsualització del xat", "Failed to load DOCX file. Please try downloading it instead.": "No s'ha pogut carregar el fitxer DOCX. Si us plau, prova de descarregar-lo.", "Failed to load Excel/CSV file. Please try downloading it instead.": "No s'ha pogut carregar el fitxer Excel/CSV. Si us plau, prova de descarregar-lo.", @@ -948,6 +1036,7 @@ "Failed to move chat": "No s'ha pogut moure el xat", "Failed to process URL: {{url}}": "No s'ha pogut processar la URL: {{url}}", "Failed to read clipboard contents": "No s'ha pogut llegir el contingut del porta-retalls", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "No s'ha pogut eliminar el membre", "Failed to render diagram": "No s'ha pogut renderitzar el diagrama", "Failed to render visualization": "No s'ha pogut renderitzar la visualització", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "No s'ha pogut desar la configuració dels models", "Failed to save policy: {{error}}": "No s'ha pogut desar la política: {{error}}", "Failed to save terminal servers": "No s'han pogut desar els servidors de terminal", + "Failed to save webhook": "", "Failed to unshare chat.": "No s'ha pogut deixar de compartir el xat.", "Failed to update settings": "No s'han pogut actualitzar les preferències", "Failed to update status": "No s'ha pogut actualitzar l'estat", + "Failed to update webhook": "", "Failed to upload file.": "No s'ha pogut pujar l'arxiu.", "Features": "Característiques", "Features Permissions": "Permisos de les característiques", @@ -979,18 +1070,20 @@ "File content updated successfully.": "El contingut de l'arxiu s'ha actualitzat correctament.", "File Context": "Contingut de l'arxiu", "File deleted successfully.": "L'arxiu s'ha eliminat correctament", - "File Extensions": "", + "File Extensions": "Extensions d'arxiu", "File Mode": "Mode d'arxiu", - "File moved.": "", + "File moved.": "Arxius moguts", "File name": "Nom d'arxiu", "File not found.": "No s'ha trobat l'arxiu.", "File removed successfully.": "Arxiu eliminat correctament.", - "File renamed.": "", + "File renamed.": "Arxiu reanomenat.", "File size should not exceed {{maxSize}} MB.": "La mida del fitxer no ha de superar els {{maxSize}} MB.", "File Upload": "Pujar arxiu", "File uploaded successfully": "Arxiu pujat satisfactòriament", "Filename": "Nom de l'arxiu", "Files": "Arxius", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtre", "Filter is now globally disabled": "El filtre ha estat desactivat globalment", "Filter is now globally enabled": "El filtre ha estat activat globalment", @@ -1013,6 +1106,7 @@ "Folder options": "Opcions de la carpeta", "Folder updated successfully": "Carpeta actualitazda correctament", "Folders": "Carpetes", + "Folders Sharing": "", "Follow up": "Seguir", "Follow Up Generation": "Generació d'indicacions de continuació", "Follow Up Generation Prompt": "Indicació per a la generació d'indicacions de continuació", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "La funció ha estat activada globalment", "Function Name": "Nom de la funció", "Function Name Filter List": "Llista de filtres de noms de funció", + "Function starter": "", "Function updated successfully": "La funció s'ha actualitzat correctament", "Functions": "Funcions", "Functions allow arbitrary code execution.": "Les funcions permeten l'execució de codi arbitrari.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Graella", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Canal de grup", + "Group Claim": "", "Group created successfully": "El grup s'ha creat correctament", "Group deleted successfully": "El grup s'ha eliminat correctament", "Group Description": "Descripció del grup", @@ -1087,6 +1185,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Retorn hàptic", + "Header variables": "", "Headers": "Capçaleres", "Headers must be a valid JSON object": "Les capçaleres han de ser un objecte JSON vàlid", "Height": "Alçada", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "L'ID no pot contenir caràcters \":\" ni \"|\"", "ID copied to clipboard": "L'ID s'ha copiat al portaretalls", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Temps d'espera d'inactivitat", "iframe Sandbox Allow Forms": "Permetre formularis sandbox iframe", "iframe Sandbox Allow Same Origin": "Permetre same-origin sandbox iframe", @@ -1142,6 +1243,7 @@ "Import From Link": "Importar des d'un enllaç", "Import Models": "Importar models", "Import Prompts": "Importar indicacions", + "Import Skills": "", "Import successful": "Importació correcta", "Import Tools": "Importar eines", "Important Update": "Actualització important", @@ -1199,12 +1301,11 @@ "Keep in Sidebar": "Mantenir a la barra lateral", "Key": "Clau", "Key is required": "La clau és necessària", - "Keyboard shortcuts": "Dreceres de teclat", "Keyboard Shortcuts": "Dreceres de teclat", "Knowledge": "Coneixement", "Knowledge Access": "Accés al coneixement", "Knowledge Base": "Base de coneixement", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "La base de coneixement s'ha reiniciat", "Knowledge created successfully.": "Coneixement creat correctament.", "Knowledge deleted successfully.": "Coneixement eliminat correctament.", "Knowledge Description": "Descripció del coneixement", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Nom del coneixement", "Knowledge Public Sharing": "Compartir públicament el Coneixement", "Knowledge Sharing": "Compartir el coneixement", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Coneixement actualitzat correctament.", "Kokoro.js (Browser)": "Kokoro.js (Navegador)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1228,7 +1331,6 @@ "Last ran": "Darrera execució", "Last reply": "Darrera resposta", "LDAP": "LDAP", - "LDAP server updated": "Servidor LDAP actualitzat", "Leaderboard": "Tauler de classificació", "Learn more": "Aprèn-ne més", "Learn More": "Aprendre'n més", @@ -1250,11 +1352,12 @@ "Legacy": "Llegat", "lexical": "lèxic", "License": "Llicència", + "Lifecycle JSON": "", "Lift List": "Aixecar la llista", "Light": "Clar", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limita les consultes de cerca simultànies. 0 = il·limitada (per defecte). Estableix-ho a 1 per a l'execució seqüencial (recomanat per a API amb límits de velocitat estrictes com el nivell gratuït de Brave).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Limita el nombre de sol·licituds d'incrustació simultànies. Estableix-ho a 0 per a un nombre il·limitat.", - "Linkup API Key": "", + "Linkup API Key": "Clau API de Linkup", "List": "Llista", "List calendars, search, create, update, and delete calendar events": "Llistar calendaris, cercar, crear, actualitzar i suprimir esdeveniments de calendari", "Listening...": "Escoltant...", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Accés a la ubicació no permesa", "Lost": "Perdut", "Low": "Baix", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Creat per la Comunitat OpenWebUI", "Make password visible in the user interface": "Fer que la contrasenya sigui visible a la interficie d'usuari", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gestionar les Pipelines", "Manage Tool Servers": "Gestionar els servidors d'eines", "Manage your account information.": "Gestionar la informació del teu compte.", + "Mapped Source": "", "March": "Març", "Markdown": "Markdown", "Markdown Header Text Splitter": "Divisor de text de capçalera de Markdown", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memòria eliminada correctament", "Memory deleted successfully": "Memòria eliminada correctament", "Memory updated successfully": "Memòria actualitzada correctament", + "Merge Accounts by Email": "", "Merge Responses": "Fusionar les respostes", "Merged Response": "Resposta combinada", "Message": "Missatge", @@ -1326,9 +1432,12 @@ "messages": "missatges", "Messages": "Missatges", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Els missatges enviats després de crear el teu enllaç no es compartiran. Els usuaris amb la URL podran veure el xat compartit.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personal)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (feina/escola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "mínim", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "És necessària la clau API de MinerU pel mode Cloud API", @@ -1381,6 +1490,7 @@ "Models Sharing": "Compartir els models", "Mojeek": "Mojeek", "Mojeek Search API Key": "Clau API de Mojeek Search", + "Monday – Friday": "", "Month": "Mes", "Monthly": "Cada mes", "More": "Més", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Anomena la teva base de coneixement", "Name, prompt, and model are required": "Nom, indicació i model són necessaris", "Native": "Natiu", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Mai", "New": "Nou", "New Automation": "Nova automatització", @@ -1405,8 +1516,8 @@ "New calendar": "Nou calendari", "New Calendar": "Nou calendari", "New Chat": "Nou xat", - "New directory": "", - "New Directory": "", + "New directory": "Nova carpeta", + "New Directory": "Nova carpeta", "New Event": "Nou esdeveniment", "New File": "Nou arxiu", "New Folder": "Nova carpeta", @@ -1427,6 +1538,7 @@ "Next run": "Següent execució", "No access grants. Private to you.": "Sense permisos d'accés. Privat per a tu.", "No activity data": "No hi ha dades d'activitat", + "No additional headers are sent unless configured.": "", "No authentication": "Sense autenticació", "No automations found": "No s'ha trobat cap automatització", "No chats found": "No s'han trobat xats", @@ -1439,8 +1551,10 @@ "No data": "No hi ha dades", "No data found": "No s'han trobat dades", "No distance available": "No hi ha distància disponible", + "No event webhooks configured.": "", "No execution logs available yet": "No hi ha registres d'execució encara", "No expiration can pose security risks.": "No posar expiració pot suposar problemes de seguretat.", + "No external knowledge sources configured.": "", "No feedback found": "No s'ha trobat cap retorn", "No file selected": "No s'ha escollit cap fitxer", "No files found": "No s'han trobat arxius", @@ -1452,13 +1566,13 @@ "No HTML, CSS, or JavaScript content found.": "No s'ha trobat contingut HTML, CSS o JavaScript.", "No inference engine with management support found": "No s'ha trobat un motor d'inferència amb suport de gestió", "No kernel": "No hi ha cap kernel", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "No hi ha cap base de coneixement disponible", "No knowledge bases found.": "No s'han trobat bases de coneixement.", "No knowledge found": "No s'ha trobat Coneixement", "No limit": "Sense límit", "No memories to clear": "No hi ha memòries per netejar", "No model IDs": "No hi ha IDs de model", - "No models accessible": "", + "No models accessible": "No hi ha models accessibles", "No models available": "No hi ha models disponibles", "No models found": "No s'han trobat models", "No models selected": "No s'ha seleccionat cap model", @@ -1468,6 +1582,7 @@ "No output items": "No hi ha element de sortida", "No pinned messages": "No hi ha missatges fixats", "No prompts found": "No s'han trobat indicacions", + "No Repeat": "", "No results": "No s'han trobat resultats", "No results found": "No s'han trobat resultats", "No search query generated": "No s'ha generat cap consulta", @@ -1479,7 +1594,7 @@ "No Terminal connection configured.": "No hi ha cap configuració de terminal configurada.", "No terminal connections configured.": "No hi ha connexions de terminal configurades.", "No tool server connections configured.": "No hi ha connexions a servidors d'eines configurades.", - "No tools accessible": "", + "No tools accessible": "No hi ha eines accessibles", "No tools found": "No s'han trobat eines", "No users were found.": "No s'han trobat usuaris", "No valves": "No hi ha valves", @@ -1487,6 +1602,7 @@ "No webhooks yet": "No hi ha webhooks encara", "Node Ids": "Id de nodes", "None": "Cap", + "Not configured": "", "Not factually correct": "No és clarament correcte", "Not helpful": "No ajuda", "Not Registered": "No registrat", @@ -1502,24 +1618,29 @@ "Notifications": "Notificacions", "November": "Novembre", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Estàtic)", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL del servidor OAuth", "OAuth session disconnected": "Sessió OAuth desconnectada", "October": "Octubre", "Off": "Desactivat", "Okay, Let's Go!": "D'acord, som-hi!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Fosc", "Ollama": "Ollama", "Ollama API": "API d'Ollama", "Ollama API settings updated": "La configuració de l'API d'Ollama s'ha actualitzat", "Ollama Cloud API Key": "Clau API d'Ollama Cloud", "Ollama Version": "Versió d'Ollama", + "Omit": "", "On": "Activat", "Once": "Una vegada", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Només actiu en le mode de Veu.", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Només està actiu quan l'opció \"Enganxa text gran com a fitxer\" està activada.", "Only active when the chat input is in focus and an LLM is generating a response.": "Només s'activa quan l'entrada del xat està en focus i un LLM està generant una resposta.", "Only active when the chat input is in focus.": "Només actiu quan l'entrada del xat està en focus.", @@ -1586,26 +1707,30 @@ "Password": "Contrasenya", "Passwords do not match.": "Les contrasenyes no coincideixen", "Paste Large Text as File": "Enganxa un text llarg com a fitxer", + "Path": "", "Path copied": "Camí copiat", "Paused": "Pausat", "PDF document (.pdf)": "Document PDF (.pdf)", "PDF Extract Images (OCR)": "Extreu imatges del PDF (OCR)", "PDF Loader Mode": "Mode de càrrega de PDF", - "pdf, docx, pptx, xlsx": "", + "pdf, docx, pptx, xlsx": "pdf, docx, pptx, xlsx", "pending": "pendent", "Pending": "Pendent", + "Pending Accounts": "", "Pending User Overlay Content": "Contingut de la finestra d'usuari pendent", "Pending User Overlay Title": "Títol de la finestra d'usuari pendent", "Permission denied when accessing media devices": "Permís denegat en accedir a dispositius multimèdia", "Permission denied when accessing microphone": "Permís denegat en accedir al micròfon", "Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}", "Permissions": "Permisos", + "Permissions reset to defaults": "", "Perplexity API Key": "Clau API de Perplexity", "Perplexity Model": "Model de Perplexity", "Perplexity Search API URL": "URL API per a Perplexity Search", "Perplexity Search Context Usage": "Utilització del context de cerca de Perplexity", "Persistent": "Persistent", "Personalization": "Personalització", + "Picture Claim": "", "Pin": "Fixar", "Pin to Sidebar": "Fixar a la barra lateral", "Pinned": "Fixat", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Emplena tots els camps, si us plau.", "Please register the OAuth client": "Si us plau, registra el client OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Si us plau, desa la connexió per conservar la informació del client OAuth i no canviïs l'ID.", - "Please select a model first.": "Si us plau, selecciona un model primer", "Please select a model.": "Si us plau, selecciona un model.", "Please select a reason": "Si us plau, selecciona una raó", "Please select a valid JSON file": "Si us plau, selecciona un arxiu JSON vàlid", "Please select at least one user for Direct Message channel.": "Selecciona com a mínim un usuari per al canal de missatge directe.", "Please wait until all files are uploaded.": "Si us plau, espera fins que s'hagin carregat tots els fitxers.", "Policy ID": "ID de política", + "Policy ID is required": "", "Port": "Port", "Ports": "Ports", "Positive attitude": "Actitud positiva", @@ -1653,7 +1778,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "L'identificador de prefix s'utilitza per evitar conflictes amb altres connexions afegint un prefix als ID de model; deixa'l en blanc per desactivar-lo.", "Prevent File Creation": "Prevenir la creació d'arxius", "Preview": "Previsualització", - "Preview Access": "", + "Preview Access": "Previsualitza l'accés", "Previous 30 days": "30 dies anteriors", "Previous 7 days": "7 dies anteriors", "Previous message": "Missatge anterior", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Compartició pública de indicacions", "Prompts Sharing": "Compartir les indicacions", "Provider": "Proveïdor", + "Provider Name": "", + "Provider URL": "", "Public": "Públic", "Pull \"{{searchValue}}\" from Ollama.com": "Obtenir \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obtenir un model d'Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Llegit", "Read Aloud": "Llegir en veu alta", "Read more →": "Llegeix més →", + "Read only": "", "Read Only": "Només lectura", "Read-Only Access": "Accés de només lectura", "Reason": "Raó", "Reasoning Effort": "Esforç de raonament", "Reasoning Tags": "Etiqueta de raonament", "Reasoning text...": "Text de raonament...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Recentment utilitzat", "Reconnected": "Reconnectat", "Record": "Enregistrar", "Record voice": "Enregistrar la veu", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirigint-te a la comunitat OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Redueix la probabilitat de generar ximpleries. Un valor més alt (p. ex. 100) donarà respostes més diverses, mentre que un valor més baix (p. ex. 10) serà més conservador.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Fes referència a tu mateix com a \"Usuari\" (p. ex., \"L'usuari està aprenent espanyol\")", "Reference Chats": "Xats de referència", "Refresh": "Refrescar", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Refusat quan no hauria d'haver estat", "Regenerate": "Regenerar", "Regenerate Menu": "Regenerar el menú", @@ -1731,28 +1867,35 @@ "Remove from favorites": "Eliminar dels favorits", "Remove image": "Eliminar imatge", "Remove Model": "Eliminar el model", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._many": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "Eliminant arxiu obsolet...", + "Removing {{count}} stale files..._many": "Eliminant arxius obsolets...", + "Removing {{count}} stale files..._other": "Eliminant arxius obsolets...", "Rename": "Canviar el nom", "Renamed to {{name}}": "S'ha renombrat a {{name}}", "Render Markdown in Assistant Messages": "Renderitzar el Markdown dels missatges de l'assistent", "Render Markdown in Previews": "Renderitzar el Markdown a les previsualitzacions", "Render Markdown in User Messages": "Renderitzar el Markdown dels missatges de l'usuari", "Reorder Models": "Reordenar els models", + "Repeat": "", "Repeats": "Repeticions", "Reply": "Respondre", "Reply in Thread": "Respondre al fil", "Reply to thread...": "Respondra al fil...", "Replying to {{NAME}}": "Responent a {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "necessari", "Reranking Batch Size": "Mida del lot de reclassificació", "Reranking Engine": "Motor de valoració", "Reranking Model": "Model de reavaluació", + "Research Knowledge": "", "Reset": "Restableix", "Reset All Models": "Restablir tots els models", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Restableix la imatge", - "Reset knowledge base?": "", + "Reset knowledge base?": "Reiniciar la base de coneixement?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Restableix el directori de pujades", "Reset Vector Storage/Knowledge": "Restableix el Repositori de vectors/Coneixement", "Reset view": "Netejar la vista", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "S'ha obtingut una font", "Rich Text Input for Chat": "Entrada de text ric per al xat", "Role": "Rol", + "Roles Claim": "", "RTL": "RTL", "Run": "Executar", "Run All": "Executar tot", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Desar els registres de xat directament a l'emmagatzematge del teu navegador ja no està suportat. Si us plau, descarregr i elimina els registres de xat fent clic al botó de sota. No et preocupis, pots tornar a importar fàcilment els teus registres de xat al backend a través de", "Schedule": "Programar", "Scheduled time must be in the future": "La data d'execucuío ha de ser en el futur", + "Scopes": "", "Scroll On Branch Change": "Fer scroll en canviar de branca", "Scroll to Top": "Anar a dalt", "Search": "Cercar", "Search a model": "Cercar un model", + "Search actions": "", "Search all emojis": "Cercar tots els emojis", "Search and manage user memories": "Cerca i gestiona les memòries d'usuari", "Search and view user chat history": "Cerca i mostra l'historial de xats", @@ -1804,6 +1950,7 @@ "Search Chats": "Cercar xats", "Search Collection": "Cercar col·leccions", "Search Files": "Cerca arxius", + "Search filters": "", "Search Filters": "Filtres de cerca", "search for archived chats": "cercar xats arxivats", "search for folders": "cercar carpetes", @@ -1818,13 +1965,16 @@ "Search Models": "Cercar models", "Search Notes": "Cercar notes", "Search options": "Opcions de cerca", + "Search or add pattern": "", "Search Prompts": "Cercar indicacions", "Search Result Count": "Recompte de resultats de cerca", + "Search skills": "", "Search Skills": "Cerca habilitats", - "Search skills...": "", "Search the internet": "Cercar a internet", "Search the web and fetch URLs": "Cerca la web i obté les URL", + "Search tools": "", "Search Tools": "Cercar eines", + "Search users or groups": "", "Search, view, and manage user notes": "Cerca, mostra i gestiona les notes d'usuari", "SearchApi API Key": "Clau API de SearchApi", "SearchApi Engine": "Motor de SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Llavor", "Select": "Escollir", "Select {{modelName}} model": "Selecciona el model {{modelName}}", - "Select a base model": "Seleccionar un model base", "Select a base model (e.g. llama3, gpt-4o)": "Seleccionar un model base (p. ex. llama3, gpt-4o)", "Select a conversation to preview": "Seleccionar una conversa a previsualitzar", "Select a engine": "Seleccionar un motor", @@ -1878,18 +2027,25 @@ "semantic": "semàntic", "Send": "Enviar", "Send a Message": "Enviar un missatge", + "Send events for": "", "Send message": "Enviar missatge", "Send now": "Enviar ara", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envia `stream_options: { include_usage: true }` a la sol·licitud.\nEls proveïdors compatibles retornaran la informació d'ús del token a la resposta quan s'estableixi.", "September": "Setembre", "SerpApi API Key": "Clau API de SerpApi", "SerpApi Engine": "Motor de SerpApi", "Serper API Key": "Clau API de Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Clau API de Serply", "Serpstack API Key": "Clau API de Serpstack", "Server connection failed": "La connexió al servidor ha fallat", "Server connection verified": "Connexió al servidor verificada", + "Service Account": "", "Session": "Sessió", + "Session expired. Please sign in again.": "", "Set as default": "Establir com a predeterminat", "Set as Production": "Establir com a producció", "Set embedding model": "Establir el model d'incrustació", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "Compartir l'enllaç copiat al portaretalls", "Share to Open WebUI Community": "Compartir amb la comunitat OpenWebUI", "Share your background and interests": "Compartir la teva informació i interessos", + "Shared": "", "Shared Chats": "Xats compartits", "Shared with you": "Compartit amb tu", "Sharing Permissions": "Compartir els permisos", "Show": "Mostrar", - "Show \"What's New\" modal on login": "Veure 'Què hi ha de nou' a l'entrada", + "Show \"What's New\" Modal on Login": "Veure 'Què hi ha de nou' a l'entrada", "Show Admin Details in Account Pending Overlay": "Mostrar els detalls de l'administrador a la superposició del compte pendent", "Show All": "Mostrar tot", "Show all ({{COUNT}} characters)": "Mostra tot ({{COUNT}} caràcters", "Show Files": "Mostra els arxius", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Mostrar la barra de format", "Show image preview": "Mostrar la previsualització de la imatge", "Show Model": "Mostrar el model", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "sID de l'API de Sougou Search", "Sougou Search API SK": "SK de l'API de Sougou Search", "Source": "Font", + "Specific users or groups": "", "Speech Playback Speed": "Velocitat de la parla", "Speech recognition error: {{error}}": "Error de reconeixement de veu: {{error}}", "Speech-to-Text": "Àudio-a-Text", @@ -2006,6 +2165,7 @@ "STT Settings": "Preferències de STT", "Stylized PDF Export": "Exportació en PDF estilitzat", "Su_day_of_week": "Diumenge", + "Sub Claim": "", "Submit question": "Enviar la pregunta", "Submit suggestion": "Enviar un suggeriment", "Subtitle": "Subtítol", @@ -2020,8 +2180,8 @@ "Switch to JSON editor": "Canviar a l'editor JSON", "Switch to visual editor": "Canviar a l'editor visual", "Sync": "Sincronitzar", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Sincronitza una carpeta local amb aquesta base de coneixement. Només es penjaran els fitxers nous i modificats. L'estructura de carpetes es duplicarà.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Sincronització completada: {{added}} afegits, {{modified}} modificats, {{deleted}} suprimits, {{unmodified}} sense modificar", "Sync Complete!": "Sincronia completada", "Sync directory": "Sincronitzar directori", "Sync Failed": "La sincronia ha fallat", @@ -2030,8 +2190,10 @@ "Syncing...": "Sincronitzant", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sincronitza només els xats amb actualitzacions posteriors a la data i hora de l'última sincronització. Desactiva-ho per tornar a sincronitzar tots els xats.", "System": "Sistema", + "System events only": "", "System Instructions": "Instruccions de sistema", "System Prompt": "Indicació del Sistema", + "Table": "", "Tag": "Etiqueta", "Tags": "Etiquetes", "Tags Generation": "Generació d'etiquetes", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Xat temporal per defecte", "Terminal": "Terminal", "Terminal servers saved": "Servidors de terminal desats", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Separador de text", "Text-to-Speech": "Text-a-veu", "Text-to-Speech Engine": "Motor de text a veu", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "L'idiom de l'àudio d'entrada. Proporcionar l'idioma d'entrada en format ISO-639-1 (p. ex. en) millorarà la precisió i la latència. Deixar-ho buit per detectar automàticament el llenguatge.", "The LDAP attribute that maps to the mail that users use to sign in.": "L'atribut LDAP que s'associa al correu que els usuaris utilitzen per iniciar la sessió.", "The LDAP attribute that maps to the username that users use to sign in.": "L'atribut LDAP que mapeja el nom d'usuari amb l'usuari que vol iniciar sessió", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "La classificació està actualment en versió beta i és possible que s'ajustin els càlculs de la puntuació a mesura que es perfeccioni l'algorisme.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "La mida màxima del fitxer en MB. Si la mida del fitxer supera aquest límit, el fitxer no es carregarà.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "El nombre màxim de fitxers que es poden utilitzar alhora al xat. Si el nombre de fitxers supera aquest límit, els fitxers no es penjaran.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Format de sortida per al text. Pot ser 'json', 'markdown' o 'html'. Per defecte és 'markdown'.", @@ -2089,6 +2256,7 @@ "This folder is empty": "Aquesta carpeta està buida", "This is a default user permission and will remain enabled.": "Aquest és un permís d'usuari per defecte i romandrà habilitat.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Aquesta és una funció experimental, és possible que no funcioni com s'espera i està subjecta a canvis en qualsevol moment.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Aquest model no està disponible públicament. Seleccioneu-ne un altre.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Aquesta opció controla quant temps el model romandrà carregat en memòria després de la sol·licitud (per defecte: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Aquesta opció controla quants tokens es conserven en actualitzar el context. Per exemple, si s'estableix en 2, es conservaran els darrers 2 tokens del context de conversa. Preservar el context pot ajudar a mantenir la continuïtat d'una conversa, però pot reduir la capacitat de respondre a nous temes.", @@ -2101,7 +2269,7 @@ "This will delete all models including custom models": "Això eliminarà tots els models incloent els personalitzats", "This will delete all models including custom models and cannot be undone.": "Això eliminarà tots els models incloent els personalitzats i no es pot desfer", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Això eliminarà permanentment el calendari \"{{name}}\" i tots els seus esdeveniments. Aquesta acció no es pot desfer.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Això eliminarà tots els fitxers i carpetes d'aquesta base de coneixement. Aquesta acció no es pot desfer.", "Thorough explanation": "Explicació en detall", "Thought": "Pensament", "Thought for {{DURATION}}": "He pensat durant {{DURATION}}", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Per obtenir més informació sobre els punts d'accés disponibles, visiteu la nostra documentació.", "To select skills here, add them to the \"Skills\" workspace first.": "Per seleccionar habilitats aquí, afegeix-les primer a l'espai de treball \"Habilitats\".", "To select toolkits here, add them to the \"Tools\" workspace first.": "Per seleccionar kits d'eines aquí, afegeix-los primer a l'espai de treball \"Eines\".", - "Toast notifications for new updates": "Notificacions Toast de noves actualitzacions", + "Toast Notifications for New Updates": "Notificacions Toast de noves actualitzacions", "Today": "Avui", "Today at": "Avui a les", "Today at {{LOCALIZED_TIME}}": "Avui a les {{LOCALIZED_TIME}}", @@ -2137,12 +2305,14 @@ "Toggle 1 source": "Activa/Desactiva 1 font", "Toggle details": "Activar/Desactivar els detalls", "Toggle Dictation": "Activa/Desactiva el dictat", - "Toggle Mute": "", + "Toggle Mute": "Activa/Desactiva el silenci", "Toggle Sidebar": "Activa/Desactiva la barra lateral", "Toggle status history": "Activa/Desactiva l'estat de l'històric", "Toggle whether current connection is active.": "Alterna si la connexió actual està activa.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "El nombre de tokens és estimat i pot no reflectir l'ús real de l'API.", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Massa explicit", @@ -2191,14 +2361,19 @@ "Unpin": "Alliberar", "Unpin from Sidebar": "No fixis a la barra lateral", "Unravel secrets": "Descobreix els secrets", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Deixar de compartir el xat", "Unsupported file type.": "Tipus no suportat", "Untagged": "Sense etiquetes", "Untitled": "Sense títol", "Update": "Actualitzar", "Update and Copy Link": "Actualitzar i copiar l'enllaç", + "Update Email": "", "Update for the latest features and improvements.": "Actualitza per a les darreres característiques i millores.", + "Update Name": "", "Update password": "Actualitzar la contrasenya", + "Update Picture": "", "Update your status": "Actualitza el teu estat", "Updated": "Actualitzat", "Updated at": "Actualitzat el", @@ -2216,7 +2391,7 @@ "Upload Progress": "Progrés de càrrega", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progrés de la pujada: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Arxius o imatges pujats", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploading {{current}}/{{total}}: {{file}}": "Pujant {{current}}/{{total}}: {{arxiu}}", "Uploading...": "Pujant...", "URL": "URL", "URL is required": "La URL és necessaria", @@ -2225,22 +2400,28 @@ "Use": "Ús", "Use '#' in the prompt input to load and include your knowledge.": "Utilitza '#' a l'entrada de la indicació per carregar i incloure els teus coneixements.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Fes servir l'endpoint /v1/chat/completions en comptes de /v1/audio/transcriptions per a una precisió potencialment millor.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Utilitza l'API de completació de xat", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Utilitza grups per organitzar els usuaris i assignar permisos.", "Use LLM": "Utilizar model de llenguatge", "Use no proxy to fetch page contents.": "No utilitzis un proxy per obtenir contingut de la pàgina.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Utilitza el proxy designat per les variables d'entorn http_proxy i https_proxy per obtenir el contingut de la pàgina.", + "Use Web Search?": "", "user": "usuari", "User": "Usuari", + "User Access": "", "User Activity": "Activitat d'usuari", "User Groups": "Grups d'usuari", "User location successfully retrieved.": "Ubicació de l'usuari obtinguda correctament", "User menu": "Menú d'usuari", - "User Preview": "", + "User Preview": "Previsualitzar l'usuari", "User ratings (thumbs up/down)": "Valoracions dels usuaris (polze amunt/avall)", "User Status": "Estats d'usuari", "User Webhooks": "Webhooks d'usuari", "Username": "Nom d'usuari", + "Username Claim": "", "users": "usuaris", "Users": "Usuaris", "Uses DefaultAzureCredential to authenticate": "Utilitza DefaultAzureCredential per a l'autenticació", @@ -2254,6 +2435,7 @@ "Valves updated": "Valves actualitzades", "Valves updated successfully": "Valves actualitzades correctament", "variable": "variable", + "Vector Field": "", "Verify Connection": "Verificar la connexió", "Verify SSL Certificate": "Verificar el certificat SSL", "Version": "Versió", @@ -2283,11 +2465,14 @@ "Web API": "Web API", "Web Loader Engine": "Motor de càrrega Web", "Web Search": "Cerca la web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motor de cerca de la web", "Web Search in Chat": "Cerca a internet al xat", "Web Search Query Generation": "Generació de consultes per a la cerca de la web", + "Webhook deleted": "", "Webhook Name": "Nom del webhook", - "Webhook URL": "URL del webhook", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URLs de la pàgina", "WebUI Settings": "Preferències de WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "Clau API de la cerca web Yandex", "Yandex Web Search config": "Configuració de la cerca web Yandex", "Yandex Web Search URL": "URL de la cerca web Yandex", + "Yearly": "", "Yesterday": "Ahir", "Yesterday at {{LOCALIZED_TIME}}": "Ahir a les {{LOCALIZED_TIME}}", "You": "Tu", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "El teu navegador no admet l'etiqueta de vídeo.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tota la teva contribució anirà directament al desenvolupador del complement; Open WebUI no se'n queda cap percentatge. Tanmateix, la plataforma de finançament escollida pot tenir les seves pròpies comissions.", "Your message text or inputs": "El text o les entrades del teu missatge", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Les teves estadístiques d'ús s'han sincronitzat correctament.", "YouTube": "Youtube", "Youtube Language": "Idioma de YouTube", diff --git a/src/lib/i18n/locales/ceb-PH/translation.json b/src/lib/i18n/locales/ceb-PH/translation.json index 4f0420c788..1386149546 100644 --- a/src/lib/i18n/locales/ceb-PH/translation.json +++ b/src/lib/i18n/locales/ceb-PH/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "", "{{webUIName}} Backend Required": "Backend {{webUIName}} gikinahanglan", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Account", @@ -72,6 +83,7 @@ "Activity": "", "Add": "", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "", "Add a tag": "Pagdugang og tag", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Idugang ang mga file", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "Admin Panel", + "Admin Roles": "", "Admin Settings": "Mga setting sa administratibo", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "advanced settings", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Naa na kay account ?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API Base URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "yawe sa API", + "API Key / Token": "", "API Key created.": "", "API Key Endpoint Restrictions": "", "API keys": "", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Awtomatikong kopya sa tubag sa clipboard", - "Auto-playback response": "Autoplay nga tubag", + "Auto-Create Groups": "", + "Auto-Playback Response": "Autoplay nga tubag", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "Base URL AUTOMATIC1111", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "magamit nga mga tiggamit", + "Available variables": "", "available!": "magamit!", "Away": "Wala", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "", "Banners": "", "Base Model (From)": "", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "", + "Chat Direction": "", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Koleksyon", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Pag-order", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "Kontento", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Gihimo ang", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "", "Default model updated": "Gi-update nga default template", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Default nga Papel sa Gumagamit", + "Default webhook": "", "Defaults": "", "Delete": "", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Gipalong", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan", + "Display the Username Instead of You in the Chat": "Ipakita ang username imbes nga 'Ikaw' sa Panaghisgutan", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokumento", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "I-edit ang tiggamit", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "I-enable ang bag-ong mga rehistro", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Gipaandar", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "Pagsulod sa mensahe {{role}} dinhi", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Pagsulod sa block overlap", "Enter Chunk Size": "Isulod ang block size", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Pagsulod sa Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Pagsulod sa URL (e.g. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Napakyas sa pagbasa sa sulod sa clipboard", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Mahinungdanong update", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Mga shortcut sa keyboard", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Kahayag", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "Gihimo sa komunidad sa OpenWebUI", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Gihiusa nga Resulta sa Tubag", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Walay resulta", "No results found": "", "No search query generated": "", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Mga pahibalo sa desktop", "November": "", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "", "Off": "Napuo", "Okay, Let's Go!": "Okay, lakaw na!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama nga bersyon", + "Omit": "", "On": "Gipaandar", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "Password", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "gipugngan", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "Gidili ang pagtugot sa dihang nag-access sa mikropono: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "Pagkuha ug template gikan sa Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Irekord ang tingog", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Gi-redirect ka sa komunidad sa OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "I-reset ang hulagway", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Papel", + "Roles Claim": "", "RTL": "", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ang pag-save sa mga chat log direkta sa imong browser storage dili na suportado. ", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Pagpanukiduki", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Pangitaa ang mga prompt", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "Binhi", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "", "Send a Message": "Magpadala ug mensahe", + "Send events for": "", "Send message": "Magpadala ug mensahe", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "Gipamatud-an nga koneksyon sa server", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Define pinaagi sa default", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Ipakigbahin sa komunidad sa OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Pagpakita", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Tinubdan", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Sayop sa pag-ila sa tingog: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "Mga setting sa STT", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "", "System Prompt": "Madasig nga Sistema", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Text-to-speech nga makina", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "I-update ang password", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "tiggamit", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Mga tiggamit", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "variable", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Bersyon", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Mga Setting sa WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/cs-CZ/translation.json b/src/lib/i18n/locales/cs-CZ/translation.json index 3703a5716e..c418e4b0a3 100644 --- a/src/lib/i18n/locales/cs-CZ/translation.json +++ b/src/lib/i18n/locales/cs-CZ/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} skrytých řádků", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} slov", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "Stažení modelu {{model}} bylo zrušeno", "{{modelName}} profile image": "", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "Konverzace uživatele {{user}}", "{{webUIName}} Backend Required": "Je vyžadován backend {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*Pro generování obrázků jsou vyžadována ID uzlů instrukce", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -63,6 +79,7 @@ "Access Control": "Řízení přístupu", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Přístupné pro všechny uživatele", "Account": "Účet", @@ -78,6 +95,7 @@ "Activity": "", "Add": "Přidat", "Add a model ID": "Přidat ID modelu", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Přidejte krátký popis toho, co tento model dělá.", "Add a tag": "Přidat štítek", "Add a tag...": "", @@ -90,8 +108,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "Přidat podrobnosti", + "Add durable context for future chats": "", "Add Files": "Přidat soubory", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -106,6 +126,7 @@ "Add to favorites": "", "Add User": "Přidat uživatele", "Add User Group": "Přidat skupinu uživatelů", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "Dodatečná konfigurace", @@ -118,7 +139,9 @@ "Admin": "Administrátor", "Admin Contact Email": "", "Admin Panel": "Administrace", + "Admin Roles": "", "Admin Settings": "Nastavení administrátora", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administrátoři mají kdykoli přístup ke všem nástrojům; uživatelé potřebují mít nástroje přiřazené k jednotlivým modelům v pracovním prostoru.", "Advanced": "", "Advanced Parameters": "Pokročilé parametry", @@ -129,16 +152,21 @@ "All": "Vše", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Všechny modely byly úspěšně smazány", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Povolit volání", "Allow Chat Controls": "Povolit ovládací prvky chatu", "Allow Chat Delete": "Povolit smazání konverzace", "Allow Chat Edit": "Povolit úpravu konverzace", "Allow Chat Export": "Povolit export konverzace", + "Allow Chat Import": "", "Allow Chat Params": "Povolit parametry chatu", "Allow Chat Share": "Povolit sdílení konverzace", "Allow Chat System Prompt": "Povolit systémové instrukce konverzace", @@ -158,9 +186,11 @@ "Allow User Location": "Povolit zjištění polohy uživatele", "Allow Voice Interruption in Call": "Povolit přerušení hlasu při hovoru", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Povolené koncové body", "Allowed File Extensions": "Povolené přípony souborů", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Povolené přípony souborů pro nahrání. Více přípon oddělte čárkami. Ponechte prázdné pro všechny typy souborů.", + "Allowed Roles": "", "Already have an account?": "Už máte účet?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa k top_p, jejímž cílem je zajistit rovnováhu mezi kvalitou a rozmanitostí. Parametr p představuje minimální pravděpodobnost, s jakou je token zvažován, vztaženou k pravděpodobnosti nejpravděpodobnějšího tokenu. Například při p=0,05 a nejpravděpodobnějším tokenu s pravděpodobností 0,9 jsou odfiltrovány logity s hodnotou menší než 0,045.", "Always": "Vždy", @@ -179,6 +209,7 @@ "API Base URL": "Základní URL adresa API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Základní URL adresa API pro službu Datalab Marker. Výchozí hodnota: https://www.datalab.to/api/v1/marker", "API Key": "Klíč API", + "API Key / Token": "", "API Key created.": "API klíč byl vytvořen.", "API Key Endpoint Restrictions": "Omezení koncových bodů API klíče", "API keys": "API klíče", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Opravdu chcete smazat tuto zprávu?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Opravdu chcete zrušit archivaci všech archivovaných konverzací?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modely pro arénu", "Artifacts": "Artefakty", "Asc": "", "Ask": "Zeptat se", "Ask a question": "Položit otázku", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistent", "Async Embedding Processing": "", "At time of event": "", @@ -229,14 +265,20 @@ "Audio": "Zvuk", "August": "Srpen", "Auth": "Ověření", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Ověřit", "Authentication": "Ověřování", "Auto": "Auto", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automaticky kopírovat odpověď do schránky", - "Auto-playback response": "Automatické přehrávání odpovědi", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatické přehrávání odpovědi", "Autocomplete Generation": "Generování automatického dokončování", "Autocomplete Generation Input Max Length": "Maximální délka vstupu pro generování automatického dokončování", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Ověřovací řetězec API pro AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Základní URL pro AUTOMATIC1111", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "Dostupné nástroje", "available users": "dostupní uživatelé", + "Available variables": "", "available!": "k dispozici!", "Away": "Nepřítomen", "Awful": "Hrozné", @@ -264,16 +307,17 @@ "Bad Response": "Špatná odpověď", "Banners": "Upozornění", "Base Model (From)": "Základní model (ze souboru)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Mezipaměť seznamu základních modelů zrychluje přístup načítáním základních modelů pouze při spuštění nebo při uložení nastavení – je to rychlejší, ale nemusí zobrazovat nedávné změny základních modelů.", "Bearer": "Bearer", "before": "před", "Being lazy": "Být líný", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Koncový bod Bing Search V7", "Bing Search V7 Subscription Key": "Klíč předplatného Bing Search V7", "Bio": "", "Birth Date": "Datum narození", + "Blocked Groups": "", "BM25 Weight": "Váha BM25", "Bocha Search API Key": "API klíč pro Bocha Search", "Bold": "Tučně", @@ -330,7 +374,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Směr konverzace", + "Chat Direction": "Směr konverzace", "Chat exported successfully": "", "Chat History": "", "Chat ID": "ID konverzace", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Sbalit", "Collection": "Kolekce", + "Collection Field": "", "Collections": "", "Color": "Barva", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "Pracovní postup ComfyUI", "ComfyUI Workflow Nodes": "Uzly pracovního postupu ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID uzlů oddělená čárkou (např. 1 nebo 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Příkaz", "Comment": "Komentář", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Dokončení", "Compress Images in Channels": "Komprimovat obrázky v kanálech", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Připojte se k vlastním koncovým bodům API kompatibilním s OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Připojte se k vlastním externím serverům nástrojů kompatibilním s OpenAPI.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Připojení se nezdařilo", "Connection lost. Reconnecting...": "", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Pro přístup k webovému rozhraní kontaktujte administrátora.", "Content": "Obsah", "Content Extraction Engine": "Jádro pro extrakci obsahu", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Pokračovat v odpovědi", "Continue with {{provider}}": "Pokračovat s {{provider}}", "Continue with Email": "Pokračovat s e-mailem", @@ -501,6 +557,7 @@ "Create new secret key": "Vytvořit nový tajný klíč", "Create note": "", "Create Note": "Vytvořit poznámku", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Vytvořte svou první poznámku kliknutím na tlačítko plus níže.", "Created at": "Vytvořeno", @@ -518,6 +575,7 @@ "Custom Gender": "", "Custom Parameter Name": "Název vlastního parametru", "Custom Parameter Value": "Hodnota vlastního parametru", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Nebezpečná zóna", @@ -540,7 +598,6 @@ "Default Features": "Výchozí funkce", "Default Filters": "Výchozí filtry", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Výchozí režim funguje s širší škálou modelů voláním nástrojů jednou před spuštěním. Nativní režim využívá vestavěné schopnosti modelu pro volání nástrojů, ale vyžaduje, aby model tuto funkci nativně podporoval.", "Default Model": "Výchozí model", "Default model updated": "Výchozí model byl aktualizován.", "Default permissions": "Výchozí oprávnění", @@ -550,6 +607,7 @@ "Default to ALL": "Výchozí hodnota VŠE", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Výchozí je segmentované vyhledávání pro cílenou a relevantní extrakci obsahu, což se doporučuje ve většině případů.", "Default User Role": "Výchozí role uživatele", + "Default webhook": "", "Defaults": "", "Delete": "Smazat", "Delete {{name}}": "", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "Zakázat interpret kódu", "Disable Image Extraction": "Zakázat extrakci obrázků", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Zakázat extrakci obrázků z PDF. Pokud je povoleno Použít LLM, obrázky budou automaticky opatřeny popisky. Výchozí hodnota je False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Zakázáno", "Disconnect OAuth": "", "Discover a function": "Objevit funkci", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Objevujte, stahujte a prozkoumávejte přednastavení modelů", "Discussion channel where access is based on groups and permissions": "", "Display": "Zobrazení", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Zobrazit emoji při hovoru", "Display Multi-model Responses in Tabs": "Zobrazit odpovědi více modelů v kartách", - "Display the username instead of You in the Chat": "Zobrazit v konverzaci uživatelské jméno místo „Vy“", + "Display the Username Instead of You in the Chat": "Zobrazit v konverzaci uživatelské jméno místo „Vy“", "Displays citations in the response": "Zobrazuje citace v odpovědi", "Displays status updates (e.g., web search progress) in the response": "Zobrazuje aktualizace stavu (např. průběh vyhledávání na webu) v odpovědi", "Dive into knowledge": "Ponořte se do znalostí", @@ -638,6 +698,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Je vyžadována URL adresa serveru Docling.", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -693,12 +754,14 @@ "Edit Default Permissions": "Upravit výchozí oprávnění", "Edit Folder": "Upravit složku", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Upravit vzpomínku", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Upravit uživatele", "Edit User Group": "Upravit skupinu uživatelů", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "Upraveno", @@ -707,6 +770,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "Vydejte se za dobrodružstvím", "Embedding": "Vektorizace", "Embedding Batch Size": "Velikost dávky pro vektorizaci", @@ -715,6 +779,7 @@ "Embedding Model Engine": "Jádro modelu pro vektorizaci", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -722,22 +787,27 @@ "Enable Code Execution": "Povolit spouštění kódu", "Enable Code Interpreter": "Povolit interpret kódu", "Enable Community Sharing": "Povolit komunitní sdílení", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Povolit uzamčení paměti (mlock), aby se zabránilo odkládání dat modelu z RAM. Tato možnost uzamkne pracovní sadu stránek modelu v RAM, čímž zajistí, že nebudou odloženy na disk. To může pomoci udržet výkon tím, že se zabrání výpadkům stránek a zajistí rychlý přístup k datům.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Povolit mapování paměti (mmap) pro načítání dat modelu. Tato možnost umožňuje systému používat diskové úložiště jako rozšíření RAM tím, že se se soubory na disku zachází, jako by byly v RAM. To může zlepšit výkon modelu tím, že umožní rychlejší přístup k datům. nemusí však správně fungovat se všemi systémy a může spotřebovat značné množství místa na disku.", "Enable Message Queue": "", "Enable Message Rating": "Povolit hodnocení zpráv", "Enable Mirostat sampling for controlling perplexity.": "Povolit vzorkování Mirostat pro řízení perplexity.", "Enable New Sign Ups": "Povolit nové registrace", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Povoleno", "End Tag": "", + "Endpoint": "", "Endpoint URL": "URL koncového bodu", "Enforce Temporary Chat": "Vynutit dočasnou konverzaci", "Enhance": "Vylepšit", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Ujistěte se, že váš CSV soubor obsahuje 4 sloupce v tomto pořadí: Jméno, E-mail, Heslo, Role.", "Enter {{role}} message here": "Zde zadejte zprávu {{role}}", - "Enter a detail about yourself for your LLMs to recall": "Zadejte podrobnost o sobě, kterou si vaše LLM mají pamatovat.", "Enter a title for the pending user info overlay. Leave empty for default.": "Zadejte název pro překryvnou vrstvu s informacemi o čekajícím uživateli. Pro výchozí ponechte prázdné.", "Enter a watermark for the response. Leave empty for none.": "Zadejte vodoznak pro odpověď. Pro žádný vodoznak ponechte prázdné.", "Enter additional headers in JSON format": "", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Zadejte překryv bloků", "Enter Chunk Size": "Zadejte velikost bloku", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Zadejte páry \"token:hodnota_odchylky\" oddělené čárkou (příklad: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Zadejte obsah pro překryvnou vrstvu s informacemi o čekajícím uživateli. Pro výchozí ponechte prázdné.", "Enter coordinates (e.g. 51.505, -0.09)": "Zadejte souřadnice (např. 50.0755, 14.4378)", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "Zadejte URL pro Jupyter", "Enter Kagi Search API Key": "Zadejte API klíč pro Kagi Search", "Enter Key Behavior": "Zadejte chování klávesy", + "Enter language": "", "Enter language codes": "Zadejte kódy jazyků", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Zadejte API klíč pro Mistral", @@ -812,6 +887,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Zadejte URL proxy (např. https://uzivatel:heslo@hostitel:port)", "Enter reasoning effort": "Zadejte úsilí pro uvažování", + "Enter Redirect URI": "", "Enter Score": "Zadejte skóre", "Enter SearchApi API Key": "Zadejte API klíč pro SearchApi", "Enter SearchApi Engine": "Zadejte jádro pro SearchApi", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "Zadejte API klíč pro SerpApi", "Enter SerpApi Engine": "Zadejte jádro pro SerpApi", "Enter Serper API Key": "Zadejte API klíč pro Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Zadejte API klíč pro Serply", "Enter Serpstack API Key": "Zadejte API klíč pro Serpstack", "Enter server host": "Zadejte hostitele serveru", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Zadejte URL serveru Tika", "Enter timeout in seconds": "Zadejte časový limit v sekundách", "Enter to Send": "Enter pro odeslání", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Zadejte Top K", "Enter Top K Reranker": "Zadejte Top K pro přehodnocení", "Enter URL (e.g. http://127.0.0.1:7860/)": "Zadejte URL (např. http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Chyba: Model s ID '{{modelId}}' již existuje. Pro pokračování prosím zvolte jiné ID.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Chyba: ID modelu nemůže být prázdné. Pro pokračování prosím zadejte platné ID.", "Evaluations": "Hodnocení", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "API klíč pro Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Příklad: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Příklad: VŠE", "Example: mail": "Příklad: mail", @@ -913,12 +996,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Exportovat do CSV", "Export Tools": "", "Export Users": "Exportovat uživatele", "External": "Externí", + "External connection not found.": "", "External Document Loader URL required.": "Je vyžadována URL externího zavaděče dokumentů.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Externí model pro úkoly", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "API klíč pro externí webový zavaděč", "External Web Loader URL": "URL pro externí webový zavaděč", "External Web Search API Key": "API klíč pro externí webové vyhledávání", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Nepodařilo se vytvořit API klíč.", "Failed to delete calendar": "", "Failed to delete note": "Nepodařilo se smazat poznámku", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "Nepodařilo se extrahovat obsah ze souboru: {{error}}", @@ -943,6 +1033,7 @@ "Failed to fetch models": "Nepodařilo se načíst modely", "Failed to generate title": "Nepodařilo se vygenerovat název", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "Nepodařilo se načíst náhled konverzace", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -952,6 +1043,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepodařilo se přečíst obsah schránky", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "Nepodařilo se uložit konfiguraci modelů", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Nepodařilo se aktualizovat nastavení", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Nepodařilo se nahrát soubor.", "Features": "Funkce", "Features Permissions": "Oprávnění funkcí", @@ -995,6 +1089,8 @@ "File uploaded successfully": "Soubor byl úspěšně nahrán", "Filename": "", "Files": "Soubory", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtr", "Filter is now globally disabled": "Filtr je nyní globálně zakázán", "Filter is now globally enabled": "Filtr je nyní globálně povolen.", @@ -1017,6 +1113,7 @@ "Folder options": "", "Folder updated successfully": "Složka byla úspěšně aktualizována", "Folders": "Složky", + "Folders Sharing": "", "Follow up": "Následná otázka", "Follow Up Generation": "Generování následných otázek", "Follow Up Generation Prompt": "Pokyn pro generování následných instrukcí", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Funkce je nyní globálně povolena.", "Function Name": "Název funkce", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funkce byla úspěšně aktualizována.", "Functions": "Funkce", "Functions allow arbitrary code execution.": "Funkce umožňují spouštění libovolného kódu.", @@ -1079,7 +1177,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Skupina byla úspěšně vytvořena", "Group deleted successfully": "Skupina byla úspěšně smazána", "Group Description": "Popis skupiny", @@ -1091,6 +1192,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptická odezva", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "Výška", @@ -1121,6 +1223,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "Povolit formuláře v sandboxu iframe", "iframe Sandbox Allow Same Origin": "Povolit stejný původ v sandboxu iframe", @@ -1146,6 +1250,7 @@ "Import From Link": "Importovat z odkazu", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Důležitá aktualizace", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "Ponechat v postranním panelu", "Key": "Klíč", "Key is required": "Klíč je vyžadován", - "Keyboard shortcuts": "Klávesové zkratky", "Keyboard Shortcuts": "", "Knowledge": "Znalosti", "Knowledge Access": "Přístup ke znalostem", @@ -1216,6 +1320,8 @@ "Knowledge Name": "Název znalosti", "Knowledge Public Sharing": "Veřejné sdílení znalostí", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Znalost byla úspěšně aktualizována", "Kokoro.js (Browser)": "Kokoro.js (prohlížeč)", "Kokoro.js Dtype": "Datový typ Kokoro.js", @@ -1232,7 +1338,6 @@ "Last ran": "", "Last reply": "Poslední odpověď", "LDAP": "LDAP", - "LDAP server updated": "LDAP server byl aktualizován", "Leaderboard": "Žebříček", "Learn more": "", "Learn More": "Zjistit více", @@ -1254,6 +1359,7 @@ "Legacy": "", "lexical": "lexikální", "License": "Licence", + "Lifecycle JSON": "", "Lift List": "Zvýraznit seznam", "Light": "Světlý", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1277,6 +1383,7 @@ "Location access not allowed": "Přístup k poloze nebyl povolen", "Lost": "Prohrál", "Low": "Nízká", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Vytvořeno komunitou Open WebUI", "Make password visible in the user interface": "Zviditelnit heslo v uživatelském rozhraní", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Správa pipeline", "Manage Tool Servers": "Spravovat servery nástrojů", "Manage your account information.": "Spravujte informace o svém účtu.", + "Mapped Source": "", "March": "Březen", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Paměť byla úspěšně vymazána.", "Memory deleted successfully": "Vzpomínka byla úspěšně smazána", "Memory updated successfully": "Vzpomínka byla úspěšně aktualizována", + "Merge Accounts by Email": "", "Merge Responses": "Sloučit odpovědi", "Merged Response": "Sloučená odpověď", "Message": "", @@ -1330,9 +1439,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Zprávy, které odešlete po vytvoření odkazu, nebudou sdíleny. Uživatelé s URL adresou budou moci zobrazit sdílenou konverzaci.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (osobní)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (pracovní/školní)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1385,6 +1497,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "API klíč pro Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Více", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "Pojmenujte svou znalostní bázi", "Name, prompt, and model are required": "", "Native": "Nativní", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1431,6 +1545,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "Nebyly nalezeny žádné konverzace", @@ -1443,8 +1558,10 @@ "No data": "", "No data found": "", "No distance available": "Vzdálenost není k dispozici", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nebyl vybrán žádný soubor", "No files found": "", @@ -1472,6 +1589,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "Nebyly nalezeny žádné instrukce", + "No Repeat": "", "No results": "Nebyly nalezeny žádné výsledky", "No results found": "Nebyly nalezeny žádné výsledky", "No search query generated": "Nebyl vygenerován žádný vyhledávací dotaz.", @@ -1491,6 +1609,7 @@ "No webhooks yet": "", "Node Ids": "ID uzlů", "None": "Žádný", + "Not configured": "", "Not factually correct": "Fakticky nesprávné", "Not helpful": "Nepomohlo", "Not Registered": "", @@ -1506,20 +1625,25 @@ "Notifications": "Oznámení", "November": "Listopad", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Říjen", "Off": "Vypnuto", "Okay, Let's Go!": "Dobře, jdeme na to!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED tmavý", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Nastavení Ollama API byla aktualizována", "Ollama Cloud API Key": "", "Ollama Version": "Verze Ollama", + "Omit": "", "On": "Zapnuto", "Once": "", "OneDrive": "OneDrive", @@ -1590,6 +1714,7 @@ "Password": "Heslo", "Passwords do not match.": "Hesla se neshodují.", "Paste Large Text as File": "Vložit velký text jako soubor", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Dokument PDF (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "čeká na vyřízení", "Pending": "Čeká na vyřízení", + "Pending Accounts": "", "Pending User Overlay Content": "Obsah překryvné vrstvy pro čekajícího uživatele", "Pending User Overlay Title": "Název překryvné vrstvy pro čekajícího uživatele", "Permission denied when accessing media devices": "Přístup k mediálním zařízením byl odepřen", "Permission denied when accessing microphone": "Přístup k mikrofonu byl odepřen", "Permission denied when accessing microphone: {{error}}": "Přístup k mikrofonu byl odepřen: {{error}}", "Permissions": "Oprávnění", + "Permissions reset to defaults": "", "Perplexity API Key": "API klíč pro Perplexity", "Perplexity Model": "Model Perplexity", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "Využití kontextu vyhledávání Perplexity", "Persistent": "", "Personalization": "Personalizace", + "Picture Claim": "", "Pin": "Připnout", "Pin to Sidebar": "", "Pinned": "Připnuto", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "Vyplňte prosím všechna pole.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Nejprve prosím vyberte model.", "Please select a model.": "Vyberte prosím model.", "Please select a reason": "Vyberte prosím důvod", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Prosím počkejte dokud nebudou všechny soubory nahrány.", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Pozitivní přístup", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "Veřejné sdílení instrukcí", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Veřejné", "Pull \"{{searchValue}}\" from Ollama.com": "Stáhnout \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Stáhnout model z Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "Přečíst", "Read Aloud": "Číst nahlas", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "Důvod", "Reasoning Effort": "reasoning effort", "Reasoning Tags": "reasoning tags", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Nahrát", "Record voice": "Nahrát hlas", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Přesměrovávám vás do komunity Open WebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na sebe jako na \"Uživatele\" (např. \"Uživatel se učí španělsky\").", "Reference Chats": "Připojit chat", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Odmítnuto, i když nemělo být", "Regenerate": "Znovu generovat", "Regenerate Menu": "Nabídka Znovu generovat", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Změnit pořadí modelů", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Odpovědět ve vlákně", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Jádro pro přehodnocení", "Reranking Model": "Model pro přehodnocení", + "Research Knowledge": "", "Reset": "Resetovat", "Reset All Models": "Resetovat všechny modely", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetovat obrázek", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Resetovat adresář pro nahrávání", "Reset Vector Storage/Knowledge": "Resetovat vektorové úložiště/znalosti", "Reset view": "Resetovat zobrazení", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Pokročilé formátování vstupního pole konverzace", "Role": "Role", + "Roles Claim": "", "RTL": "RTL", "Run": "Spustit", "Run All": "", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ukládání záznamů konverzací přímo do úložiště vašeho prohlížeče již není podporováno. Věnujte prosím chvíli stažení a smazání svých záznamů konverzací kliknutím na tlačítko níže. Nemějte obavy, své záznamy konverzací můžete snadno znovu importovat do backendu prostřednictvím", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Posouvat při změně větve", "Scroll to Top": "", "Search": "Hledat", "Search a model": "Hledat model", + "Search actions": "", "Search all emojis": "Hledat všechny emoji", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1810,6 +1960,7 @@ "Search Chats": "Hledat v konverzacích", "Search Collection": "Hledat v kolekci", "Search Files": "", + "Search filters": "", "Search Filters": "Filtry vyhledávání", "search for archived chats": "hledat archivované konverzace", "search for folders": "hledat složky", @@ -1824,13 +1975,16 @@ "Search Models": "Hledat modely", "Search Notes": "Hledat poznámky", "Search options": "Možnosti vyhledávání", + "Search or add pattern": "", "Search Prompts": "Hledat instrukce", "Search Result Count": "Počet výsledků hledání", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Hledat na internetu", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Hledat nástroje", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "API klíč pro SearchApi", "SearchApi Engine": "Jádro pro SearchApi", @@ -1846,7 +2000,6 @@ "Seed": "seed", "Select": "Vybrat", "Select {{modelName}} model": "", - "Select a base model": "Vyberte základní model", "Select a base model (e.g. llama3, gpt-4o)": "Vyberte základní model (např. llama3, gpt-4o)", "Select a conversation to preview": "Vyberte konverzaci pro náhled", "Select a engine": "Vyberte jádro", @@ -1884,18 +2037,25 @@ "semantic": "sémantický", "Send": "Odeslat", "Send a Message": "Odeslat zprávu", + "Send events for": "", "Send message": "Odeslat zprávu", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Odešle `stream_options: { include_usage: true }` v požadavku.\nPodporovaní poskytovatelé vrátí informace o využití tokenů v odpovědi, pokud je tato možnost nastavena.", "September": "Září", "SerpApi API Key": "API klíč pro SerpApi", "SerpApi Engine": "Jádro pro SerpApi", "Serper API Key": "API klíč pro Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "API klíč pro Serply", "Serpstack API Key": "API klíč pro Serpstack", "Server connection failed": "", "Server connection verified": "Připojení k serveru ověřeno", + "Service Account": "", "Session": "Relace", + "Session expired. Please sign in again.": "", "Set as default": "Nastavit jako výchozí", "Set as Production": "", "Set embedding model": "Nastavit model pro vektorizaci", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Sdílet s komunitou Open WebUI", "Share your background and interests": "Sdílejte své zkušenosti a zájmy", + "Shared": "", "Shared Chats": "", "Shared with you": "Sdíleno s vámi", "Sharing Permissions": "Oprávnění pro sdílení", "Show": "Zobrazit", - "Show \"What's New\" modal on login": "Zobrazit okno \"Co je nového\" při přihlášení", + "Show \"What's New\" Modal on Login": "Zobrazit okno \"Co je nového\" při přihlášení", "Show Admin Details in Account Pending Overlay": "Zobrazit podrobnosti administrátora v překryvné vrstvě čekajícího účtu", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Zobrazit panel nástrojů pro formátování", "Show image preview": "Zobrazit náhled obrázku", "Show Model": "Zobrazit model", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "sID API pro Sougou Search", "Sougou Search API SK": "SK API pro Sougou Search", "Source": "Zdroj", + "Specific users or groups": "", "Speech Playback Speed": "Rychlost přehrávání řeči", "Speech recognition error: {{error}}": "Chyba rozpoznávání řeči: {{error}}", "Speech-to-Text": "Převod řeči na text", @@ -2013,6 +2176,7 @@ "STT Settings": "Nastavení STT", "Stylized PDF Export": "Stylizovaný export do PDF", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2037,8 +2201,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Systém", + "System events only": "", "System Instructions": "Systémové instrukce", "System Prompt": "Systémové instrukce", + "Table": "", "Tag": "Štítek", "Tags": "Štítky", "Tags Generation": "Generování štítků", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Rozdělovač textu", "Text-to-Speech": "Převod textu na řeč", "Text-to-Speech Engine": "Jádro pro převod textu na řeč", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Jazyk vstupního zvuku. Zadání vstupního jazyka ve formátu ISO-639-1 (např. cs) zlepší přesnost a latenci. Ponechte prázdné pro automatickou detekci jazyka.", "The LDAP attribute that maps to the mail that users use to sign in.": "Atribut LDAP, který se mapuje na e-mail, který uživatelé používají k přihlášení.", "The LDAP attribute that maps to the username that users use to sign in.": "Atribut LDAP, který se mapuje na uživatelské jméno, které uživatelé používají k přihlášení.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Žebříček je v současné době v beta verzi a můžeme upravit výpočty hodnocení, jak budeme zdokonalovat algoritmus.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Maximální velikost souboru v MB. Pokud velikost souboru překročí tento limit, soubor nebude nahrán.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maximální počet souborů, které lze použít najednou v konverzaci. Pokud počet souborů překročí tento limit, soubory nebudou nahrány.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Výstupní formát textu. Může být 'json', 'markdown' nebo 'html'. Výchozí je 'markdown'.", @@ -2096,6 +2267,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Toto je experimentální funkce, nemusí fungovat podle očekávání a může být kdykoli změněna.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Tento model není veřejně dostupný. Vyberte prosím jiný model.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Tato možnost řídí, jak dlouho zůstane model po požadavku načten v paměti (výchozí: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Tato možnost řídí, kolik tokenů se zachová při obnovování kontextu. Například, pokud je nastavena na 2, poslední 2 tokeny kontextu konverzace budou zachovány. Zachování kontextu může pomoci udržet kontinuitu konverzace, ale může snížit schopnost reagovat na nová témata.", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "Pro více informací o dostupných koncových bodech navštivte naši dokumentaci.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Pro výběr sad nástrojů zde je nejprve přidejte do pracovního prostoru \"Nástroje\".", - "Toast notifications for new updates": "Vyskakovací oznámení o nových aktualizacích", + "Toast Notifications for New Updates": "Vyskakovací oznámení o nových aktualizacích", "Today": "Dnes", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "Přepnout, zda je aktuální připojení aktivní.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Příliš rozvláčné", @@ -2198,14 +2372,19 @@ "Unpin": "Odepnout", "Unpin from Sidebar": "", "Unravel secrets": "Rozplétejte tajemství", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "Nepodporovaný typ souboru.", "Untagged": "Bez štítku", "Untitled": "Bez názvu", "Update": "Aktualizovat", "Update and Copy Link": "Aktualizovat a zkopírovat odkaz", + "Update Email": "", "Update for the latest features and improvements.": "Aktualizujte pro nejnovější funkce a vylepšení.", + "Update Name": "", "Update password": "Aktualizovat heslo", + "Update Picture": "", "Update your status": "", "Updated": "Aktualizováno", "Updated at": "Aktualizováno", @@ -2232,13 +2411,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Použijte '#' ve vstupu promptu pro načtení a zahrnutí vašich znalostí.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Použít LLM", "Use no proxy to fetch page contents.": "Nepoužívat proxy pro načítání obsahu stránky.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Použít proxy určenou proměnnými prostředí http_proxy a https_proxy pro načítání obsahu stránky.", + "Use Web Search?": "", "user": "uživatel", "User": "Uživatel", + "User Access": "", "User Activity": "", "User Groups": "Skupiny uživatelů", "User location successfully retrieved.": "Poloha uživatele byla úspěšně získána.", @@ -2248,6 +2432,7 @@ "User Status": "", "User Webhooks": "Uživatelské webhooky", "Username": "Uživatelské jméno", + "Username Claim": "", "users": "", "Users": "Uživatelé", "Uses DefaultAzureCredential to authenticate": "", @@ -2261,6 +2446,7 @@ "Valves updated": "Valves aktualizovány", "Valves updated successfully": "Valves byly úspěšně aktualizovány.", "variable": "proměnná", + "Vector Field": "", "Verify Connection": "Ověřit připojení", "Verify SSL Certificate": "Ověřit SSL certifikát", "Version": "Verze", @@ -2290,11 +2476,14 @@ "Web API": "Webové API", "Web Loader Engine": "Jádro webového zavaděče", "Web Search": "Vyhledávání na webu", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Webový vyhledávač", "Web Search in Chat": "Vyhledávání na webu v konverzaci", "Web Search Query Generation": "Generování dotazu pro webové vyhledávání", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL webhooku", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Nastavení WebUI", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Včera", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vy", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Celý váš příspěvek půjde přímo vývojáři pluginu; Open WebUI si nebere žádné procento. Zvolená platforma pro financování však může mít vlastní poplatky.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "Jazyk YouTube", diff --git a/src/lib/i18n/locales/da-DK/translation.json b/src/lib/i18n/locales/da-DK/translation.json index bec7c926a7..020b4c1bd4 100644 --- a/src/lib/i18n/locales/da-DK/translation.json +++ b/src/lib/i18n/locales/da-DK/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} skjulte linjer", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} kilder", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} ord", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} klokken {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Download af {{model}} er blevet annulleret", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}s chats", "{{webUIName}} Backend Required": "{{webUIName}} Backend kræves", "*Prompt node ID(s) are required for image generation": "*Prompt node ID(s) er påkrævet for at kunne generere billeder", + "1 group": "", "1 hour before": "", "1 Source": "1 kilde", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Adgangskontrol", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Tilgængelig for alle brugere", "Account": "Profil", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Tilføj", "Add a model ID": "Tilføj et model-ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "En kort beskrivelse af hvad denne model gør", "Add a tag": "Tilføj et tag", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Tilføj brugerdefineret prompt", "Add description": "", "Add Details": "Tilføj detaljer", + "Add durable context for future chats": "", "Add Files": "Tilføj filer", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "Tilføj medlem", "Add Members": "Tilføj medlemmer", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Tilføj bruger", "Add User Group": "Tilføj Brugergruppe", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "Yderligere konfiguration", @@ -112,7 +127,9 @@ "Admin": "Administrator", "Admin Contact Email": "", "Admin Panel": "Administrationspanel", + "Admin Roles": "", "Admin Settings": "Administrationsindstillinger", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorer har adgang til alle værktøjer altid; brugere skal tilføjes værktøjer pr. model i hvert workspace.", "Advanced": "", "Advanced Parameters": "Avancerede indstillinger", @@ -123,16 +140,21 @@ "All": "Alle", "All chats have been unarchived.": "Alle chatte er blevet aktive", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Alle modeller slettet uden fejl", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Tillad kald", "Allow Chat Controls": "Tillad kontrol af chats", "Allow Chat Delete": "Tillad sletning af chats", "Allow Chat Edit": "Tillad redigering af chats", "Allow Chat Export": "Tillad eksport af chats", + "Allow Chat Import": "", "Allow Chat Params": "Tillad parametre i chats", "Allow Chat Share": "Tillad deling af chats", "Allow Chat System Prompt": "Tillad system prompt", @@ -152,9 +174,11 @@ "Allow User Location": "Tillad bruger-lokation", "Allow Voice Interruption in Call": "Tillad afbrydelser i stemme i opkald", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Tilladte endpoints", "Allowed File Extensions": "Tilladte filtypenavne", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Filtypenavne tilladte til upload. Adskil flere filtypenavne med komma. Lad den være tom for alle filtypenavne", + "Allowed Roles": "", "Already have an account?": "Har du allerede en profil?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativ til top_p, og sigter mod at sikre en balance mellem kvalitet og variation. Parameteren p repræsenterer minimumsandsynligheden for at et token overvejes, relativt til sandsynligheden for det mest sandsynlige token. For eksempel, med p=0.05 og det mest sandsynlige token med en sandsynlighed på 0.9, filtreres logits med en værdi mindre end 0.045 fra.", "Always": "Altid", @@ -173,6 +197,7 @@ "API Base URL": "API base URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API base URL for Datalab Marker service. Standard: https://www.datalab.to/api/v1/marker", "API Key": "API nøgle", + "API Key / Token": "", "API Key created.": "API nøgle lavet", "API Key Endpoint Restrictions": "API nøgler endpoint forbehold", "API keys": "API nøgler", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Er du sikker på du vil slette denne besked?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Er du sikker på du vil fjerne alle arkiverede chats?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena Modeller", "Artifacts": "Artifakter", "Asc": "", "Ask": "Spørg", "Ask a question": "Stil et spørgsmål", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "Asynkron embedding processering", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Lyd", "August": "august", "Auth": "Auth", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentificer", "Authentication": "Autentifikation", "Auto": "Auto", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatisk kopiering af svar til udklipsholder", - "Auto-playback response": "Automatisk afspil svar", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatisk afspil svar", "Autocomplete Generation": "Genere automatisk fuldførsel", "Autocomplete Generation Input Max Length": "Maksimal længde for genereret autofuldførsel", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 base URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Tilgængelige værktøj", "available users": "tilgængelige brugere", + "Available variables": "", "available!": "tilgængelig!", "Away": "Fraværende", "Awful": "Forfærdeligt", @@ -258,16 +295,17 @@ "Bad Response": "Problem i response", "Banners": "Bannere", "Base Model (From)": "Base Model (Fra)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Base Model List Cache øger hastigheden ved kun at hente base modeller ved opstart eller når indstillinger gemmes, men viser muligvis ikke nylige ændringer i base modeller.", "Bearer": "Bearer", "before": "før", "Being lazy": "At være doven", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 Endpoint", "Bing Search V7 Subscription Key": "Bing Search V7 Subscription Key", "Bio": "Biografi", "Birth Date": "Fødselsdato", + "Blocked Groups": "", "BM25 Weight": "BM25 vægt", "Bocha Search API Key": "Bocha Search API Key", "Bold": "Fed", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "Chat samtale", "Chat deleted.": "", - "Chat direction": "Chat retning", + "Chat Direction": "Chat retning", "Chat exported successfully": "", "Chat History": "", "Chat ID": "Chat ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Samarbejdskanal hvor folk tilmelder sig som medlemmer", "Collapse": "Kollapse", "Collection": "Samling", + "Collection Field": "", "Collections": "", "Color": "Farve", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI Workflow", "ComfyUI Workflow Nodes": "ComfyUI Workflow Nodes", "Comma separated Node Ids (e.g. 1 or 1,2)": "Kommaseparerede node ID'er (f.eks. 1 eller 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Kommando", "Comment": "Kommentar", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Completions", "Compress Images in Channels": "Komprimér billeder i kanaler", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Opret forbindelse til din egen OpenAI kompatible API endpoints.", "Connect to your own OpenAPI compatible external tool servers.": "Opret forbindelse til dine egne OpenAPI kompatible eksterne værktøjsservere.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Forbindelse mislykkedes", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Kontakt din administrator for adgang til WebUI", "Content": "Indhold", "Content Extraction Engine": "Content Extraction Motor", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Fortsæt svar", "Continue with {{provider}}": "Fortsæt med {{provider}}", "Continue with Email": "Fortsæt med Email", @@ -493,6 +543,7 @@ "Create new secret key": "Opret en ny hemmelig nøgle", "Create note": "", "Create Note": "Opret note", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Opret din første note ved at klikke på plus knappen nedenfor.", "Created at": "Oprettet", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "Brugerdefineret parameternavn", "Custom Parameter Value": "Brugerdefineret parameterværdi", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Danger Zone", @@ -532,7 +584,6 @@ "Default Features": "Standardfunktioner", "Default Filters": "Standardfiltre", "Default Group": "Standardgruppe", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Standardtilstand fungerer med et bredere udvalg af modeller ved at kalde værktøjer én gang før udførelse. Native tilstand udnytter modellens indbyggede værktøjskald-funktioner, men kræver at modellen i sagens natur understøtter denne funktion.", "Default Model": "Standard model", "Default model updated": "Standard model opdateret", "Default permissions": "Standard tilladelser", @@ -542,6 +593,7 @@ "Default to ALL": "Standard til ALLE", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Standard til segmenteret hentning for fokuseret og relevant indholdsudtrækning, dette anbefales i de fleste tilfælde.", "Default User Role": "Brugers rolle som standard", + "Default webhook": "", "Defaults": "", "Delete": "Slet", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Deaktiver kode interpreter", "Disable Image Extraction": "Deaktiver billedudtrækning", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Deaktiver billedudtrækning fra PDF'en. Hvis Use LLM er aktiveret, vil billeder automatisk få undertekster. Standard er False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Deaktiveret", "Disconnect OAuth": "", "Discover a function": "Find en funktion", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Find, download og udforsk modelindstillinger", "Discussion channel where access is based on groups and permissions": "Diskussionskanal hvor adgang styres af grupper og tilladelser", "Display": "Vis", - "Display chat title in tab": "Vis chattitel i fane", + "Display Chat Title in Tab": "Vis chattitel i fane", "Display Emoji in Call": "Vis emoji i chat", "Display Multi-model Responses in Tabs": "Vis multimodel svar i faner", - "Display the username instead of You in the Chat": "Vis brugernavn i stedet for Dig i chatten", + "Display the Username Instead of You in the Chat": "Vis brugernavn i stedet for Dig i chatten", "Displays citations in the response": "Vis citat i svaret", "Displays status updates (e.g., web search progress) in the response": "Vis statusopdateringer (f.eks. websøgningsprocess) i svaret", "Dive into knowledge": "Undersøg viden", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling parametre", "Docling Server URL required.": "Docling Server URL påkrævet.", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Document Intelligence endpoint påkrævet", "Document Intelligence Model": "Document Intelligence model", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Rediger standard tilladelser", "Edit Folder": "Rediger mappe", "Edit Image": "Rediger billede", + "Edit Knowledge Connection": "", "Edit Last Message": "Rediger sidste besked", "Edit Memory": "Rediger hukommelse", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Rediger bruger", "Edit User Group": "Rediger brugergruppe", + "Edit webhook": "", "Edit workflow.json content": "Rediger workflow.json indhold", "edited": "redigeret", "Edited": "Redigeret", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Udforsk eventyr", "Embedding": "Embedding", "Embedding Batch Size": "Embedding Batch størrelse", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Embedding Model engine", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "Aktiver API nøgler", @@ -714,22 +773,27 @@ "Enable Code Execution": "Aktiver kodekørsel", "Enable Code Interpreter": "Aktiver kode interpreter", "Enable Community Sharing": "Aktiver deling til Community", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Aktiver Memory Locking (mlock) for at forhindre modeldata i at blive swappet ud af RAM. Denne indstilling låser modellens arbejdssæt af sider i RAM og sikrer, at de ikke bliver swappet til disk. Dette kan hjælpe med at opretholde ydeevnen ved at undgå page faults og sikre hurtig dataaccess.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Aktiver Memory Mapping (mmap) for at indlæse modeldata. Denne indstilling tillader systemet at bruge disklagring som en udvidelse af RAM ved at behandle diskfiler, som om de var i RAM. Dette kan forbedre modellens ydeevne ved at muliggøre hurtigere dataaccess. Det fungerer dog måske ikke korrekt på alle systemer og kan forbruge betydelig diskplads.", "Enable Message Queue": "", "Enable Message Rating": "Aktiver rating af besked", "Enable Mirostat sampling for controlling perplexity.": "Aktiver Mirostat sampling for at kontrollere perplexity.", "Enable New Sign Ups": "Aktiver nye signups", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Aktiver, deaktiver eller tilpas brugerdefinerede ræsonneringstags benyttet af modellen. \"Aktiveret\" benytter standardtags, \"Deaktiveret\" slår ræsonneringstags fra og \"Brugerdefineret\" giver dig mulighed for at angive dine egne start- og sluttags", "Enabled": "Aktiveret", "End Tag": "Slut tag", + "Endpoint": "", "Endpoint URL": "Endpoint URL", "Enforce Temporary Chat": "Gennemtving midlertidig chat", "Enhance": "Forbedre", "Enrich Hybrid Search Text": "Berig hybrid søgetekst", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Sørg for at din CSV-fil indeholder 4 kolonner i denne rækkefølge: Name, Email, Password, Role.", "Enter {{role}} message here": "Indtast {{role}} besked her", - "Enter a detail about yourself for your LLMs to recall": "Indtast en detalje om dig selv, som dine LLMs kan huske", "Enter a title for the pending user info overlay. Leave empty for default.": "Indtast en titel til afventende bruger informations overlay. Lad være tom for standard.", "Enter a watermark for the response. Leave empty for none.": "Indtast et vandmærke til svaret. Lad være tom for ingen.", "Enter additional headers in JSON format": "Indtast yderligere headers i JSON format", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Indtast overlapning af tekststykker", "Enter Chunk Size": "Indtast størrelse af tekststykker", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Indtast kommaseparerede \"token:bias_værdi\" par (eksempel: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Indtast indhold til afventende bruger informations overlay. Lad være tom for standard.", "Enter coordinates (e.g. 51.505, -0.09)": "Indtast koordinater (f.eks. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Indtast Jupyter URL", "Enter Kagi Search API Key": "Indtast Kagi Search API nøgle", "Enter Key Behavior": "Indtast taste opførsel", + "Enter language": "", "Enter language codes": "Indtast sprogkoder", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "Indtast Mistral API base URL", "Enter Mistral API Key": "Indtast Mistral API nøgle", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Indtast proxy URL (f.eks. https://bruger:adgangskode@host:port)", "Enter reasoning effort": "Indtast ræsonneringsindsats", + "Enter Redirect URI": "", "Enter Score": "Indtast score", "Enter SearchApi API Key": "Indtast SearchApi API-nøgle", "Enter SearchApi Engine": "Indtast SearchApi-engine", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Indtast SerpApi API-nøgle", "Enter SerpApi Engine": "Indtast SerpApi-engine", "Enter Serper API Key": "Indtast Serper API-nøgle", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Indtast Serply API-nøgle", "Enter Serpstack API Key": "Indtast Serpstack API-nøgle", "Enter server host": "Indtast server-host", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Indtast Tika Server URL", "Enter timeout in seconds": "Indtast timeout i sekunder", "Enter to Send": "Indtast for at sende", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Indtast Top K", "Enter Top K Reranker": "Indtast Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Indtast URL (f.eks. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Fejl: En model med ID '{{modelId}}' eksisterer allerede. Vælg venligst et andet ID for at fortsætte.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Fejl: Model ID kan ikke være tomt. Indtast venligst et gyldigt ID for at fortsætte.", "Evaluations": "Evalueringer", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API-nøgle", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Eksempel: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Eksempel: ALL", "Example: mail": "Eksempel: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "Eksportér modeller", "Export Prompts": "Eksportér prompter", + "Export Skills": "", "Export to CSV": "Eksportér til CSV", "Export Tools": "Eksportér værktøjer", "Export Users": "Eksportér brugere", "External": "Ekstern", + "External connection not found.": "", "External Document Loader URL required.": "External Dokument Loader URL påkrævet.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Ekstern opgavemodel", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Ekstern Web Loader API-nøgle", "External Web Loader URL": "Ekstern Web Loader URL", "External Web Search API Key": "Ekstern Web Search API-nøgle", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Kunne ikke oprette API-nøgle.", "Failed to delete calendar": "", "Failed to delete note": "Kunne ikke slette note", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "Kunne ikke udtrække indhold fra filen: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Kunne ikke hente modeller", "Failed to generate title": "Kunne ikke generere titel", "Failed to import models": "Kunne ikke importere modeller", + "Failed to load chat": "", "Failed to load chat preview": "Kunne ikke indlæse chat forhåndsvisning", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "Kunne ikke flytte chat", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Kunne ikke læse indholdet af udklipsholderen", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Kunne ikke fjerne medlem", "Failed to render diagram": "Kunne ikke rendere diagram", "Failed to render visualization": "Kunne ikke rendere visualisering", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Kunne ikke gemme modeller konfiguration", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Kunne ikke opdatere indstillinger", "Failed to update status": "Kunne ikke opdatere status", + "Failed to update webhook": "", "Failed to upload file.": "Kunne ikke uploade fil.", "Features": "Features", "Features Permissions": "Features tilladelser", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Fil uploadet.", "Filename": "", "Files": "Filer", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filter", "Filter is now globally disabled": "Filter er nu globalt deaktiveret", "Filter is now globally enabled": "Filter er nu globalt aktiveret", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "Mappe opdateret", "Folders": "Mapper", + "Folders Sharing": "", "Follow up": "Opfølgning", "Follow Up Generation": "Opfølgnings generering", "Follow Up Generation Prompt": "Opfølgnings genererings prompt", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funktionen er nu globalt aktiveret", "Function Name": "Funktionsnavn", "Function Name Filter List": "Funktionsnavn filterliste", + "Function starter": "", "Function updated successfully": "Funktion opdateret.", "Functions": "Funktioner", "Functions allow arbitrary code execution.": "Funktioner tillader kørsel af vilkårlig kode.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "Gruppekanal", + "Group Claim": "", "Group created successfully": "Gruppe oprettet.", "Group deleted successfully": "Gruppe slettet.", "Group Description": "Gruppe beskrivelse", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptisk feedback", + "Header variables": "", "Headers": "Headers", "Headers must be a valid JSON object": "Headers skal være et gyldigt JSON objekt", "Height": "Højde", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID må ikke indeholde tegnene \":\" eller \"|\"", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox tillad formularer", "iframe Sandbox Allow Same Origin": "iframe Sandbox tillad samme oprindelse", @@ -1138,6 +1236,7 @@ "Import From Link": "Importer fra et link", "Import Models": "Importer modeller", "Import Prompts": "Importer prompter", + "Import Skills": "", "Import successful": "Importeret", "Import Tools": "Importer værktøjer", "Important Update": "Vigtig opdatering", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Behold i sidebaren", "Key": "Nøgle", "Key is required": "Nøgle er påkrævet", - "Keyboard shortcuts": "Tastaturgenveje", "Keyboard Shortcuts": "Tastaturgenveje", "Knowledge": "Viden", "Knowledge Access": "Videnadgang", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Vidensnavn", "Knowledge Public Sharing": "Viden offentlig deling", "Knowledge Sharing": "Vidensdeling", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Viden opdateret.", "Kokoro.js (Browser)": "Kokoro.js (Browser)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Sidste svar", "LDAP": "LDAP", - "LDAP server updated": "LDAP server opdateret", "Leaderboard": "Lederboard", "Learn more": "", "Learn More": "Lær mere", @@ -1246,6 +1345,7 @@ "Legacy": "Legacy", "lexical": "leksikalsk", "License": "Licens", + "Lifecycle JSON": "", "Lift List": "Løft liste", "Light": "Lys", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Adgang til placering ikke tilladt", "Lost": "Tabt", "Low": "Lav", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Lavet af OpenWebUI Community", "Make password visible in the user interface": "Gør adgangskode synlig i brugergrænsefladen", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Administrer pipelines", "Manage Tool Servers": "Administrer værktøjsservere", "Manage your account information.": "Administrer dine brugerinformationer.", + "Mapped Source": "", "March": "Marts", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Hukommelse ryddet.", "Memory deleted successfully": "Hukommelse slettet.", "Memory updated successfully": "Hukommelse opdateret.", + "Merge Accounts by Email": "", "Merge Responses": "Flet svar", "Merged Response": "Sammensat svar", "Message": "Besked", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Beskeder, du sender efter at have oprettet dit link, deles ikke. Brugere med URL'en vil kunne se den delte chat.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personlig)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (arbejde/skole)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API nøgle påkrævet for Cloud API tilstand.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Modeldeling", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search API nøgle", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Mere", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Navngiv din vidensbase", "Name, prompt, and model are required": "", "Native": "Indbygget", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "Ingen autentificering", "No automations found": "", "No chats found": "Ingen chats fundet", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Ingen afstand tilgængelig", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "Ingen udløbsdato kan udgøre en sikkerhedsrisiko.", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ingen fil valgt", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "Ingen fastgjorte beskeder", "No prompts found": "Ingen prompts fundet", + "No Repeat": "", "No results": "Ingen resultater fundet", "No results found": "Ingen resultater fundet", "No search query generated": "Ingen søgeforespørgsel genereret", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "Node Id'er", "None": "Ingen", + "Not configured": "", "Not factually correct": "Ikke faktuelt korrekt", "Not helpful": "Ikke hjælpsom", "Not Registered": "Ikke registreret", @@ -1498,20 +1611,25 @@ "Notifications": "Notifikationer", "November": "November", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth-ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktober", "Off": "Fra", "Okay, Let's Go!": "Okay, lad os komme i gang!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Mørk", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API indstillinger opdateret", "Ollama Cloud API Key": "Ollama Cloud API nøgle", "Ollama Version": "Ollama-version", + "Omit": "", "On": "Til", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Adgangskode", "Passwords do not match.": "Passwords stemmer ikke overens.", "Paste Large Text as File": "Indsæt store tekster som fil", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF-dokument (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "afventer", "Pending": "Afventer", + "Pending Accounts": "", "Pending User Overlay Content": "Afventende bruger overlay indhold", "Pending User Overlay Title": "Afventende bruger overlay titel", "Permission denied when accessing media devices": "Tilladelse nægtet ved adgang til medieenheder", "Permission denied when accessing microphone": "Tilladelse nægtet ved adgang til mikrofon", "Permission denied when accessing microphone: {{error}}": "Tilladelse nægtet ved adgang til mikrofon: {{error}}", "Permissions": "Tilladelser", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API nøgle", "Perplexity Model": "Perplexity model", "Perplexity Search API URL": "Perplexity Search API URL", "Perplexity Search Context Usage": "Perplexity søgekontekst brug", "Persistent": "", "Personalization": "Personalisering", + "Picture Claim": "", "Pin": "Fastgør", "Pin to Sidebar": "", "Pinned": "Fastgjort", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Udfyld alle felter.", "Please register the OAuth client": "Registrer venligst OAuth-klienten", "Please save the connection to persist the OAuth client information and do not change the ID": "Gem venligst forbindelsen for at bevare OAuth-klientoplysningerne og ændr ikke ID'et", - "Please select a model first.": "Vælg en model først.", "Please select a model.": "Vælg en model.", "Please select a reason": "Vælg en årsag", "Please select a valid JSON file": "Vælg en valid JSON-fil", "Please select at least one user for Direct Message channel.": "Vælg mindst én bruger til direkte besked-kanal.", "Please wait until all files are uploaded.": "Vent venligst indtil alle filerne er uploadet.", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Positiv holdning", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Prompts offentlig deling", "Prompts Sharing": "Promptdeling", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Offentlig", "Pull \"{{searchValue}}\" from Ollama.com": "Hent \"{{searchValue}}\" fra Ollama.com", "Pull a model from Ollama.com": "Hent en model fra Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Læs", "Read Aloud": "Læs højt", "Read more →": "Læs mere →", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "Årsag", "Reasoning Effort": "Ræsonnements indsats", "Reasoning Tags": "Ræsonneringstags", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Optag", "Record voice": "Optag stemme", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Omdirigerer dig til OpenWebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Reducerer sandsynligheden for at generere vrøvl. En højere værdi (f.eks. 100) vil give mere varierede svar, mens en lavere værdi (f.eks. 10) vil være mere konservativ.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referer til dig selv som \"Bruger\" (f.eks. \"Bruger lærer spansk\")", "Reference Chats": "Reference chats", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Afvist, når den ikke burde have været det", "Regenerate": "Regenerer", "Regenerate Menu": "Regenerer menu", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Omarranger modeller", + "Repeat": "", "Repeats": "", "Reply": "Svar", "Reply in Thread": "Svar i tråd", "Reply to thread...": "Svar på tråd...", "Replying to {{NAME}}": "Svarer {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "påkrævet", "Reranking Batch Size": "", "Reranking Engine": "Omarrangerings engine", "Reranking Model": "Omarrangeringsmodel", + "Research Knowledge": "", "Reset": "Nulstil", "Reset All Models": "Nulstil alle modeller", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Nulstil billede", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Nulstil uploadmappe", "Reset Vector Storage/Knowledge": "Nulstil vektor lager/viden", "Reset view": "Nulstil visning", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "Fandt en kildehenvisning", "Rich Text Input for Chat": "Rich text input til chat", "Role": "Rolle", + "Roles Claim": "", "RTL": "RTL", "Run": "Kør", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Lagring af chatlogs direkte i din browsers lager understøttes ikke længere. Download og slet dine chatlogs ved at klikke på knappen nedenfor. Du kan nemt importere dine chatlogs til backend igennem", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Scroll ved gren ændring", "Scroll to Top": "", "Search": "Søg", "Search a model": "Søg efter en model", + "Search actions": "", "Search all emojis": "Søg i alle emojis", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Søg i chats", "Search Collection": "Søg i samling", "Search Files": "", + "Search filters": "", "Search Filters": "Søg i filtre", "search for archived chats": "søg efter arkiverede chats", "search for folders": "søg efter mapper", @@ -1812,13 +1955,16 @@ "Search Models": "Søg i modeller", "Search Notes": "Søg i noter", "Search options": "Søgemuligheder", + "Search or add pattern": "", "Search Prompts": "Søg i prompts", "Search Result Count": "Antal søgeresultater", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Søg internettet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Søg i værktøjer", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API-nøgle", "SearchApi Engine": "SearchApi-engine", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Vælg", "Select {{modelName}} model": "", - "Select a base model": "Vælg en basemodel", "Select a base model (e.g. llama3, gpt-4o)": "Vælg en basemodel (f.eks. llama3, gpt-4o)", "Select a conversation to preview": "Vælg en samtale til forhåndsvisning", "Select a engine": "Vælg en engine", @@ -1872,18 +2017,25 @@ "semantic": "semantisk", "Send": "Send", "Send a Message": "Send en besked", + "Send events for": "", "Send message": "Send besked", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Sender `stream_options: { include_usage: true }` i forespørgslen.\nUnderstøttede udbydere vil returnere tokenforbrugsinformation i svaret, når det er indstillet.", "September": "September", "SerpApi API Key": "SerpApi API nøgle", "SerpApi Engine": "SerpApi engine", "Serper API Key": "Serper API-nøgle", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API-nøgle", "Serpstack API Key": "Serpstack API-nøgle", "Server connection failed": "", "Server connection verified": "Serverforbindelse bekræftet", + "Service Account": "", "Session": "Session", + "Session expired. Please sign in again.": "", "Set as default": "Indstil som standard", "Set as Production": "", "Set embedding model": "Indstil indlejringsmodel", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Del til OpenWebUI Community", "Share your background and interests": "Del din baggrund og interesser", + "Shared": "", "Shared Chats": "", "Shared with you": "Delt med dig", "Sharing Permissions": "Delingstilladelser", "Show": "Vis", - "Show \"What's New\" modal on login": "Vis \"Hvad er nyt\" modal ved login", + "Show \"What's New\" Modal on Login": "Vis \"Hvad er nyt\" modal ved login", "Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i overlay for ventende konto", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Vis formateringsværktøjslinjen", "Show image preview": "Vis billedforhåndsvisning", "Show Model": "Vis model", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Kilde", + "Specific users or groups": "", "Speech Playback Speed": "Talehastighed", "Speech recognition error: {{error}}": "Talegenkendelsesfejl: {{error}}", "Speech-to-Text": "Tale-til-tekst", @@ -1999,6 +2154,7 @@ "STT Settings": "STT-indstillinger", "Stylized PDF Export": "Stiliseret PDF eksport", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "Undertekst", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "System", + "System events only": "", "System Instructions": "Systeminstruktioner", "System Prompt": "Systemprompt", + "Table": "", "Tag": "Tag", "Tags": "Tags", "Tags Generation": "Tag generering", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Midlertidig chat per standard", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Tekstopdeler", "Text-to-Speech": "Tekst-til-tale", "Text-to-Speech Engine": "Tekst-til-tale-engine", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Sproget for input-lyden. At angive input-sproget i ISO-639-1 (f.eks. da) format vil forbedre nøjagtighed og ventetid. Lad være tom for automatisk sprogregistrering.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP-attributten der mapper til den mail brugere bruger til at logge ind.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP-attributten der mapper til det brugernavn brugere bruger til at logge ind.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Lederbordet er i øjeblikket i beta, og vi kan justere rating-beregningerne, mens vi forfiner algoritmen.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Den maksimale filstørrelse i MB. Hvis filstørrelsen overstiger denne grænse, uploades filen ikke.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Det maksimale antal filer, der kan bruges på én gang i chatten. Hvis antallet af filer overstiger denne grænse, uploades filerne ikke.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Output-formatet for teksten. Kan være 'json', 'markdown' eller 'html'. Standard er 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "Dette er en standardbrugertilladelse og vil forblive aktiveret.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dette er en eksperimentel funktion, den fungerer muligvis ikke som forventet og kan ændres når som helst.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Denne model er ikke offentligt tilgængelig. Vælg venligst en anden model.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Denne indstilling styrer hvor længe modellen forbliver indlæst i hukommelsen efter forespørgslen (standard: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Denne indstilling styrer hvor mange tokens der bevares ved opdatering af konteksten. For eksempel, hvis sat til 2, vil de sidste 2 tokens af samtale-konteksten blive bevaret. At bevare kontekst kan hjælpe med at opretholde kontinuiteten i en samtale, men det kan reducere evnen til at reagere på nye emner.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "For at lære mere om tilgængelige endpoints, besøg vores dokumentation.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "For at vælge værktøjssæt her skal du først tilføje dem til \"Værktøjer\"-arbejdsområdet.", - "Toast notifications for new updates": "Toast-notifikationer for nye opdateringer", + "Toast Notifications for New Updates": "Toast-notifikationer for nye opdateringer", "Today": "I dag", "Today at": "", "Today at {{LOCALIZED_TIME}}": "I dag {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Skift om nuværende forbindelse er aktiv.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "For ordrigt", @@ -2184,14 +2350,19 @@ "Unpin": "Frigør", "Unpin from Sidebar": "", "Unravel secrets": "Afslør hemmeligheder", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "Ikke-understøttet filtype.", "Untagged": "Uden mærker", "Untitled": "Unavngivet", "Update": "Opdater", "Update and Copy Link": "Opdater og kopier link", + "Update Email": "", "Update for the latest features and improvements.": "Opdater for at få de nyeste funktioner og forbedringer.", + "Update Name": "", "Update password": "Opdater adgangskode", + "Update Picture": "", "Update your status": "Opdater din status", "Updated": "Opdateret", "Updated at": "Opdateret kl.", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Brug '#' i promptinput for at indlæse og inkludere din viden.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Brug /v1/chat/completions endpointet i stedet for /v1/audio/transcriptions for potentielt øget nøjagtighed.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Brug Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Brug LLM", "Use no proxy to fetch page contents.": "Brug ingen proxy til at hente sideindhold.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Brug proxy angivet af http_proxy og https_proxy miljøvariabler til at hente sideindhold.", + "Use Web Search?": "", "user": "bruger", "User": "Bruger", + "User Access": "", "User Activity": "", "User Groups": "Brugergrupper", "User location successfully retrieved.": "Brugerplacering hentet.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Bruger Webhooks", "Username": "Brugernavn", + "Username Claim": "", "users": "brugere", "Users": "Brugere", "Uses DefaultAzureCredential to authenticate": "Bruger DefaultAzureCredential til at autentificere", @@ -2247,6 +2424,7 @@ "Valves updated": "Ventiler opdateret", "Valves updated successfully": "Ventiler opdateret.", "variable": "variabel", + "Vector Field": "", "Verify Connection": "Verificer forbindelse", "Verify SSL Certificate": "Verificer SSL-certifikat", "Version": "Version", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "Web indlæser motor", "Web Search": "Websøgning", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Websøgemaskine", "Web Search in Chat": "Websøgning i chat", "Web Search Query Generation": "Web søgeforespørgsel generering", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook-URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI-indstillinger", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "I går", "Yesterday at {{LOCALIZED_TIME}}": "I går klokken {{LOCALIZED_TIME}}", "You": "Du", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hele dit bidrag går direkte til plugin-udvikleren; Open WebUI tager ikke nogen procentdel. Den valgte finansieringsplatform kan dog have sine egne gebyrer.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube sprog", diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index bc583f1958..1dbc3562b0 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -9,28 +9,36 @@ "[Today at] h:mm A": "[Heute um] h:mm A", "[Yesterday at] h:mm A": "[Gestern um] h:mm A", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Skills": "", + "{{COUNT}} Available Skills": "{{COUNT}} verfügbare Skills", "{{COUNT}} Available Tools": "{{COUNT}} verfügbare Werkzeuge", "{{COUNT}} characters": "{{COUNT}} Zeichen", "{{COUNT}} extracted lines": "{{COUNT}} extrahierte Zeilen", "{{COUNT}} files": "{{COUNT}} Dateien", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "{{count}} Datei ausgewählt. Es werden nur neue und geänderte Dateien hochgeladen. Gelöschte Dateien werden entfernt. Die Ordnerstruktur wird gespiegelt. Fortfahren?", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "{{count}} Dateien ausgewählt. Es werden nur neue und geänderte Dateien hochgeladen. Gelöschte Dateien werden entfernt. Die Ordnerstruktur wird gespiegelt. Fortfahren?", + "{{count}} filters_one": "{{count}} Filter", + "{{count}} filters_other": "{{count}} Filter", + "{{count}} groups_one": "{{count}} Gruppe", + "{{count}} groups_other": "{{count}} Gruppen", "{{COUNT}} hidden lines": "{{COUNT}} ausgeblendete Zeilen", "{{COUNT}} members": "{{COUNT}} Mitglieder", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}} von {{total}} zugänglich", + "{{count}} of {{total}} accessible_other": "{{count}} von {{total}} zugänglich", "{{COUNT}} Replies": "{{COUNT}} Antworten", "{{COUNT}} Rows": "{{COUNT}} Reihen", "{{count}} selected_one": "{{count}} ausgewählt", "{{count}} selected_other": "{{count}} ausgewählt", "{{COUNT}} Sources": "{{COUNT}} Quellen", + "{{count}} users_one": "{{count}} Benutzer", + "{{count}} users_other": "{{count}} Benutzer", "{{COUNT}} words": "{{COUNT}} Wörter", "{{COUNT}}d_time_ago": "{{COUNT}} T", "{{COUNT}}h_time_ago": "{{COUNT}} h", "{{COUNT}}m_time_ago": "{{COUNT}} min", "{{COUNT}}w_time_ago": "{{COUNT}} W", "{{COUNT}}y_time_ago": "{{COUNT}} J", + "{{label}} contains invalid JSON": "{{label}} enthält ungültiges JSON", + "{{label}} must be a JSON object": "{{label}} muss ein JSON-Objekt sein", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} um {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Der Download von {{model}} wurde abgebrochen", "{{modelName}} profile image": "{{modelName}} Profil Bild", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Chats von {{user}}", "{{webUIName}} Backend Required": "{{webUIName}}-Backend erforderlich", "*Prompt node ID(s) are required for image generation": "*Prompt-Node-ID(s) sind für die Bildgenerierung erforderlich", + "1 group": "1 Gruppe", "1 hour before": "1 Stunde vor", "1 Source": "1 Quelle", + "1 user": "1 Benutzer", "10 minutes before": "10 Minuten vor", "15 minutes before": "15 Minuten vor", "1m_time_ago": "vor 1 Minute", @@ -57,6 +67,7 @@ "Access Control": "Zugriffskontrolle", "Access Grants": "Zugriffsrechte", "Access List": "Zugriffsliste", + "Access prohibited": "Zugriff verboten", "Access updated": "Zugriff aktualisiert", "Accessible to all users": "Für alle Benutzer zugänglich", "Account": "Konto", @@ -72,6 +83,7 @@ "Activity": "Aktivität", "Add": "Hinzufügen", "Add a model ID": "Modell-ID hinzufügen", + "Add a preference, fact, or instruction about you": "Eine Präferenz, einen Fakt oder eine Anweisung über sich hinzufügen", "Add a short description about what this model does": "Fügen Sie eine kurze Beschreibung der Funktion dieses Modells hinzu", "Add a tag": "Tag hinzufügen", "Add a tag...": "Tag hinzufügen...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Benutzerdefinierten Prompt hinzufügen", "Add description": "Beschreibung hinzufügen", "Add Details": "Details hinzufügen", + "Add durable context for future chats": "Dauerhaften Kontext für zukünftige Chats hinzufügen", "Add Files": "Dateien hinzufügen", "Add Image": "Bild hinzufügen", + "Add Knowledge Connection": "Wissensverbindung hinzufügen", "Add location": "Ort hinzufügen", "Add Member": "Mitglied hinzufügen", "Add Members": "Mitglieder hinzufügen", @@ -100,6 +114,7 @@ "Add to favorites": "Zu Favoriten hinzufügen", "Add User": "Benutzer hinzufügen", "Add User Group": "Benutzergruppe hinzufügen", + "Add webhook": "Webhook hinzufügen", "Add webpage": "Webseite hinzufügen", "Add your Open Terminal URL and API key in Settings → Integrations.": "Füge deine Open Terminal URL und API Key in den Einstellungen → Integrationen hinzu.", "Additional Config": "Zusätzliche Konfiguration", @@ -112,7 +127,9 @@ "Admin": "Administrator", "Admin Contact Email": "Admin Kontakt E-Mail", "Admin Panel": "Admin-Bereich", + "Admin Roles": "Administratorrollen", "Admin Settings": "Admin-Einstellungen", + "Admin-managed service account": "Vom Administrator verwaltetes Dienstkonto", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratoren haben jederzeit Zugriff auf alle Werkzeuge; Benutzern müssen Werkzeuge pro Modell im Arbeitsbereich zugewiesen werden.", "Advanced": "Erweitert", "Advanced Parameters": "Erweiterte Parameter", @@ -123,16 +140,21 @@ "All": "Alle", "All chats have been unarchived.": "Alle Chats wurden aus dem Archiv wiederhergestellt.", "All day": "Ganzer Tag", + "All events": "Alle Ereignisse", "All models are now hidden": "Alle Modelle sind nun versteckt", "All models are now visible": "Alle Modelle sind nun sichtbar", "All models deleted successfully": "Alle Modelle erfolgreich gelöscht", + "All shared chats have been unshared.": "Die Freigabe aller geteilten Chats wurde aufgehoben.", + "All Sources": "Alle Quellen", "All time": "Gesamte Zeit", "All Users": "Alle Nutzer", + "All users and system events": "Alle Benutzer- und Systemereignisse", "Allow Call": "Anruffunktion erlauben", "Allow Chat Controls": "Chat-Steuerung erlauben", "Allow Chat Delete": "Löschen von Chats erlauben", "Allow Chat Edit": "Bearbeiten von Chats erlauben", "Allow Chat Export": "Chat-Export erlauben", + "Allow Chat Import": "Chat-Import erlauben", "Allow Chat Params": "Chat-Parameter erlauben", "Allow Chat Share": "Chat-Teilen erlauben", "Allow Chat System Prompt": "Chat-System-Prompt erlauben", @@ -152,9 +174,11 @@ "Allow User Location": "Standortzugriff erlauben", "Allow Voice Interruption in Call": "Unterbrechung durch Stimme im Anruf zulassen", "Allow Web Upload": "Webseiten Upload erlauben", + "Allowed Domains": "Erlaubte Domains", "Allowed Endpoints": "Erlaubte Endpunkte", "Allowed File Extensions": "Erlaubte Dateiendungen", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Erlaubte Dateiendungen für den Upload. Trennen Sie mehrere Endungen mit Kommas. Leer lassen, um alle Dateitypen zu erlauben.", + "Allowed Roles": "Erlaubte Rollen", "Already have an account?": "Bereits registriert?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Eine Alternative zu top_p, die ein Gleichgewicht zwischen Qualität und Vielfalt anstrebt. Der Parameter p stellt die Mindestwahrscheinlichkeit dar, mit der ein Token relativ zur Wahrscheinlichkeit des wahrscheinlichsten Tokens berücksichtigt wird. Wenn z. B. p = 0.05 ist und das wahrscheinlichste Token eine Wahrscheinlichkeit von 0.9 hat, werden Logits mit einem Wert kleiner als 0.045 gefiltert.", "Always": "Immer", @@ -173,12 +197,13 @@ "API Base URL": "API-Basis-URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API-Basis-URL für den Datalab Marker-Dienst. Standardwert: https://www.datalab.to/api/v1/marker", "API Key": "API-Schlüssel", + "API Key / Token": "API-Schlüssel / Token", "API Key created.": "API-Schlüssel erstellt.", "API Key Endpoint Restrictions": "API-Schlüssel Endpunkteinschränkungen", "API keys": "API-Schlüssel", "API Keys": "API-Schlüssel", "API Mode": "API-Modus", - "API Timeout": "API Timeout", + "API Timeout": "API-Timeout", "API Type": "API Typ", "API Version": "API-Version", "API Version is required": "API-Version ist erforderlich", @@ -198,17 +223,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "Sind Sie sicher, dass Sie alle Chats löschen wollen? Dieser Vorgang kann nicht rückgängig gemacht werden.", "Are you sure you want to delete this channel?": "Sind Sie sicher, dass Sie diesen Kanal löschen möchten?", "Are you sure you want to delete this connection? This action cannot be undone.": "Möchten Sie diese Verbindung wirklich löschen? Dieser Vorgang kann nicht rückgängig gemacht werden.", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "Sind Sie sicher, dass Sie dieses Verzeichnis löschen möchten?", "Are you sure you want to delete this memory? This action cannot be undone.": "Möchten Sie diese Erinnerung wirklich löschen? Dieser Vorgang kann nicht rückgängig gemacht werden.", "Are you sure you want to delete this message?": "Sind Sie sicher, dass Sie diese Nachricht löschen möchten?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Sind Sie sicher, dass Sie diese Version löschen wollen? Child-Versionen werden zu dem Parent dieser Version verlinkt.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "Sind Sie sicher, dass Sie diesen Webhook löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.", "Are you sure you want to delete this?": "Sind Sie sicher, dass Sie das löschen wollen?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "Sind Sie sicher, dass Sie alle Berechtigungen auf ihre Standardwerte zurücksetzen möchten? Sie müssen dennoch speichern, um die Änderungen anzuwenden.", "Are you sure you want to unarchive all archived chats?": "Sind Sie sicher, dass Sie alle archivierten Chats wiederherstellen möchten?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "Sind Sie sicher, dass Sie die Freigabe aller geteilten Chats aufheben möchten? Dadurch werden alle Freigabe-Links entfernt.", "Arena Models": "Arena-Modelle", "Artifacts": "Artefakte", "Asc": "Aufsteigend", "Ask": "Fragen", "Ask a question": "Stellen Sie eine Frage", + "Ask a test question": "Eine Testfrage stellen", + "Ask this knowledge source a test question": "Dieser Wissensquelle eine Testfrage stellen", "Assistant": "Assistent", "Async Embedding Processing": "Asynchrone Embedding-Verarbeitung", "At time of event": "Zum Zeitpunkt des Ereignisses", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "August", "Auth": "Authentifizierung", + "Auth Mode": "Authentifizierungsmodus", + "Auth required": "Authentifizierung notwendig", "Authenticate": "Authentifizieren", "Authentication": "Authentifizierung", "Auto": "Automatisch", "Auto (Random)": "Auto (zufällig)", + "Auto Redirect": "Automatische Weiterleitung", "Auto-Copy Response to Clipboard": "Antwort autom. in Zwischenablage kopieren", - "Auto-playback response": "Antwort automatisch abspielen", + "Auto-Create Groups": "Gruppen automatisch erstellen", + "Auto-Playback Response": "Antwort automatisch abspielen", "Autocomplete Generation": "Autovervollständigung", "Autocomplete Generation Input Max Length": "Max. Eingabelänge für Autovervollständigung", + "Autocomplete Generation Prompt": "Prompt für Autovervollständigung", + "Automatic": "Automatisch", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API-Auth-String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Basis-URL", @@ -245,9 +281,10 @@ "Automations": "Automatisierungen", "Available list": "Verfügbare Liste", "Available models": "Verfügbare Modelle", - "Available Skills": "", + "Available Skills": "Verfügbare Skills", "Available Tools": "Verfügbare Werkzeuge", "available users": "verfügbare Benutzer", + "Available variables": "Verfügbare Variablen", "available!": "Verfügbar!", "Away": "Abwesend", "Awful": "Schrecklich", @@ -258,16 +295,17 @@ "Bad Response": "Schlechte Antwort", "Banners": "Banner", "Base Model (From)": "Basismodell (Von)", + "Base Model is required.": "Basis Modell ist notwendig.", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Der Cache für die Basismodell-Liste beschleunigt den Zugriff, indem Basismodelle nur beim Start oder Speichern abgerufen werden – schneller, zeigt aber evtl. keine aktuellen Änderungen an.", "Bearer": "Bearer", "before": "zuvor", "Being lazy": "Faulheit", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 Endpunkt", "Bing Search V7 Subscription Key": "Bing Search V7 Abonnement-Schlüssel", "Bio": "Biografie", "Birth Date": "Geburtsdatum", + "Blocked Groups": "Blockierte Gruppen", "BM25 Weight": "BM25-Gewichtung", "Bocha Search API Key": "Bocha Search API-Schlüssel", "Bold": "Fett", @@ -324,9 +362,9 @@ "Chat Completions": "Chat Completions", "Chat Conversation": "Chat-Unterhaltung", "Chat deleted.": "Chat gelöscht.", - "Chat direction": "Chat-Ausrichtung", + "Chat Direction": "Chat-Ausrichtung", "Chat exported successfully": "Chat erfolgreich exportiert", - "Chat History": "Chat History", + "Chat History": "Chatverlauf", "Chat ID": "Chat-ID", "Chat moved successfully": "Chat erfolgreich verschoben", "Chat Permissions": "Chat-Berechtigungen", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Kollaborationskanal, dem Benutzer beitreten können", "Collapse": "Einklappen", "Collection": "Sammlung", + "Collection Field": "Collection-Feld", "Collections": "Sammlungen", "Color": "Farbe", "ComfyUI": "ComfyUI", @@ -405,17 +444,19 @@ "ComfyUI Workflow": "ComfyUI-Workflow", "ComfyUI Workflow Nodes": "ComfyUI-Workflow-Nodes", "Comma separated Node Ids (e.g. 1 or 1,2)": "Kommagetrennte Node-IDs (z. B. 1 oder 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "Durch Kommata getrennte Gruppennamen", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Durch Kommata getrennte Liste von Dateierweiterungen, die MinerU verarbeitet (z. B. pdf, docx, pptx, xlsx)", "command": "Befehl", "Command": "Befehl", "Comment": "Kommentar", "Commit Message": "Commit Nachricht", "Community Reviews": "Community Bewertungen", - "Comparing with knowledge base...": "", + "Compacting context": "Kontext wird verdichtet", + "Comparing with knowledge base...": "Vergleich mit Wissensspeicher...", "Completions": "Vervollständigungen", "Compress Images in Channels": "Bilder in Kanälen komprimieren", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Prüfsummen werden berechnet ({{count}} Datei)", + "Computing checksums ({{count}} files)_other": "Prüfsummen werden berechnet ({{count}} Dateien)", "Concurrent Requests": "Gleichzeitige Anfragen", "Config": "Konfiguration", "Config imported successfully": "Konfiguration erfolgreich importiert", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Verbinde zu Open Terminal Instanzen. AAlle Nutzer werden Zugriff auf die Dateien und Terminal Werkzeige durch diese Server bekommen.", "Connect to your own OpenAI compatible API endpoints.": "Verbinden Sie Ihre eigenen OpenAI-kompatiblen API-Endpunkte.", "Connect to your own OpenAPI compatible external tool servers.": "Verbinden Sie Ihre eigenen OpenAPI-kompatiblen externen Tool-Server.", + "Connected": "Verbunden", "Connected ({{type}})": "Verbunden ({{type}})", "Connection failed": "Verbindung fehlgeschlagen", "Connection lost. Reconnecting...": "Verbindung unterbrochen. Verbinde neu...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Kontaktieren Sie den Administrator für WebUI-Zugriff", "Content": "Inhalt", "Content Extraction Engine": "Engine zur Inhaltsextraktion", + "Content Field": "Inhaltsfeld", "Content lengths (character counts only)": "Content-Längen (nur Zeichen)", + "Context": "Kontext", + "Context compacted": "Kontext verdichtet", + "Context Compaction": "Kontextverdichtung", + "Context compaction failed": "Kontextverdichtung fehlgeschlagen", + "Context Compaction Prompt": "Prompt für Kontextverdichtung", + "Context Compaction Threshold": "Schwellenwert für Kontextverdichtung", "Context Tokens": "Kontext-Token", + "Continue": "Fortfahren", "Continue Response": "Antwort fortsetzen", "Continue with {{provider}}": "Mit {{provider}} fortfahren", "Continue with Email": "Mit E-Mail fortfahren", @@ -493,6 +543,7 @@ "Create new secret key": "Neuen Geheimschlüssel erstellen", "Create note": "Notiz erstellen", "Create Note": "Notiz erstellen", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "Pro externer Collection eine schreibgeschützte Wissensquelle erstellen. Der Test muss erfolgreich sein, bevor die Quelle erstellt wird.", "Create scheduled prompts that run automatically on a recurring basis.": "Erstelle geplante Prompts, die automatisch in regelmäßigen Abständen ausgeführt werden.", "Create your first note by clicking on the plus button below.": "Erstellen Sie Ihre erste Notiz durch Klick auf das Plus-Symbol unten.", "Created at": "Erstellt am", @@ -510,6 +561,7 @@ "Custom Gender": "Benutzerdefiniertes Geschlecht", "Custom Parameter Name": "Name des benutzerdef. Parameters", "Custom Parameter Value": "Wert des benutzerdef. Parameters", + "Custom range": "Benutzerdefinierter Bereich", "Daily": "Täglich", "Daily Messages": "Tägliche Nachrichten", "Danger Zone": "Gefahrenzone", @@ -519,7 +571,7 @@ "Datalab Marker API": "Datalab Marker API", "Date Modified": "Datum geändert", "Day": "Tag", - "DD/MM/YYYY": "TT.MM.JJJJ", + "DD/MM/YYYY": "DD.MM.YYYY", "DDGS Backend": "DDGS Backend", "December": "Dezember", "Decrease UI Scale": "UI-Skalierung verringern", @@ -532,7 +584,6 @@ "Default Features": "Standardfunktionen", "Default Filters": "Standardfilter", "Default Group": "Standardgruppe", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Der Standardmodus funktioniert mit mehr Modellen, indem Werkzeuge vor der Ausführung aufgerufen werden. Der native Modus nutzt die integrierte Tool-Calling-Fähigkeit des Modells, setzt diese aber voraus.", "Default Model": "Standardmodell", "Default model updated": "Standardmodell aktualisiert", "Default permissions": "Standardberechtigungen", @@ -542,20 +593,21 @@ "Default to ALL": "Standardmäßig ALLE", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Standardmäßig segmentierter Abruf für fokussierte Inhaltsextraktion (empfohlen).", "Default User Role": "Standard-Benutzerrolle", + "Default webhook": "Standard-Webhook", "Defaults": "Standardwerte", "Delete": "Löschen", "Delete {{name}}": "{{name}} löschen", "Delete a model": "Ein Modell löschen", "Delete All": "Alle löschen", "Delete All Chats": "Alle Chats löschen", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Alle Inhalte in diesem Verzeichnis löschen", "Delete all contents inside this folder": "Alle Inhalte in diesem Ordner löschen", "Delete automation?": "Automatisierung löschen?", "Delete calendar": "Kalender löschen", "Delete Calendar": "Kalender löschen", "Delete Chat": "Chat löschen", "Delete chat?": "Chat löschen?", - "Delete directory?": "", + "Delete directory?": "Verzeichnis löschen?", "Delete Event": "Ereignis löschen", "Delete File": "Datei löschen", "Delete folder?": "Ordner löschen?", @@ -592,16 +644,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Direktverbindungen erlauben Benutzern die Verbindung zu eigenen OpenAI-kompatiblen API-Endpunkten.", "Direct Message": "Direktnachricht", "Direct Tool Servers": "Direkte Tool-Server", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Verzeichnis erstellt.", + "Directory deleted.": "Verzeichnis gelöscht.", + "Directory moved.": "Verzeichnis verschoben.", + "Directory name": "Verzeichnisname", + "Directory renamed.": "Verzeichnis umbenannt.", "Directory selection was cancelled": "Verzeichnisauswahl wurde abgebrochen", "Disable All": "Alle deaktivieren", "Disable Code Interpreter": "Code-Interpreter deaktivieren", "Disable Image Extraction": "Bildextraktion deaktivieren", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Deaktiviert Bildextraktion aus PDFs. Wenn 'LLM verwenden' aktiv ist, werden Bilder automatisch beschriftet. Standard: False.", + "Disable Image Generation": "Bildgenerierung deaktivieren", + "Disable Web Search": "Websuche deaktivieren", "Disabled": "Deaktiviert", "Disconnect OAuth": "OAuth trennen", "Discover a function": "Funktion entdecken", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Modellvorlagen entdecken und herunterladen", "Discussion channel where access is based on groups and permissions": "Diskussionskanal mit gruppenbasiertem Zugriff", "Display": "Anzeige", - "Display chat title in tab": "Chat-Titel im Tab anzeigen", + "Display Chat Title in Tab": "Chat-Titel im Tab anzeigen", "Display Emoji in Call": "Emojis im Anruf anzeigen", "Display Multi-model Responses in Tabs": "Antworten mehrerer Modelle in Tabs anzeigen", - "Display the username instead of You in the Chat": "Benutzernamen statt 'Sie' im Chat anzeigen", + "Display the Username Instead of You in the Chat": "Benutzernamen statt 'Sie' im Chat anzeigen", "Displays citations in the response": "Zeigt Zitate in der Antwort an", "Displays status updates (e.g., web search progress) in the response": "Zeigt Status-Updates (z. B. Websuche) in der Antwort an", "Dive into knowledge": "In Wissen eintauchen", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling-Parameter", "Docling Server URL required.": "Docling Server-URL erforderlich.", "Document": "Dokument", + "Document ID Field": "Dokument-ID-Feld", "Document Intelligence": "Dokumentenintelligenz", "Document Intelligence endpoint required.": "Dokumentenintelligenz-Endpunkt erforderlich.", "Document Intelligence Model": "Dokumentenintelligenz-Modell", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Standardberechtigungen bearbeiten", "Edit Folder": "Ordner bearbeiten", "Edit Image": "Bild bearbeiten", + "Edit Knowledge Connection": "Wissensverbindung bearbeiten", "Edit Last Message": "Letzte Nachricht bearbeiten", "Edit Memory": "Erinnerung bearbeiten", "Edit Prompt": "Prompt editieren", "Edit Terminal Connection": "Terminal Verbindung bearbeiten", "Edit User": "Benutzer bearbeiten", "Edit User Group": "Benutzergruppe bearbeiten", + "Edit webhook": "Webhook bearbeiten", "Edit workflow.json content": "workflow.json Inhalt bearbeiten", "edited": "bearbeitet", "Edited": "Bearbeitet", @@ -699,14 +756,16 @@ "Eject model": "Modell auswerfen", "ElevenLabs": "ElevenLabs", "Email": "E-Mail", + "Email Claim": "E-Mail-Claim", "Embark on adventures": "Abenteuer beginnen", "Embedding": "Embedding", "Embedding Batch Size": "Embedding-Batch-Größe", "Embedding Concurrent Requests": "Gleichzeitige Embedding Anfragen", "Embedding Model": "Embedding-Modell", "Embedding Model Engine": "Embedding-Modell-Engine", - "Emoji": "", + "Emoji": "Emoji", "Emojis": "Emoji", + "Empty": "Leer", "Empty message": "Leere Nachricht", "Enable All": "Alle aktivieren", "Enable API Keys": "API-Schlüssel aktivieren", @@ -714,22 +773,27 @@ "Enable Code Execution": "Codeausführung aktivieren", "Enable Code Interpreter": "Code-Interpreter aktivieren", "Enable Community Sharing": "Community-Sharing aktivieren", + "Enable Group Mapping": "Gruppenzuordnung aktivieren", + "Enable Image Generation": "Bildgenerierung aktivieren", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Aktiviert Memory Locking (mlock), um das Auslagern von Modelldaten aus dem RAM zu verhindern. Dies sperrt den Arbeitsspeicherbereich des Modells und sichert schnellen Datenzugriff sowie konstante Leistung.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Aktiviert Memory Mapping (mmap) zum Laden von Modelldaten. Dies nutzt Festplattenspeicher als RAM-Erweiterung, was die Leistung durch schnelleren Datenzugriff verbessern kann, jedoch viel Speicherplatz benötigt und systemabhängig ist.", "Enable Message Queue": "Nachrichten Queue aktivieren", "Enable Message Rating": "Nachrichtenbewertung aktivieren", "Enable Mirostat sampling for controlling perplexity.": "Mirostat-Sampling zur Perplexitätskontrolle aktivieren.", "Enable New Sign Ups": "Neue Registrierungen erlauben", + "Enable OAuth Signup": "OAuth-Registrierung aktivieren", + "Enable Role Mapping": "Rollenzuordnung aktivieren", + "Enable Web Search": "Websuche aktivieren", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Aktivieren, deaktivieren oder passen Sie Reasoning-Tags an. \"Aktiviert\" nutzt Standard-Tags, \"Deaktiviert\" schaltet sie aus, \"Benutzerdefiniert\" erlaubt eigene Start/End-Tags.", "Enabled": "Aktiviert", "End Tag": "End-Tag", + "Endpoint": "Endpunkt", "Endpoint URL": "Endpunkt-URL", "Enforce Temporary Chat": "Temporären Chat erzwingen", "Enhance": "Verbessern", "Enrich Hybrid Search Text": "Hybrid-Suchtext anreichern", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Die CSV-Datei muss 4 Spalten in dieser Reihenfolge enthalten: Name, E-Mail, Passwort, Rolle.", "Enter {{role}} message here": "{{role}}-Nachricht hier eingeben", - "Enter a detail about yourself for your LLMs to recall": "Geben Sie ein Detail über sich an, an das sich LLMs erinnern sollen", "Enter a title for the pending user info overlay. Leave empty for default.": "Titel für das Overlay 'Ausstehende Aktivierung'. Leer lassen für Standard.", "Enter a watermark for the response. Leave empty for none.": "Wasserzeichen für die Antwort. Leer lassen für keines.", "Enter additional headers in JSON format": "Zusätzliche Header im JSON-Format eingeben", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Zielwert für minimale Chunk-Größe eingeben", "Enter Chunk Overlap": "Chunk-Überlappung eingeben", "Enter Chunk Size": "Chunk-Größe eingeben", + "Enter Client ID": "Client-ID eingeben", + "Enter Client Secret": "Client Secret eingeben", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Kommagetrennte \"token:bias_value\"-Paare eingeben (Bsp: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Inhalt für das Overlay 'Ausstehende Aktivierung'. Leer lassen für Standard.", "Enter coordinates (e.g. 51.505, -0.09)": "Koordinaten eingeben (z. B. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter-URL eingeben", "Enter Kagi Search API Key": "Kagi Search API-Schlüssel eingeben", "Enter Key Behavior": "Eingabetasten-Verhalten", + "Enter language": "Sprache eingeben", "Enter language codes": "Sprachcodes eingeben", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Linkup-API-Schlüssel eingeben", + "Enter Microsoft Web IQ API Base URL": "Microsoft Web IQ API-Basis-URL eingeben", + "Enter Microsoft Web IQ API Key": "Microsoft Web IQ API-Schlüssel eingeben", "Enter MinerU API Key": "MinerU-API-Schlüssel eingeben", "Enter Mistral API Base URL": "Mistral API Basis-URL eingeben", "Enter Mistral API Key": "Mistral API-Schlüssel eingeben", @@ -804,6 +873,7 @@ "Enter prompt here.": "Prompt hier eingeben.", "Enter proxy URL (e.g. https://user:password@host:port)": "Proxy-URL eingeben (z. B. https://user:password@host:port)", "Enter reasoning effort": "Reasoning Effort eingeben", + "Enter Redirect URI": "Redirect-URI eingeben", "Enter Score": "Wertung eingeben", "Enter SearchApi API Key": "SearchApi API-Schlüssel eingeben", "Enter SearchApi Engine": "SearchApi Engine eingeben", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API-Schlüssel eingeben", "Enter SerpApi Engine": "SerpApi Engine eingeben", "Enter Serper API Key": "Serper API-Schlüssel eingeben", + "Enter SERPHouse API Key": "SERPHouse-API-Schlüssel eingeben", "Enter Serply API Key": "Serply API-Schlüssel eingeben", "Enter Serpstack API Key": "Serpstack API-Schlüssel eingeben", "Enter server host": "Server-Host eingeben", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Tika Server-URL eingeben", "Enter timeout in seconds": "Timeout in Sekunden eingeben", "Enter to Send": "Enter zum Senden", + "Enter token threshold": "Token-Schwellenwert eingeben", + "Enter Tokenizer Model": "Tokenizer Modell eingeben", "Enter Top K": "Top K eingeben", "Enter Top K Reranker": "Top K Reranker eingeben", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL eingeben (z. B. http://127.0.0.1:7860/)", @@ -860,7 +933,7 @@ "Enter your webhook URL": "Webhook-URL eingeben", "Entra ID": "Entra ID", "Environment Variables": "Umgebungsvariablen", - "Ephemeral": "Ephemeral", + "Ephemeral": "Flüchtig", "Error": "Fehler", "ERROR": "FEHLER", "Error accessing directory": "Fehler beim Zugriff auf das Verzeichnis", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Fehler: Ein Modell mit der ID '{{modelId}}' existiert bereits. Bitte wählen Sie eine andere ID.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Fehler: Die Modell-ID darf nicht leer sein. Bitte geben Sie eine gültige ID ein.", "Evaluations": "Evaluationen", + "Event": "Ereignis", "Event created": "Ereignis erstellt", "Event deleted": "Ereignis gelöscht", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "Ereignisnamen können sich mit der Weiterentwicklung von Open WebUI ändern. Verwenden Sie breite Muster wie user.* für Integrationen, die über neue verwandte Ereignisse hinweg fortbestehen sollen.", "Event title": "Ereignistitel", "Event updated": "Ereignis aktualisiert", + "Events": "Ereignisse", "Exa API Key": "Exa API-Schlüssel", + "Example": "Beispiel", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Bsp: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Bsp: ALL", "Example: mail": "Bsp: mail", @@ -905,12 +982,18 @@ "Export Config": "Konfiguration exportieren", "Export Models": "Modelle exportieren", "Export Prompts": "Prompts exportieren", + "Export Skills": "Skills exportieren", "Export to CSV": "Nach CSV exportieren", "Export Tools": "Werkzeuge exportieren", "Export Users": "Benutzer exportieren", "External": "Extern", + "External connection not found.": "Externe Verbindung nicht gefunden.", "External Document Loader URL required.": "URL für ext. Dokumenten-Loader erforderlich.", + "External Knowledge Source": "Externe Wissensquelle", + "External Knowledge Sources": "Externe Wissensquellen", "External Task Model": "Externes Aufgabenmodell", + "External Tool Servers": "Externe Werkzeug-Server", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "Externe Vektoren müssen mit demselben Embedding-Modell erzeugt werden, das in Open WebUI konfiguriert ist.", "External Web Loader API Key": "API-Schlüssel für ext. Web-Loader", "External Web Loader URL": "URL für ext. Web-Loader", "External Web Search API Key": "API-Schlüssel für ext. Websuche", @@ -921,13 +1004,14 @@ "Failed to archive chat.": "Chat konnte nicht archiviert werden.", "Failed to attach file": "Datei konnte nicht hinzugefügt werden", "Failed to clear status": "Status konnte nicht geleert werden", - "Failed to compare files.": "", + "Failed to compare files.": "Dateien konnten nicht verglichen werden.", "Failed to connect to {{URL}} OpenAPI tool server": "Verbindung zum OpenAPI-Toolserver {{URL}} fehlgeschlagen", "Failed to connect to {{URL}} terminal server": "Fehler beim Verbinden zum Terminal Server {{URL}}", "Failed to copy link": "Link konnte nicht kopiert werden", "Failed to create API Key.": "API-Schlüssel konnte nicht erstellt werden.", "Failed to delete calendar": "Kalender konnte nicht gelöscht werden", "Failed to delete note": "Notiz konnte nicht gelöscht werden", + "Failed to delete webhook": "Webhook konnte nicht gelöscht werden", "Failed to disconnect": "Verbindung konnte nicht getrennt werden", "Failed to download image": "Bild konnte nicht heruntergeladen werden", "Failed to extract content from the file: {{error}}": "Inhaltsextraktion fehlgeschlagen: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Modelle konnten nicht abgerufen werden", "Failed to generate title": "Titel konnte nicht generiert werden", "Failed to import models": "Modelle konnten nicht importiert werden", + "Failed to load chat": "Chat konnte nicht geladen werden", "Failed to load chat preview": "Chat-Vorschau konnte nicht geladen werden", "Failed to load DOCX file. Please try downloading it instead.": "DOCX Datei konnte nicht geladen werden. Versuche die Datei stattdessen herunterzuladen.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-Datei konnte nicht geladen werden. Bitte versuchen Sie stattdessen, sie herunterzuladen.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Chat konnte nicht verschoben werden", "Failed to process URL: {{url}}": "{{url}} konnte nicht verarbeitet werden", "Failed to read clipboard contents": "Zwischenablage konnte nicht gelesen werden", + "Failed to refresh terminals: {{error}}": "Terminals konnten nicht aktualisiert werden: {{error}}", "Failed to remove member": "Mitglied konnte nicht entfernt werden", "Failed to render diagram": "Diagramm konnte nicht gerendert werden", "Failed to render visualization": "Visualisierung konnte nicht gerendert werden", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Modellkonfiguration konnte nicht gespeichert werden", "Failed to save policy: {{error}}": "Fehler beim Speichern der Policy: {{error}}", "Failed to save terminal servers": "Terminal Server konnten nicht gespeichert werden", + "Failed to save webhook": "Webhook konnte nicht gespeichert werden", "Failed to unshare chat.": "Chat-Freigabe konnte nicht entfernt werden", "Failed to update settings": "Einstellungen konnten nicht aktualisiert werden", "Failed to update status": "Status konnte nicht aktualisiert werden", + "Failed to update webhook": "Webhook konnte nicht aktualisiert werden", "Failed to upload file.": "Datei-Upload fehlgeschlagen.", "Features": "Funktionen", "Features Permissions": "Funktionsberechtigungen", @@ -975,18 +1063,20 @@ "File content updated successfully.": "Dateiinhalt erfolgreich aktualisiert.", "File Context": "Datei-Kontext", "File deleted successfully.": "Datei erfolgreich gelöscht.", - "File Extensions": "", + "File Extensions": "Dateierweiterungen", "File Mode": "Datei-Modus", - "File moved.": "", + "File moved.": "Datei verschoben.", "File name": "Dateiname", "File not found.": "Datei nicht gefunden.", "File removed successfully.": "Datei erfolgreich entfernt.", - "File renamed.": "", + "File renamed.": "Datei umbenannt.", "File size should not exceed {{maxSize}} MB.": "Dateigröße darf {{maxSize}} MB nicht überschreiten.", "File Upload": "Dateiupload", "File uploaded successfully": "Datei erfolgreich hochgeladen", "Filename": "Dateiname", "Files": "Dateien", + "Fill the required fields first.": "Füllen Sie zuerst die erforderlichen Felder aus.", + "Fill the source fields and test query first.": "Füllen Sie zuerst die Quellfelder und die Testabfrage aus.", "Filter": "Filter", "Filter is now globally disabled": "Filter ist nun global deaktiviert", "Filter is now globally enabled": "Filter ist nun global aktiviert", @@ -994,7 +1084,7 @@ "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Fingerabdruck-Spoofing erkannt: Initialen können nicht verwendet werden. Nutze Standard-Profilbild.", "Firecrawl API Base URL": "Firecrawl API Basis-URL", "Firecrawl API Key": "Firecrawl API-Schlüssel", - "Firecrawl Timeout (s)": "Firecrawl Timeout (s)", + "Firecrawl Timeout (s)": "Firecrawl-Timeout (s)", "Floating Quick Actions": "Schwebende Schnellaktionen", "Focus Chat Input": "Chat-Eingabe fokussieren", "Folder": "Ordner", @@ -1009,6 +1099,7 @@ "Folder options": "Ordner Optionen", "Folder updated successfully": "Ordner erfolgreich aktualisiert", "Folders": "Ordner", + "Folders Sharing": "Ordnerfreigabe", "Follow up": "Folgefragen", "Follow Up Generation": "Folgefragen-Generierung", "Follow Up Generation Prompt": "Prompt für Folgefragen-Generierung", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funktion ist nun global aktiviert", "Function Name": "Funktionsname", "Function Name Filter List": "Filterliste für Funktionsnamen", + "Function starter": "Funktionsvorlage", "Function updated successfully": "Funktion erfolgreich aktualisiert", "Functions": "Funktionen", "Functions allow arbitrary code execution.": "Funktionen erlauben die Ausführung beliebigen Codes.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Raster", "Grokipedia": "Grokipedia", + "group": "Gruppe", + "Group": "Gruppe", "Group Channel": "Gruppenkanal", + "Group Claim": "Gruppen-Claim", "Group created successfully": "Gruppe erfolgreich erstellt", "Group deleted successfully": "Gruppe erfolgreich gelöscht", "Group Description": "Gruppenbeschreibung", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptisches Feedback", + "Header variables": "Header-Variablen", "Headers": "Header", "Headers must be a valid JSON object": "Header müssen ein gültiges JSON-Objekt sein", "Height": "Höhe", @@ -1098,7 +1194,7 @@ "Hide Model": "Modell verbergen", "High": "Hoch", "High Contrast Mode": "Hoher Kontrast", - "History": "History", + "History": "Verlauf", "Home": "Startseite", "Host": "Host", "Hourly": "Stündlich", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID darf keine \":\" oder \"|\" Zeichen enthalten", "ID copied to clipboard": "ID in die Zwischenablage kopiert", + "Identity audit": "Identitätsprüfung", + "Idle only": "Nur im Leerlauf", "Idle Timeout": "Inaktivitäts-Timeout", "iframe Sandbox Allow Forms": "iFrame Sandbox: Formulare erlauben", "iframe Sandbox Allow Same Origin": "iFrame Sandbox: Gleichen Ursprung erlauben", @@ -1138,6 +1236,7 @@ "Import From Link": "Von Link importieren", "Import Models": "Modelle importieren", "Import Prompts": "Prompts importieren", + "Import Skills": "Skills importieren", "Import successful": "Import erfolgreich", "Import Tools": "Werkzeuge importieren", "Important Update": "Wichtiges Update", @@ -1195,12 +1294,11 @@ "Keep in Sidebar": "In Seitenleiste anzeigen", "Key": "Schlüssel", "Key is required": "Schlüssel ist erforderlich", - "Keyboard shortcuts": "Tastenkombinationen", "Keyboard Shortcuts": "Tastenkombinationen", "Knowledge": "Wissen", "Knowledge Access": "Wissenszugriff", "Knowledge Base": "Wissensspeicher", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "Wissensspeicher wurde zurückgesetzt", "Knowledge created successfully.": "Wissen erfolgreich erstellt.", "Knowledge deleted successfully.": "Wissen erfolgreich gelöscht.", "Knowledge Description": "Wissensbeschreibung", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Wissensname", "Knowledge Public Sharing": "Öffentliche Freigabe von Wissen", "Knowledge Sharing": "Wissen teilen", + "Knowledge source created.": "Wissensquelle erstellt.", + "Knowledge source updated.": "Wissensquelle aktualisiert.", "Knowledge updated successfully": "Wissen erfolgreich aktualisiert", "Kokoro.js (Browser)": "Kokoro.js (Browser)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Letzter Durchlauf", "Last reply": "Letzte Antwort", "LDAP": "LDAP", - "LDAP server updated": "LDAP-Server aktualisiert", "Leaderboard": "Bestenliste", "Learn more": "Mehr erfahren", "Learn More": "Mehr erfahren", @@ -1246,11 +1345,12 @@ "Legacy": "Veraltet", "lexical": "lexikalisch", "License": "Lizenz", + "Lifecycle JSON": "Lifecycle-JSON", "Lift List": "Liste anheben", "Light": "Hell", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Gleichzeitige Suchanfragen begrenzen. 0 = unbegrenzt (Standard). Auf 1 setzen für sequentielle Ausführung (empfohlen für APIs mit strengen Ratenbegrenzungen wie dem kostenlosen Brave-Tarif).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Limitiert die Anzahl gleichzeitiger embedding Anfragen. Auf 0 setzen für unlimitiert.", - "Linkup API Key": "", + "Linkup API Key": "Linkup-API-Schlüssel", "List": "Liste", "List calendars, search, create, update, and delete calendar events": "Kalender auflisten, suchen, erstellen, aktualisieren und löschen", "Listening...": "Höre zu...", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Standortzugriff nicht erlaubt", "Lost": "Verloren", "Low": "Niedrig", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "Senken Sie den Token-Schwellenwert für die Kontextverdichtung dieses Modells. Der globale Schwellenwert für die Kontextverdichtung bleibt das Maximum.", "LTR": "LTR", "Made by Open WebUI Community": "Von der Open WebUI Community", "Make password visible in the user interface": "Passwort in der Benutzeroberfläche sichtbar machen", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Pipelines verwalten", "Manage Tool Servers": "Tool-Server verwalten", "Manage your account information.": "Verwalten Sie Ihre Kontoinformationen.", + "Mapped Source": "Zugeordnete Quelle", "March": "März", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown-Header-Text-Splitter", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Erinnerungen erfolgreich gelöscht", "Memory deleted successfully": "Erinnerung erfolgreich gelöscht", "Memory updated successfully": "Erinnerung erfolgreich aktualisiert", + "Merge Accounts by Email": "Konten anhand der E-Mail-Adresse zusammenführen", "Merge Responses": "Antworten zusammenführen", "Merged Response": "Zusammengeführte Antwort", "Message": "Nachricht", @@ -1322,9 +1425,12 @@ "messages": "Nachrichten", "Messages": "Nachrichten", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Nachrichten, die Sie nach dem Erstellen des Links senden, werden nicht geteilt. Benutzer mit der URL können nur den bis dahin geteilten Chat sehen.", + "Metadata Field": "Metadatenfeld", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (persönlich)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (Arbeit/Schule)", + "Microsoft Web IQ API Base URL": "Microsoft Web IQ API-Basis-URL", + "Microsoft Web IQ API Key": "Microsoft Web IQ API-Schlüssel", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU-API-Schlüssel für den Cloud-API-Modus erforderlich.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Modelle teilen", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API-Schlüssel", + "Monday – Friday": "Montag – Freitag", "Month": "Monat", "Monthly": "Monatlich", "More": "Mehr", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Benennen Sie Ihren Wissensspeicher", "Name, prompt, and model are required": "Name, Prompt und Modell sind erforderlich", "Native": "Nativ", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "Der native Modus (Standard) nutzt die integrierten Funktionsaufruf-Fähigkeiten des Modells. Der Legacy-Modus funktioniert mit einer größeren Bandbreite an Modellen, indem Werkzeuge einmalig vor der Ausführung per Prompt-Injektion aufgerufen werden.", "Never": "Nie", "New": "Neu", "New Automation": "Neue Automatisierung", @@ -1401,8 +1509,8 @@ "New calendar": "Neuer Kalender", "New Calendar": "Neuer Kalender", "New Chat": "Neuer Chat", - "New directory": "", - "New Directory": "", + "New directory": "Neues Verzeichnis", + "New Directory": "Neues Verzeichnis", "New Event": "Neues Ereignis", "New File": "Neue Datei", "New Folder": "Neuer Ordner", @@ -1423,6 +1531,7 @@ "Next run": "Nächster Durchlauf", "No access grants. Private to you.": "Keine Freigaben konfiguriert. Nur für Sie zugänglich.", "No activity data": "Keine Aktivitätsdaten", + "No additional headers are sent unless configured.": "Es werden keine zusätzlichen Header gesendet, sofern nicht konfiguriert.", "No authentication": "Keine Authentifizierung", "No automations found": "Keine Automatisierungen gefunden", "No chats found": "Keine Chats gefunden", @@ -1435,8 +1544,10 @@ "No data": "Keine Daten", "No data found": "Keine Daten gefunden", "No distance available": "Keine Distanz verfügbar", + "No event webhooks configured.": "Keine Ereignis-Webhooks konfiguriert.", "No execution logs available yet": "Noch keine Ausführungsprotokolle vorhanden", "No expiration can pose security risks.": "Ein fehlendes Ablaufdatum kann Sicherheitsrisiken bergen.", + "No external knowledge sources configured.": "Keine externen Wissensquellen konfiguriert.", "No feedback found": "Kein Feedback gefunden", "No file selected": "Keine Datei ausgewählt", "No files found": "Keine Dateien gefunden", @@ -1448,13 +1559,13 @@ "No HTML, CSS, or JavaScript content found.": "Keine HTML-, CSS- oder JavaScript-Inhalte gefunden.", "No inference engine with management support found": "Keine Inferenz-Engine mit Verwaltungsunterstützung gefunden", "No kernel": "Kein Kernel", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "Keine Wissensspeicher zugänglich", "No knowledge bases found.": "Keine Wissensspeicher gefunden.", "No knowledge found": "Kein Wissen gefunden", "No limit": "Kein Limit", "No memories to clear": "Keine Erinnerungen zum Löschen", "No model IDs": "Keine Modell-IDs", - "No models accessible": "", + "No models accessible": "Keine Modelle zugänglich", "No models available": "Keine Modelle verfügbar", "No models found": "Keine Modelle gefunden", "No models selected": "Keine Modelle ausgewählt", @@ -1464,6 +1575,7 @@ "No output items": "Keine Ausgabepunkte", "No pinned messages": "Keine angehefteten Nachrichten", "No prompts found": "Keine Prompts gefunden", + "No Repeat": "Keine Wiederholung", "No results": "Keine Ergebnisse", "No results found": "Keine Ergebnisse gefunden", "No search query generated": "Keine Suchanfrage generiert", @@ -1475,7 +1587,7 @@ "No Terminal connection configured.": "Keine Terminal Verbindung konfiguriert.", "No terminal connections configured.": "Keine Terminal Verbindungen konfiguriert.", "No tool server connections configured.": "Keine Werkzeug-Server Verbindungen konfiguriert.", - "No tools accessible": "", + "No tools accessible": "Keine Werkzeuge zugänglich", "No tools found": "Keine Werkzeuge gefunden", "No users were found.": "Keine Benutzer gefunden.", "No valves": "Keine Valves", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Noch keine Webhooks", "Node Ids": "Knoten-IDs", "None": "Keine", + "Not configured": "Nicht konfiguriert", "Not factually correct": "Inhaltlich nicht korrekt", "Not helpful": "Nicht hilfreich", "Not Registered": "Nicht registriert", @@ -1498,24 +1611,29 @@ "Notifications": "Benachrichtigungen", "November": "November", "OAuth": "OAuth", + "OAuth / OIDC": "OAuth / OIDC", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statisch)", "OAuth ID": "OAuth-ID", + "OAuth Resource Parameter": "OAuth-Ressourcenparameter", + "OAuth Scopes": "OAuth-Scopes", "OAuth Server URL": "OAuth Server URL", "OAuth session disconnected": "OAuth-Sitzung getrennt", "October": "Oktober", "Off": "Aus", "Okay, Let's Go!": "Okay, los geht's!", + "Older messages are summarized when estimated context exceeds this token limit.": "Ältere Nachrichten werden zusammengefasst, wenn der geschätzte Kontext dieses Token-Limit überschreitet.", "OLED Dark": "OLED Dunkel", "Ollama": "Ollama", "Ollama API": "Ollama-API", "Ollama API settings updated": "Ollama-API-Einstellungen aktualisiert", "Ollama Cloud API Key": "Ollama Cloud API-Schlüssel", "Ollama Version": "Ollama-Version", + "Omit": "Auslassen", "On": "Ein", "Once": "Einmalig", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Nur im Sprachmodus aktiv.", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Nur aktiv, wenn die Einstellung „Großen Text als Datei einfügen“ aktiviert ist.", "Only active when the chat input is in focus and an LLM is generating a response.": "Nur aktiv, wenn das Chat-Eingabefeld fokussiert ist und ein LLM eine Antwort generiert.", "Only active when the chat input is in focus.": "Nur aktiv, wenn das Chat-Eingabefeld fokussiert ist.", @@ -1541,7 +1659,7 @@ "Open Model Selector": "Modell-Selektor öffnen", "Open Settings": "Einstellungen öffnen", "Open Sidebar": "Seitenleiste öffnen", - "Open Terminal": "Open Terminal", + "Open Terminal": "Terminal öffnen", "Open User Profile Menu": "Benutzerprofilmenü öffnen", "Open WebUI can use tools provided by any OpenAPI server.": "Open WebUI kann Werkzeuge verwenden, die von jedem OpenAPI-Server bereitgestellt werden.", "Open WebUI uses faster-whisper internally.": "Open WebUI verwendet intern faster-whisper.", @@ -1582,26 +1700,30 @@ "Password": "Passwort", "Passwords do not match.": "Die Passwörter stimmen nicht überein.", "Paste Large Text as File": "Großen Text als Datei einfügen", + "Path": "Pfad", "Path copied": "Pfad kopiert", "Paused": "Pausiert", "PDF document (.pdf)": "PDF-Dokument (.pdf)", "PDF Extract Images (OCR)": "Bilder aus PDFs extrahieren (OCR)", "PDF Loader Mode": "PDF Loader Modus", - "pdf, docx, pptx, xlsx": "", + "pdf, docx, pptx, xlsx": "pdf, docx, pptx, xlsx", "pending": "ausstehend", "Pending": "Ausstehend", + "Pending Accounts": "Ausstehende Konten", "Pending User Overlay Content": "Inhalt des Overlays 'Ausstehende Kontoaktivierung'", "Pending User Overlay Title": "Titel des Overlays 'Ausstehende Kontoaktivierung'", "Permission denied when accessing media devices": "Zugriff auf Mediengeräte verweigert", "Permission denied when accessing microphone": "Zugriff auf Mikrofon verweigert", "Permission denied when accessing microphone: {{error}}": "Zugriff auf Mikrofon verweigert: {{error}}", "Permissions": "Berechtigungen", + "Permissions reset to defaults": "Berechtigungen auf Standardwerte zurückgesetzt", "Perplexity API Key": "Perplexity-API-Schlüssel", "Perplexity Model": "Perplexity-Modell", "Perplexity Search API URL": "Perplexity Search API-URL", "Perplexity Search Context Usage": "Perplexity-Suchkontext-Nutzung", "Persistent": "Persistent", "Personalization": "Personalisierung", + "Picture Claim": "Bild-Claim", "Pin": "Anheften", "Pin to Sidebar": "An Seitenleiste anheften", "Pinned": "Angeheftet", @@ -1618,7 +1740,7 @@ "Plain text (.md)": "Klartext (.md)", "Plain text (.txt)": "Klartext (.txt)", "Playground": "Testumgebung", - "Playwright Timeout (ms)": "Playwright Timeout (ms)", + "Playwright Timeout (ms)": "Playwright-Timeout (ms)", "Playwright WebSocket URL": "Playwright WebSocket-URL", "Please carefully review the following warnings:": "Bitte lesen Sie die folgenden Warnungen sorgfältig durch:", "Please connect all required integrations before sending a message": "Bitte verbinde alle erforderlichen Integrationen, bevor du eine Nachricht sendest", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Bitte füllen Sie alle Felder aus.", "Please register the OAuth client": "Bitte registrieren Sie den OAuth-Client", "Please save the connection to persist the OAuth client information and do not change the ID": "Bitte speichern Sie die Verbindung, um die OAuth-Client-Informationen zu sichern, und ändern Sie die ID nicht.", - "Please select a model first.": "Bitte wählen Sie zuerst ein Modell aus.", "Please select a model.": "Bitte wählen Sie ein Modell aus.", "Please select a reason": "Bitte wählen Sie einen Grund aus", "Please select a valid JSON file": "Bitte wählen Sie eine gültige JSON-Datei aus", "Please select at least one user for Direct Message channel.": "Bitte wählen Sie mindestens einen Benutzer für den Direktnachrichten-Kanal aus.", "Please wait until all files are uploaded.": "Bitte warten Sie, bis alle Dateien hochgeladen sind.", "Policy ID": "Policy-ID", + "Policy ID is required": "Richtlinien-ID ist erforderlich", "Port": "Port", "Ports": "Ports", "Positive attitude": "Positive Einstellung", @@ -1649,7 +1771,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "Die Präfix-ID wird verwendet, um Konflikte mit anderen Verbindungen zu vermeiden, indem ein Präfix zu den Modell-IDs hinzugefügt wird - zum Deaktivieren leer lassen.", "Prevent File Creation": "Dateierstellung verhindern", "Preview": "Vorschau", - "Preview Access": "", + "Preview Access": "Vorschau-Zugriff", "Previous 30 days": "Letzte 30 Tage", "Previous 7 days": "Letzte 7 Tage", "Previous message": "Vorherige Nachricht", @@ -1661,7 +1783,7 @@ "Prompt Autocompletion": "Prompt-Autovervollständigung", "Prompt Content": "Prompt-Inhalt", "Prompt created successfully": "Prompt erfolgreich erstellt", - "Prompt Name": "Prompt Name", + "Prompt Name": "Prompt-Name", "Prompt Suggestions": "Prompt Vorschläge", "Prompt Template": "Prompt Vorlage", "Prompt updated successfully": "Prompt erfolgreich aktualisiert", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Öffentliche Freigabe von Prompts", "Prompts Sharing": "Prompts teilen", "Provider": "Anbieter", + "Provider Name": "Anbietername", + "Provider URL": "Anbieter-URL", "Public": "Öffentlich", "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" von Ollama.com laden", "Pull a model from Ollama.com": "Ein Modell von Ollama.com laden", @@ -1687,21 +1811,29 @@ "Read": "Lesen", "Read Aloud": "Vorlesen", "Read more →": "Mehr lesen →", + "Read only": "Schreibgeschützt", "Read Only": "Nur lesend", "Read-Only Access": "Nur lesender Zugriff", "Reason": "Nachdenken", "Reasoning Effort": "Reasoning Effort", "Reasoning Tags": "Reasoning Tags", "Reasoning text...": "Reasoning text...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "Empfängt passende Ereignisse instanzweit, einschließlich System-/Konfigurationsereignissen und Ereignissen, die einem beliebigen Benutzer zugeordnet sind.", + "Receives matching events that are not associated with a user.": "Empfängt passende Ereignisse, die keinem Benutzer zugeordnet sind.", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "Empfängt passende benutzerbezogene Ereignisse nur, wenn der Akteur, das Benutzersubjekt oder die Benutzerdaten mit diesen Benutzern oder aktuellen Gruppenmitgliedern übereinstimmen. System-/Konfigurationsereignisse werden nicht gesendet.", "Recently Used": "Kürzlich verwendet", "Reconnected": "Erneut verbunden", "Record": "Aufnehmen", "Record voice": "Stimme aufnehmen", + "Redirect URI": "Redirect-URI", "Redirecting you to Open WebUI Community": "Sie werden zur Open WebUI Community weitergeleitet", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Verringert die Wahrscheinlichkeit von unsinnigen Ausgaben. Ein höherer Wert (z. B. 100) führt zu vielfältigeren Antworten, während ein niedrigerer Wert (z. B. 10) konservativer ist.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Beziehen Sie sich auf sich selbst als \"User\" (z. B. \"User lernt Spanisch\")", "Reference Chats": "Chats referenzieren", "Refresh": "Aktualisieren", + "Refresh requested: {{count}} terminal(s)_one": "Aktualisierung angefordert: {{count}} Terminal", + "Refresh requested: {{count}} terminal(s)_other": "Aktualisierung angefordert: {{count}} Terminals", + "Refresh Terminals": "Terminals aktualisieren", + "Refreshing...": "Wird aktualisiert...", "Refused when it shouldn't have": "Fälschlicherweise abgelehnt", "Regenerate": "Neu generieren", "Regenerate Menu": "Menü neu generieren", @@ -1727,27 +1859,34 @@ "Remove from favorites": "Von Favoriten entfernen", "Remove image": "Bild entfernen", "Remove Model": "Modell entfernen", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "{{count}} veraltete Datei wird entfernt...", + "Removing {{count}} stale files..._other": "{{count}} veraltete Dateien werden entfernt...", "Rename": "Umbenennen", "Renamed to {{name}}": "In {{name}} umbenannt", "Render Markdown in Assistant Messages": "Markdown in Assistentennachrichten rendern", "Render Markdown in Previews": "Markdown in der Vorschau rendern", "Render Markdown in User Messages": "Markdown in Benutzernachrichten rendern", "Reorder Models": "Modelle neu anordnen", + "Repeat": "Wiederholen", "Repeats": "Wiederholen", "Reply": "Antworten", "Reply in Thread": "Im Thread antworten", "Reply to thread...": "Im Thread antworten...", "Replying to {{NAME}}": "Antwort an {{NAME}}", + "Require users to confirm before using Web Search.": "Benutzer müssen vor der Nutzung der Websuche bestätigen.", "required": "erforderlich", "Reranking Batch Size": "Reranking-Batch-Größe", "Reranking Engine": "Reranking-Engine", "Reranking Model": "Reranking-Modell", + "Research Knowledge": "Recherche-Wissen", "Reset": "Zurücksetzen", "Reset All Models": "Alle Modelle zurücksetzen", + "Reset all permissions to their initial configuration values": "Alle Berechtigungen auf ihre ursprünglichen Konfigurationswerte zurücksetzen", + "Reset group permissions to match the current default user permissions": "Gruppenberechtigungen auf die aktuellen Standard-Benutzerberechtigungen zurücksetzen", "Reset Image": "Bild zurücksetzen", - "Reset knowledge base?": "", + "Reset knowledge base?": "Wissensspeicher zurücksetzen?", + "Reset persisted files": "Persistierte Dateien zurücksetzen", + "Reset to Defaults": "Auf Standardwerte zurücksetzen", "Reset Upload Directory": "Upload-Verzeichnis zurücksetzen", "Reset Vector Storage/Knowledge": "Vektorspeicher/Wissen zurücksetzen", "Reset view": "Ansicht zurücksetzen", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 Quelle abgerufen", "Rich Text Input for Chat": "Rich-Text-Eingabe für Chat", "Role": "Rolle", + "Roles Claim": "Rollen-Claim", "RTL": "RTL", "Run": "Ausführen", "Run All": "Alle starten", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Das direkte Speichern von Chat-Protokollen im Browserspeicher wird nicht mehr unterstützt. Bitte nehmen Sie sich einen Moment Zeit, um Ihre Chat-Protokolle herunterzuladen und zu löschen, indem Sie auf die Schaltfläche unten klicken. Sie können Ihre Chat-Protokolle später problemlos über das Backend wieder importieren.", "Schedule": "Planen", "Scheduled time must be in the future": "Geplante Zeit muss in der Zukunft liegen", + "Scopes": "Scopes", "Scroll On Branch Change": "Bei Zweigwechsel scrollen", "Scroll to Top": "Zum Anfang scrollen", "Search": "Suchen", "Search a model": "Ein Modell suchen", + "Search actions": "Actions durchsuchen", "Search all emojis": "Alle Emojis durchsuchen", "Search and manage user memories": "Suche und manage Benutzer Erinnerungen", "Search and view user chat history": "Suche und sehe die Chat History des Benutzers ein", @@ -1798,6 +1940,7 @@ "Search Chats": "Chats durchsuchen...", "Search Collection": "Sammlung durchsuchen", "Search Files": "Suche Dateien", + "Search filters": "Filter durchsuchen", "Search Filters": "Suchfilter", "search for archived chats": "nach archivierten Chats suchen", "search for folders": "nach Ordnern suchen", @@ -1812,13 +1955,16 @@ "Search Models": "Modelle durchsuchen...", "Search Notes": "Notizen durchsuchen...", "Search options": "Suchoptionen", + "Search or add pattern": "Muster suchen oder hinzufügen", "Search Prompts": "Prompts durchsuchen...", "Search Result Count": "Anzahl der Suchergebnisse", + "Search skills": "Skills durchsuchen", "Search Skills": "Durchsuche Skills", - "Search skills...": "", "Search the internet": "Das Internet durchsuchen", "Search the web and fetch URLs": "Durchsuche das Internet und rufe URLs auf", + "Search tools": "Tools durchsuchen", "Search Tools": "Werkzeuge durchsuchen...", + "Search users or groups": "Benutzer oder Gruppen suchen", "Search, view, and manage user notes": "Suche, sehe und manage Notizen des Benutzers", "SearchApi API Key": "SearchApi-API-Schlüssel", "SearchApi Engine": "SearchApi-Engine", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Auswählen", "Select {{modelName}} model": "Modell {{modelName}} auswählen", - "Select a base model": "Wählen Sie ein Basismodell", "Select a base model (e.g. llama3, gpt-4o)": "Wählen Sie ein Basismodell (z. B. llama3, gpt-4o)", "Select a conversation to preview": "Wählen Sie eine Unterhaltung für die Vorschau", "Select a engine": "Wählen Sie eine Engine", @@ -1872,18 +2017,25 @@ "semantic": "semantisch", "Send": "Senden", "Send a Message": "Eine Nachricht senden", + "Send events for": "Ereignisse senden für", "Send message": "Nachricht senden", "Send now": "Jetzt senden", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "Produktereignisse als JSON an externe Dienste senden. Chat-Ziele erhalten lesbare Nachrichten.", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Sendet `stream_options: { include_usage: true }` in der Anfrage.\nUnterstützte Anbieter geben Token-Nutzungsinformationen in der Antwort zurück, wenn dies gesetzt ist.", "September": "September", "SerpApi API Key": "SerpApi-API-Schlüssel", "SerpApi Engine": "SerpApi-Engine", "Serper API Key": "Serper-API-Schlüssel", + "SERPHouse API Key": "SERPHouse-API-Schlüssel", + "SERPHouse Domain": "SERPHouse-Domain", "Serply API Key": "Serply-API-Schlüssel", "Serpstack API Key": "Serpstack-API-Schlüssel", "Server connection failed": "Verbindung zum Server fehlgeschlagen", "Server connection verified": "Serververbindung überprüft", + "Service Account": "Dienstkonto", "Session": "Sitzung", + "Session expired. Please sign in again.": "Sitzung abgelaufen. Bitte melden Sie sich erneut an.", "Set as default": "Als Standard festlegen", "Set as Production": "Als produktiv festlegen", "Set embedding model": "Embedding-Modell festlegen", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Freigabelink in die Zwischenablage kopiert", "Share to Open WebUI Community": "Mit der Open WebUI Community teilen", "Share your background and interests": "Teilen Sie Ihren Hintergrund und Ihre Interessen", + "Shared": "Geteilt", "Shared Chats": "Geteilte Chats", "Shared with you": "Mit Ihnen geteilt", "Sharing Permissions": "Freigabeberechtigungen", "Show": "Anzeigen", - "Show \"What's New\" modal on login": "\"Was gibt's Neues\"-Fenster beim Anmelden anzeigen", + "Show \"What's New\" Modal on Login": "\"Was gibt's Neues\"-Fenster beim Anmelden anzeigen", "Show Admin Details in Account Pending Overlay": "Admin-Details im 'Konto ausstehend'-Overlay anzeigen", "Show All": "Alle anzeigen", "Show all ({{COUNT}} characters)": "Zeige alle ({{COUNT}} Zeichen)", "Show Files": "Dateien anzeigen", + "Show Files on Terminal Select": "Dateien bei Terminal-Auswahl anzeigen", "Show Formatting Toolbar": "Formatierungsleiste anzeigen", "Show image preview": "Bildvorschau anzeigen", "Show Model": "Modell anzeigen", @@ -1941,10 +2095,10 @@ "Skill created successfully": "Skill erfolgreich erstellt", "Skill deleted successfully": "Skill erfolgreich gelöscht", "Skill Description": "Skill Beschreibung", - "Skill ID": "Skill ID", + "Skill ID": "Skill-ID", "Skill imported successfully": "Skill erfolgreich importiert", "Skill Instructions": "Skill Anweisung", - "Skill Name": "Skill Name", + "Skill Name": "Skill-Name", "Skill updated successfully": "Skill erfolgreich aktualisiert", "Skills": "Skills", "Skills Access": "Skills Zugang", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Quelle", + "Specific users or groups": "Bestimmte Benutzer oder Gruppen", "Speech Playback Speed": "Sprachwiedergabegeschwindigkeit", "Speech recognition error: {{error}}": "Spracherkennungsfehler: {{error}}", "Speech-to-Text": "Sprache-zu-Text", @@ -1999,6 +2154,7 @@ "STT Settings": "STT-Einstellungen", "Stylized PDF Export": "Stilisierter PDF-Export", "Su_day_of_week": "So", + "Sub Claim": "Sub-Claim", "Submit question": "Frage absenden", "Submit suggestion": "Vorschlag absenden", "Subtitle": "Untertitel", @@ -2013,8 +2169,8 @@ "Switch to JSON editor": "Zum JSON-Editor wechseln", "Switch to visual editor": "Zum visuellen Editor wechseln", "Sync": "Synchronisieren", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Ein lokales Verzeichnis mit diesem Wissensspeicher synchronisieren. Es werden nur neue und geänderte Dateien hochgeladen. Die Verzeichnisstruktur wird gespiegelt.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Synchronisierung abgeschlossen: {{added}} hinzugefügt, {{modified}} geändert, {{deleted}} gelöscht, {{unmodified}} unverändert", "Sync Complete!": "Synchronisierung abgeschlossen!", "Sync directory": "Ordner synchronisieren", "Sync Failed": "Synchronisierung fehlgeschlagen", @@ -2023,8 +2179,10 @@ "Syncing...": "Synchronisierung läuft …", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synchronisiert nur Chats mit Änderungen seit dem letzten Abgleich. Deaktivieren, um alle Chats neu zu synchronisieren.", "System": "System", + "System events only": "Nur Systemereignisse", "System Instructions": "Systemanweisungen", "System Prompt": "System-Prompt", + "Table": "Tabelle", "Tag": "Tag", "Tags": "Tags", "Tags Generation": "Tag-Generierung", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Temporärer Chat als Standard", "Terminal": "Terminal", "Terminal servers saved": "Terminal Server gespeichert", + "Test": "Testen", + "Test Query": "Testabfrage", + "Test returned no results.": "Test lieferte keine Ergebnisse.", + "Test succeeded.": "Test erfolgreich.", + "Test the source before creating it.": "Testen Sie die Quelle, bevor Sie sie erstellen.", + "Test the source before saving it.": "Testen Sie die Quelle, bevor Sie sie speichern.", "Text Splitter": "Text-Splitter", "Text-to-Speech": "Text-zu-Sprache", "Text-to-Speech Engine": "Text-zu-Sprache-Engine", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Die Sprache des Eingangsaudios. Die Angabe im ISO-639-1-Format (z. B. en) verbessert Genauigkeit und Latenz. Leer lassen für automatische Erkennung.", "The LDAP attribute that maps to the mail that users use to sign in.": "Das LDAP-Attribut, das der E-Mail zugeordnet ist, mit der sich Benutzer anmelden.", "The LDAP attribute that maps to the username that users use to sign in.": "Das LDAP-Attribut, das dem Benutzernamen zugeordnet ist, mit dem sich Benutzer anmelden.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Die Bestenliste ist derzeit im Beta-Stadium. Wir passen die Bewertungsberechnungen möglicherweise an, während wir den Algorithmus verfeinern.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Die maximale Dateigröße in MB. Dateien, die dieses Limit überschreiten, werden nicht hochgeladen.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Die maximale Anzahl von Dateien, die gleichzeitig im Chat verwendet werden können. Überzählige Dateien werden nicht hochgeladen.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Das Ausgabeformat für den Text. Kann 'json', 'markdown' oder 'html' sein. Standard ist 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Dieser Ordner ist leer", "This is a default user permission and will remain enabled.": "Dies ist eine Standardberechtigung und bleibt aktiviert.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dies ist eine experimentelle Funktion. Sie funktioniert möglicherweise nicht wie erwartet und kann jederzeit geändert werden.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "Dieser Wissensspeicher ruft Daten aus einer verbundenen Quelle ab. Open WebUI kann ihn abfragen, dessen Quelldaten aber nicht hochladen, synchronisieren, bearbeiten, löschen, zurücksetzen oder neu indizieren.", "This model is not publicly available. Please select another model.": "Dieses Modell ist nicht öffentlich verfügbar. Bitte wählen Sie ein anderes Modell.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Diese Option steuert, wie lange das Modell nach der Anfrage im Speicher bleibt (Standard: 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Diese Option steuert, wie viele Token beim Aktualisieren des Kontexts behalten werden. Bei 2 werden z. B. die letzten 2 Token des Gesprächskontexts beibehalten. Dies hilft, die Kontinuität zu wahren, kann aber die Reaktion auf neue Themen einschränken.", @@ -2094,7 +2258,7 @@ "This will delete all models including custom models": "Dies löscht alle Modelle, einschließlich benutzerdefinierter Modelle", "This will delete all models including custom models and cannot be undone.": "Dies löscht alle Modelle, einschließlich benutzerdefinierter Modelle, und kann nicht rückgängig gemacht werden.", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Dies wird den Kalender \"{{name}}\" und alle seine Ereignisse dauerhaft löschen. Diese Aktion kann nicht rückgängig gemacht werden.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Dadurch werden alle Dateien und Verzeichnisse aus diesem Wissensspeicher entfernt. Diese Aktion kann nicht rückgängig gemacht werden.", "Thorough explanation": "Ausführliche Erklärung", "Thought": "Gedanke", "Thought for {{DURATION}}": "Nachgedacht für {{DURATION}}", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Um mehr über verfügbare Endpunkte zu erfahren, besuchen Sie unsere Dokumentation.", "To select skills here, add them to the \"Skills\" workspace first.": "Um hier Skills auszuwählen, füge sie zuerst dem Workspace \"Skills\" hinzu.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Um Toolkits auszuwählen, fügen Sie sie zuerst dem Arbeitsbereich \"Werkzeuge\" hinzu.", - "Toast notifications for new updates": "Toast-Benachrichtigungen für neue Updates", + "Toast Notifications for New Updates": "Toast-Benachrichtigungen für neue Updates", "Today": "Heute", "Today at": "Heute um", "Today at {{LOCALIZED_TIME}}": "Heute um {{LOCALIZED_TIME}}", @@ -2130,12 +2294,14 @@ "Toggle 1 source": "Eine Quelle umschalten", "Toggle details": "Details umschalten", "Toggle Dictation": "Diktieren umschalten", - "Toggle Mute": "", + "Toggle Mute": "Stummschaltung umschalten", "Toggle Sidebar": "Seitenleiste umschalten", "Toggle status history": "Status Updates umschalten", "Toggle whether current connection is active.": "Umschalten, ob die aktuelle Verbindung aktiv ist.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Token-Anzahlen sind Schätzwerte und entsprechen möglicherweise nicht der tatsächlichen API-Nutzung.", + "Token Threshold": "Token-Schwellenwert", + "Tokenizer Model": "Tokenizer Modell", "tokens": "Token", "Tokens": "Token", "Too verbose": "Zu ausführlich", @@ -2150,11 +2316,11 @@ "Tools": "Werkzeuge", "Tools Access": "Werkzeugzugriff", "Tools are a function calling system with arbitrary code execution": "Werkzeuge sind ein System für Funktionsaufrufe mit beliebiger Codeausführung", - "Tools Function Calling Prompt": "Tools Function Calling Prompt", + "Tools Function Calling Prompt": "Prompt für Werkzeug-Funktionsaufrufe", "Tools have a function calling system that allows arbitrary code execution.": "Werkzeuge verfügen über ein Funktionsaufrufsystem, das die Ausführung beliebigen Codes ermöglicht.", "Tools Public Sharing": "Öffentliche Freigabe von Werkzeugen", "Tools Sharing": "Werkzeuge teilen", - "Top": "Top", + "Top": "Oben", "Top K": "Top-K", "Top K Reranker": "Top-K Reranker", "Transformers": "Transformers", @@ -2184,14 +2350,19 @@ "Unpin": "Lösen", "Unpin from Sidebar": "Aus der Seitenleiste lösen", "Unravel secrets": "Geheimnisse lüften", + "Unshare All": "Alle Freigaben aufheben", + "Unshare All Shared Chats": "Freigabe aller geteilten Chats aufheben", "Unshare Chat": "Chat-Freigabe entfernen", "Unsupported file type.": "Nicht unterstützter Dateityp.", "Untagged": "Ohne Tag", "Untitled": "Unbenannt", "Update": "Aktualisieren", "Update and Copy Link": "Aktualisieren und Link kopieren", + "Update Email": "E-Mail aktualisieren", "Update for the latest features and improvements.": "Führen Sie ein Update für die neuesten Funktionen und Verbesserungen durch.", + "Update Name": "Name aktualisieren", "Update password": "Passwort aktualisieren", + "Update Picture": "Bild aktualisieren", "Update your status": "Status aktualisieren", "Updated": "Aktualisiert", "Updated at": "Aktualisiert am", @@ -2209,7 +2380,7 @@ "Upload Progress": "Upload-Fortschritt", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Fortschritt: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Hochgeladene Dateien oder Bilder", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploading {{current}}/{{total}}: {{file}}": "Wird hochgeladen {{current}}/{{total}}: {{file}}", "Uploading...": "Lade hoch...", "URL": "URL", "URL is required": "URL ist erforderlich", @@ -2218,22 +2389,28 @@ "Use": "Nutze", "Use '#' in the prompt input to load and include your knowledge.": "Verwenden Sie '#' in der Prompt-Eingabe, um Ihr Wissen zu laden und einzubeziehen.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Verwenden Sie den Endpunkt /v1/chat/completions statt /v1/audio/transcriptions für potenziell bessere Genauigkeit.", + "Use a valid event name or pattern like user.*": "Verwenden Sie einen gültigen Ereignisnamen oder ein Muster wie user.*", + "Use Base64": "", "Use Chat Completions API": "Chat Completions API verwenden", + "Use discovered scopes": "Erkannte Scopes verwenden", "Use groups to organize your users and assign permissions.": "Nutze Gruppen um deine Nutzer zu organisieren und Berechtigungen zu vergeben", "Use LLM": "LLM verwenden", "Use no proxy to fetch page contents.": "Keinen Proxy zum Abrufen von Seiteninhalten verwenden.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Den durch die Umgebungsvariablen http_proxy und https_proxy festgelegten Proxy verwenden.", + "Use Web Search?": "Websuche verwenden?", "user": "Benutzer", "User": "Benutzer", + "User Access": "Benutzerzugriff", "User Activity": "Benutzer Aktivität", "User Groups": "Benutzergruppen", "User location successfully retrieved.": "Benutzerstandort erfolgreich abgerufen.", "User menu": "Benutzermenü", - "User Preview": "", + "User Preview": "Benutzervorschau", "User ratings (thumbs up/down)": "Benutzerbewertungen (Daumen hoch/runter)", "User Status": "Nutzerstatus", "User Webhooks": "Benutzer-Webhooks", "Username": "Benutzername", + "Username Claim": "Benutzername-Claim", "users": "Benutzer", "Users": "Benutzer", "Uses DefaultAzureCredential to authenticate": "Verwendet DefaultAzureCredential zur Authentifizierung", @@ -2247,6 +2424,7 @@ "Valves updated": "Valves aktualisiert", "Valves updated successfully": "Valves erfolgreich aktualisiert", "variable": "Variable", + "Vector Field": "Vektorfeld", "Verify Connection": "Verbindung prüfen", "Verify SSL Certificate": "SSL-Zertifikat prüfen", "Version": "Version", @@ -2276,11 +2454,14 @@ "Web API": "Web-API", "Web Loader Engine": "Web-Loader-Engine", "Web Search": "Websuche", + "Web Search Confirmation": "Websuche-Bestätigung", + "Web Search Confirmation Content": "Inhalt der Websuche-Bestätigung", "Web Search Engine": "Web-Suchmaschine", "Web Search in Chat": "Websuche im Chat", "Web Search Query Generation": "Suchanfragen-Generierung", + "Webhook deleted": "Webhook gelöscht", "Webhook Name": "Webhook-Name", - "Webhook URL": "Webhook-URL", + "Webhook saved": "Webhook gespeichert", "Webhooks": "Webhooks", "Webpage URLs": "Webseiten URLs", "WebUI Settings": "WebUI-Einstellungen", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex Web Search API Key", "Yandex Web Search config": "Yandex Web Search Konfiguration", "Yandex Web Search URL": "Yandex Web Search URL", + "Yearly": "Jährlich", "Yesterday": "Gestern", "Yesterday at {{LOCALIZED_TIME}}": "Gestern um {{LOCALIZED_TIME}}", "You": "Du", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Dein Browser unterstützt den Video tag nicht.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Ihr gesamter Beitrag geht direkt an den Plugin-Entwickler; Open WebUI behält keinen Anteil ein. Die gewählte Plattform kann jedoch eigene Gebühren erheben.", "Your message text or inputs": "Ihre Nachrichtentexte oder Eingaben", + "Your query will be sent to the configured web search provider.": "Ihre Anfrage wird an den konfigurierten Web-Suchanbieter gesendet.", "Your usage stats have been successfully synced.": "Ihre Nutzungsstatistiken wurden erfolgreich synchronisiert.", "YouTube": "YouTube", "Youtube Language": "YouTube-Sprache", diff --git a/src/lib/i18n/locales/dg-DG/translation.json b/src/lib/i18n/locales/dg-DG/translation.json index 6b1f73f8af..b24f749f08 100644 --- a/src/lib/i18n/locales/dg-DG/translation.json +++ b/src/lib/i18n/locales/dg-DG/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "", "{{webUIName}} Backend Required": "{{webUIName}} Backend Much Required", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Account", @@ -72,6 +83,7 @@ "Activity": "", "Add": "", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "", "Add a tag": "Add such tag", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Add Files", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "Admin Panel", + "Admin Roles": "", "Admin Settings": "Admin Settings", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "Advanced Parameters", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Such account exists?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API Base URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API Key", + "API Key / Token": "", "API Key created.": "", "API Key Endpoint Restrictions": "", "API keys": "", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copy Bark Auto Bark", - "Auto-playback response": "Auto-playback response", + "Auto-Create Groups": "", + "Auto-Playback Response": "Auto-Playback Response", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Base URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "such available users", + "Available variables": "", "available!": "available! So excite!", "Away": "So away", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "", "Banners": "", "Base Model (From)": "", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "", + "Chat Direction": "", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Collection", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Command", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "Content", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Created at", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "", "Default model updated": "Default model much updated", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Default User Role", + "Default webhook": "", "Defaults": "", "Delete": "", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Disabled sad", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Discover, download, and explore model presets", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Display username instead of You in Chat", + "Display the Username Instead of You in the Chat": "Display username instead of You in Chat", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Edit Wowser", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Enable New Bark Ups", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Enabled wow", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "Enter {{role}} bork here", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Enter Overlap of Chunks", "Enter Chunk Size": "Enter Size of Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Enter Top Wow", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Enter URL (e.g. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Failed to read clipboard borks", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Very important update", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Keyboard Barkcuts", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Light", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "Made by Open WebUI Community", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "No results, very empty", "No results found": "", "No search query generated": "", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Notifications", "November": "", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "", "Off": "Off", "Okay, Let's Go!": "Okay, Let's Go!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Dark", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama Version", + "Omit": "", "On": "On", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "Barkword", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "pending", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "Permission denied when accessing microphone: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalization", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "Pull a wowdel from Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Record Bark", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirecting you to Open WebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Reset image. Very wow.", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Role", + "Roles Claim": "", "RTL": "", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Saving chat logs in browser storage not support anymore. Pls download and delete your chat logs by click button below. Much easy re-import to backend through", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Search very search", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Search Prompts much wow", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "Seed very plant", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "", "Send a Message": "Send a Message much message", + "Send events for": "", "Send message": "Send message very send", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "Server connection verified much secure", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Set as default very default", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Share to Open WebUI Community much community", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Show much show", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Source", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Speech recognition error: {{error}} so error", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT Settings very settings", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "System very system", + "System events only": "", "System Instructions": "", "System Prompt": "System Prompt much prompt", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Text-to-Speech Engine much speak", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "Update password much change", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "user much user", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Users much users", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "variable very variable", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Version much version", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI Settings much settings", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/el-GR/translation.json b/src/lib/i18n/locales/el-GR/translation.json index ac64e1f389..b5fab9536f 100644 --- a/src/lib/i18n/locales/el-GR/translation.json +++ b/src/lib/i18n/locales/el-GR/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Συνομιλίες του {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Απαιτείται Backend", "*Prompt node ID(s) are required for image generation": "*Τα αναγνωριστικά κόμβου Prompt απαιτούνται για τη δημιουργία εικόνων", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Έλεγχος Πρόσβασης", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Προσβάσιμο σε όλους τους χρήστες", "Account": "Λογαριασμός", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Προσθήκη", "Add a model ID": "Προσθήκη αναγνωριστικού μοντέλου", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Προσθήκη σύντομης περιγραφής για το τι κάνει αυτό το μοντέλο", "Add a tag": "Προσθήκη ετικέτας", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Προσθήκη Αρχείων", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Προσθήκη Χρήστη", "Add User Group": "Προσθήκη Ομάδας Χρηστών", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Διαχειριστής", "Admin Contact Email": "", "Admin Panel": "Πίνακας Διαχειριστή", + "Admin Roles": "", "Admin Settings": "Ρυθμίσεις Διαχειριστή", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Οι διαχειριστές έχουν πρόσβαση σε όλα τα εργαλεία ανά πάσα στιγμή· οι χρήστες χρειάζονται εργαλεία ανά μοντέλο στον χώρο εργασίας.", "Advanced": "", "Advanced Parameters": "Προηγμένοι Παράμετροι", @@ -123,16 +140,21 @@ "All": "Όλα", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Όλα τα μοντέλα διαγράφηκαν με επιτυχία", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Επιτρέπεται η Κλήση", "Allow Chat Controls": "Επιτρέπεται ο Έλεγχος Συνομιλίας", "Allow Chat Delete": "Επιτρέπεται η διαγραφή συνομιλίας", "Allow Chat Edit": "Επιτρέπεται η Επεξεργασία Συνομιλίας", "Allow Chat Export": "Επιτρέπεται η Εξαγωγή Συνομιλίας", + "Allow Chat Import": "", "Allow Chat Params": "Επιτρέπονται οι Παράμετροι Συνομιλίας", "Allow Chat Share": "Επιτρέπεται ο Διαμοιρασμός Συνομιλίας", "Allow Chat System Prompt": "Επιτρέπεται η Προτροπή Συστήματος Συνομιλίας", @@ -152,9 +174,11 @@ "Allow User Location": "Επιτρέπεται η Τοποθεσία Χρήστη", "Allow Voice Interruption in Call": "Επιτρέπεται η Παύση Φωνής στην Κλήση", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Επιτρεπόμενα Endpoints", "Allowed File Extensions": "Επιτρεπόμενες Επεκτάσεις Αρχείων", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Επιτρεπόμενες επεκτάσεις αρχείων για ανέβασμα. Διαχωρίστε πολλαπλές επεκτάσεις με κόμματα. Αφήστε κενό για όλους τους τύπους αρχείων.", + "Allowed Roles": "", "Already have an account?": "Έχετε ήδη λογαριασμό;", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Πάντα", @@ -173,6 +197,7 @@ "API Base URL": "Βασικό URL API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Κλειδί API", + "API Key / Token": "", "API Key created.": "Το κλειδί API δημιουργήθηκε.", "API Key Endpoint Restrictions": "Περιορισμοί Κλειδιού API", "API keys": "κλειδιά API", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το μήνυμα;", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Είστε σίγουροι ότι θέλετε να απο-αρχειοθετήσετε όλες τις αρχειοθετημένες συνομιλίες;", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Μοντέλα Arena", "Artifacts": "Αρχεία", "Asc": "", "Ask": "", "Ask a question": "Ρωτήστε μια ερώτηση", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Βοηθός", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Ήχος", "August": "Αύγουστος", "Auth": "Ταυτοποίηση", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Επαλήθευση", "Authentication": "Ταυτοποίηση", "Auto": "Αυτόματο", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Αυτόματη Αντιγραφή Απάντησης στο Πρόχειρο", - "Auto-playback response": "Αυτόματη αναπαραγωγή της απάντησης", + "Auto-Create Groups": "", + "Auto-Playback Response": "Αυτόματη αναπαραγωγή της απάντησης", "Autocomplete Generation": "Δημιουργία Αυτόματης Συμπλήρωσης", "Autocomplete Generation Input Max Length": "Μέγιστο Μήκος Εισόδου Δημιουργίας Αυτόματης Συμπλήρωσης", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Σειρά Επαλήθευσης API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Βασικό URL AUTOMATIC1111", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Διαθέσιμα Εργαλεία", "available users": "διαθέσιμοι χρήστες", + "Available variables": "", "available!": "διαθέσιμο!", "Away": "Απών", "Awful": "Ασχημο", @@ -258,16 +295,17 @@ "Bad Response": "Κακή Απάντηση", "Banners": "Ανακοινώσεις", "Base Model (From)": "Βασικό Μοντέλο (Από)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "πριν", "Being lazy": "Τρώλακας", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "Τέλος Bing Search V7", "Bing Search V7 Subscription Key": "Κλειδί Συνδρομής Bing Search V7", "Bio": "Βιογραφικό", "Birth Date": "Ημερομηνία Γέννησης", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "Συνομιλία", "Chat deleted.": "", - "Chat direction": "Κατεύθυνση Συνομιλίας", + "Chat Direction": "Κατεύθυνση Συνομιλίας", "Chat exported successfully": "", "Chat History": "", "Chat ID": "ID Συνομιλίας", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Σύμπτυξη", "Collection": "Συλλογή", + "Collection Field": "", "Collections": "", "Color": "Χρώμα", "ComfyUI": "", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "Ροές Εργασίας ComfyUI", "ComfyUI Workflow Nodes": "Κόμβοι Ροής Εργασίας ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID κόμβων διαχωρισμένα με κόμμα (π.χ. 1 ή 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Εντολή", "Comment": "Σχόλιο", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Ολοκληρώσεις", "Compress Images in Channels": "Συμπίεση εικόνων σε κανάλια", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "Συνδεθείτε στους δικούς σας διακομιστές εξωτερικών εργαλείων συμβατών με OpenAPI.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Σύνδεση απέτυχε", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Επικοινωνήστε με τον Διαχειριστή για Πρόσβαση στο WebUI", "Content": "Περιεχόμενο", "Content Extraction Engine": "Μηχανή Εξαγωγής Περιεχομένου", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Συνέχεια Απάντησης", "Continue with {{provider}}": "Συνέχεια με {{provider}}", "Continue with Email": "Συνέχεια με Email", @@ -493,6 +543,7 @@ "Create new secret key": "Δημιουργία νέου μυστικού κλειδιού", "Create note": "", "Create Note": "Δημιουργία Σημείωσης", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Δημιουργήθηκε στις", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Περιοχή Κινδύνου", @@ -532,7 +584,6 @@ "Default Features": "Προεπιλεγμένες Λειτουργίες", "Default Filters": "Προεπιλεγμένα Φίλτρα", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Προεπιλεγμένο Μοντέλο", "Default model updated": "Το προεπιλεγμένο μοντέλο ενημερώθηκε", "Default permissions": "Προεπιλεγμένα δικαιώματα", @@ -542,6 +593,7 @@ "Default to ALL": "Προεπιλογή σε ΟΛΑ", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Η προεπιλογή είναι η τμηματοποιημένη ανάκτηση για στοχευμένη και σχετική εξαγωγή περιεχομένου, κάτι που συνιστάται στις περισσότερες περιπτώσεις.", "Default User Role": "Προεπιλεγμένος Ρόλος Χρήστη", + "Default webhook": "", "Defaults": "", "Delete": "Διαγραφή", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Απενεργοποιημένο", "Disconnect OAuth": "", "Discover a function": "Ανακάλυψη λειτουργίας", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Ανακαλύψτε, κατεβάστε και εξερευνήστε προκαθορισμένα μοντέλα", "Discussion channel where access is based on groups and permissions": "", "Display": "Εμφάνιση", - "Display chat title in tab": "Εμφάνιση τίτλου συνομιλίας στην καρτέλα", + "Display Chat Title in Tab": "Εμφάνιση τίτλου συνομιλίας στην καρτέλα", "Display Emoji in Call": "Εμφάνιση Emoji στην Κλήση", "Display Multi-model Responses in Tabs": "Εμφάνιση Απαντήσεων Πολυτροπικών Μοντέλων στις Καρτέλες", - "Display the username instead of You in the Chat": "Εμφάνιση του ονόματος χρήστη αντί του Εσάς στη Συνομιλία", + "Display the Username Instead of You in the Chat": "Εμφάνιση του ονόματος χρήστη αντί του Εσάς στη Συνομιλία", "Displays citations in the response": "Εμφανίζει παραπομπές στην απάντηση", "Displays status updates (e.g., web search progress) in the response": "Εμφανίζει ενημερώσεις κατάστασης (π.χ. πρόοδο αναζήτησης στο διαδίκτυο) στην απάντηση", "Dive into knowledge": "Βυθιστείτε στη γνώση", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Απαιτείται το URL του διακομιστή Docling.", "Document": "Έγγραφο", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "Απαιτείται το endpoint του Document Intelligence.", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Επεξεργασία Προεπιλεγμένων Δικαιωμάτων", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Επεξεργασία Μνήμης", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Επεξεργασία Χρήστη", "Edit User Group": "Επεξεργασία Ομάδας Χρηστών", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Ξεκινήστε περιπέτειες", "Embedding": "Ενσωμάτωση", "Embedding Batch Size": "Μέγεθος Παρτίδας Ενσωμάτωσης", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Μηχανή Μοντέλου Ενσωμάτωσης", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Ενεργοποίηση Εκτέλεσης Κώδικα", "Enable Code Interpreter": "Ενεργοποίηση Διερμηνέα Κώδικα", "Enable Community Sharing": "Ενεργοποίηση Κοινοτικής Κοινής Χρήσης", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Ενεργοποίηση Κλείδωσης Μνήμης (mlock) για την αποτροπή της ανταλλαγής δεδομένων του μοντέλου από τη μνήμη RAM. Αυτή η επιλογή κλειδώνει το σύνολο εργασίας των σελίδων του μοντέλου στη μνήμη RAM, διασφαλίζοντας ότι δεν θα ανταλλαχθούν στο δίσκο. Αυτό μπορεί να βοηθήσει στη διατήρηση της απόδοσης αποφεύγοντας σφάλματα σελίδων και διασφαλίζοντας γρήγορη πρόσβαση στα δεδομένα.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Ενεργοποίηση Χαρτογράφησης Μνήμης (mmap) για φόρτωση δεδομένων μοντέλου. Αυτή η επιλογή επιτρέπει στο σύστημα να χρησιμοποιεί αποθήκευση δίσκου ως επέκταση της μνήμης RAM, αντιμετωπίζοντας αρχεία δίσκου σαν να ήταν στη μνήμη RAM. Αυτό μπορεί να βελτιώσει την απόδοση του μοντέλου επιτρέποντας γρηγορότερη πρόσβαση στα δεδομένα. Ωστόσο, μπορεί να μην λειτουργεί σωστά με όλα τα συστήματα και να καταναλώνει σημαντικό χώρο στο δίσκο.", "Enable Message Queue": "", "Enable Message Rating": "Ενεργοποίηση Αξιολόγησης Μηνυμάτων", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Ενεργοποίηση Νέων Εγγραφών", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Ενεργοποιημένο", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Βεβαιωθείτε ότι το αρχείο CSV σας περιλαμβάνει 4 στήλες με αυτή τη σειρά: Όνομα, Email, Κωδικός, Ρόλος.", "Enter {{role}} message here": "Εισάγετε το μήνυμα {{role}} εδώ", - "Enter a detail about yourself for your LLMs to recall": "Εισάγετε μια λεπτομέρεια για τον εαυτό σας ώστε τα LLMs να την ανακαλούν", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Εισάγετε την Επικάλυψη Τμημάτων", "Enter Chunk Size": "Εισάγετε το Μέγεθος Τμημάτων", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Εισάγετε Jupyter URL", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Εισάγετε κωδικούς γλώσσας", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Εισάγετε URL διακομιστή μεσολάβησης (π.χ. https://user:password@host:port)", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Εισάγετε το Score", "Enter SearchApi API Key": "Εισάγετε το Κλειδί API SearchApi", "Enter SearchApi Engine": "Εισάγετε τη Μηχανή SearchApi", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Εισάγετε το Κλειδί API SerpApi", "Enter SerpApi Engine": "Εισάγετε τη Μηχανή SerpApi", "Enter Serper API Key": "Εισάγετε το Κλειδί API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Εισάγετε το Κλειδί API Serply", "Enter Serpstack API Key": "Εισάγετε το Κλειδί API Serpstack", "Enter server host": "Εισάγετε τον διακομιστή host", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Εισάγετε το URL διακομιστή Tika", "Enter timeout in seconds": "Εισάγετε το χρονικό όριο σε δευτερόλεπτα", "Enter to Send": "Εισάγετε για Αποστολή", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Εισάγετε το Top K", "Enter Top K Reranker": "Εισάγετε το Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Εισάγετε το URL (π.χ. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Αξιολογήσεις", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "API κλειδί του Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Παράδειγμα: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Παράδειγμα: ALL", "Example: mail": "Παράδειγμα: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Εξαγωγή σε CSV", "Export Tools": "", "Export Users": "Εξαγωγή Χρηστών", "External": "Εξωτερική", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Εξωτερικό Μοντέλο Εργασιών", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "API κλειδί του εξωτερικού διακομιστή φόρτωσης", "External Web Loader URL": "URL του εξωτερικού διακομιστή φόρτωσης", "External Web Search API Key": "API κλειδί του εξωτερικού διακομιστή αναζήτησης", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Αποτυχία δημιουργίας Κλειδιού API.", "Failed to delete calendar": "", "Failed to delete note": "Αποτυχία διαγραφής σημειώσεως", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Αποτυχία ανάκτησης μοντέλων", "Failed to generate title": "Αποτυχία δημιουργίας τίτλου", "Failed to import models": "Αποτυχία εισαγωγής μοντέλων", + "Failed to load chat": "", "Failed to load chat preview": "Αποτυχία φόρτωσης προεπισκόπησης συνομιλίας", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "Αποτυχία μετακίνησης συνομιλίας", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Αποτυχία ανάγνωσης περιεχομένων πρόχειρου", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "Αποτυχία απεικόνισης διαγράμματος", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Αποτυχία αποθήκευσης ρυθμίσεων μοντέλων", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Αποτυχία ενημέρωσης ρυθμίσεων", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Αποτυχία ανεβάσματος αρχείου.", "Features": "Λειτουργίες", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Αρχεία", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Φίλτρο", "Filter is now globally disabled": "Το φίλτρο είναι τώρα καθολικά απενεργοποιημένο", "Filter is now globally enabled": "Το φίλτρο είναι τώρα καθολικά ενεργοποιημένο", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "Φάκελοι", + "Folders Sharing": "", "Follow up": "Συνέχιση", "Follow Up Generation": "Δημιουργία Συνέχισης", "Follow Up Generation Prompt": "Προτροπή Δημιουργίας Συνέχισης", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Η λειτουργία είναι τώρα καθολικά ενεργοποιημένη", "Function Name": "Όνομα Λειτουργίας", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Η λειτουργία ενημερώθηκε με επιτυχία", "Functions": "Λειτουργίες", "Functions allow arbitrary code execution.": "Οι λειτουργίες επιτρέπουν την εκτέλεση αυθαίρετου κώδικα.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Η ομάδα δημιουργήθηκε με επιτυχία", "Group deleted successfully": "Η ομάδα διαγράφηκε με επιτυχία", "Group Description": "Περιγραφή Ομάδας", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Ανατροφοδότηση Haptic", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "Εισαγωγή επιτυχής", "Import Tools": "", "Important Update": "Σημαντική ενημέρωση", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Κρατήστε στην πλευρική μπάρα", "Key": "Κλειδί", "Key is required": "Το κλειδί είναι απαραίτητο", - "Keyboard shortcuts": "Συντομεύσεις Πληκτρολογίου", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "Πρόσβαση στο Knowledge", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Όνομα Knowledge", "Knowledge Public Sharing": "Κοινή χρήση Knowledge", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Το Knowledge ενημερώθηκε με επιτυχία", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Τελευταία απάντηση", "LDAP": "LDAP", - "LDAP server updated": "Ο διακομιστής LDAP ενημερώθηκε", "Leaderboard": "Κατάταξη", "Learn more": "", "Learn More": "Μάθετε Περισσότερα", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Άδεια", + "Lifecycle JSON": "", "Lift List": "", "Light": "Φως", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Η πρόσβαση στην τοποθεσία δεν επιτρέπεται", "Lost": "Χαμένος", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Δημιουργήθηκε από την Κοινότητα OpenWebUI", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Διαχείριση Καναλιών", "Manage Tool Servers": "Διαχείριση Διακομιστών Εργαλείων", "Manage your account information.": "Διαχειριστείτε τις πληροφορίες του λογαριασμού σας.", + "Mapped Source": "", "March": "Μάρτιος", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Η μνήμη καθαρίστηκε με επιτυχία", "Memory deleted successfully": "Η μνήμη διαγράφηκε με επιτυχία", "Memory updated successfully": "Η μνήμη ενημερώθηκε με επιτυχία", + "Merge Accounts by Email": "", "Merge Responses": "Συγχώνευση Απαντήσεων", "Merged Response": "Συγχωνευμένη απάντηση", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Τα μηνύματα που στέλνετε μετά τη δημιουργία του συνδέσμου σας δεν θα κοινοποιηθούν. Οι χρήστες με το URL θα μπορούν να δουν τη συνομιλία που μοιραστήκατε.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Κλειδί API Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Περισσότερα", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Ονομάστε τη βάση γνώσης σας", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Δεν υπάρχει διαθέσιμη απόσταση", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Δεν έχει επιλεγεί αρχείο", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "Δεν βρέθηκαν προτροπές", + "No Repeat": "", "No results": "Δεν βρέθηκαν αποτελέσματα", "No results found": "Δεν βρέθηκαν αποτελέσματα", "No search query generated": "Δεν δημιουργήθηκε ερώτηση αναζήτησης", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "IDs Κόμβων", "None": "Κανένα", + "Not configured": "", "Not factually correct": "Δεν είναι γεγονότα", "Not helpful": "Δεν είναι χρήσιμο", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Ειδοποιήσεις", "November": "Νοέμβριος", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Οκτώβριος", "Off": "Ανενεργό", "Okay, Let's Go!": "Εντάξει, Πάμε!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Σκούρο OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Οι ρυθμίσεις API Ollama ενημερώθηκαν", "Ollama Cloud API Key": "", "Ollama Version": "Έκδοση Ollama", + "Omit": "", "On": "Ενεργό", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "Κωδικός", "Passwords do not match.": "Οι κωδικοί δεν ταιριάζουν", "Paste Large Text as File": "Επικόλληση Μεγάλου Κειμένου ως Αρχείο", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Έγγραφο PDF (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "εκκρεμεί", "Pending": "Εκκρεμεί", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Άρνηση δικαιώματος κατά την πρόσβαση σε μέσα συσκευές", "Permission denied when accessing microphone": "Άρνηση δικαιώματος κατά την πρόσβαση σε μικρόφωνο", "Permission denied when accessing microphone: {{error}}": "Άρνηση δικαιώματος κατά την πρόσβαση σε μικρόφωνο: {{error}}", "Permissions": "Δικαιώματα", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API κλειδί", "Perplexity Model": "Perplexity Μοντέλο", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Προσωποποίηση", + "Picture Claim": "", "Pin": "Καρφίτσωμα", "Pin to Sidebar": "", "Pinned": "Καρφιτσωμένο", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Παρακαλώ συμπληρώστε όλα τα πεδία.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "Παρακαλώ επιλέξτε έναν λόγο", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Θύρα", "Ports": "", "Positive attitude": "Θετική στάση", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Δημόσιο", "Pull \"{{searchValue}}\" from Ollama.com": "Τραβήξτε \"{{searchValue}}\" από το Ollama.com", "Pull a model from Ollama.com": "Τραβήξτε ένα μοντέλο από το Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "Ανάγνωση Φωναχτά", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Εγγραφή φωνής", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Μετακατεύθυνση στην Κοινότητα OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Αναφέρεστε στον εαυτό σας ως \"User\" (π.χ., \"User μαθαίνει Ισπανικά\")", "Reference Chats": "Αναφορά σε Συνομιλίες", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Αρνήθηκε όταν δεν έπρεπε", "Regenerate": "Επαναδημιουργία", "Regenerate Menu": "Επαναδημιουργία Μενού", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Επαναταξινόμηση Μοντέλων", + "Repeat": "", "Repeats": "", "Reply": "Απάντηση", "Reply in Thread": "Απάντηση στο Νήμα Συζήτησης", "Reply to thread...": "Απάντηση στο νήμα συζήτησης...", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "απαιτείται", "Reranking Batch Size": "", "Reranking Engine": "Μηχανή Επαναταξινόμησης", "Reranking Model": "Μοντέλο Επαναταξινόμησης", + "Research Knowledge": "", "Reset": "Επαναφορά", "Reset All Models": "Επαναφορά Όλων των Μοντέλων", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Επαναφορά εικόνας", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Επαναφορά Καταλόγου Ανεβάσματος", "Reset Vector Storage/Knowledge": "Επαναφορά Αποθήκευσης Διανυσμάτων/Knowledge", "Reset view": "Επαναφορά προβολής", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Πλούσιο Εισαγωγή Κειμένου για Συνομιλία", "Role": "Ρόλος", + "Roles Claim": "", "RTL": "RTL", "Run": "Εκτέλεση", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Η αποθήκευση των αρχείων συνομιλίας απευθείας στη μνήμη αποθήκευσης του προγράμματος περιήγησής σας δεν υποστηρίζεται πλέον. Παρακαλώ αφιερώστε λίγο χρόνο να κατεβάσετε και να διαγράψετε τα αρχεία συνομιλίας σας κάνοντας κλικ στο κουμπί παρακάτω. Μην ανησυχείτε, μπορείτε εύκολα να επαναφέρετε τα αρχεία συνομιλιών σας στο backend μέσω", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Αναζήτηση", "Search a model": "Αναζήτηση μοντέλου", + "Search actions": "", "Search all emojis": "Αναζήτησε όλα τα emojis", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Αναζήτηση Συνομιλιών", "Search Collection": "Αναζήτηση Συλλογής", "Search Files": "", + "Search filters": "", "Search Filters": "Φίλτρα Αναζήτησης", "search for archived chats": "αναζήτηση για αρχειοθετημένες συνομιλίες", "search for folders": "αναζήτηση για φακέλους", @@ -1812,13 +1955,16 @@ "Search Models": "Αναζήτηση Μοντέλων", "Search Notes": "Αναζήτηση Σημειώσεων", "Search options": "Επιλογές Αναζήτησης", + "Search or add pattern": "", "Search Prompts": "Αναζήτηση Προτροπών", "Search Result Count": "Αριθμός Αποτελεσμάτων Αναζήτησης", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Αναζήτησε το διαδίκτυο", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Αναζήτηση Εργαλείων", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Κλειδί API SearchApi", "SearchApi Engine": "Μηχανή SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Επιλογή", "Select {{modelName}} model": "", - "Select a base model": "Επιλέξτε ένα βασικό μοντέλο", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Επιλέξτε μια μηχανή", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Αποστολή", "Send a Message": "Αποστολή Μηνύματος", + "Send events for": "", "Send message": "Αποστολή μηνύματος", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Στέλνει `stream_options: { include_usage: true }` στο αίτημα.\nΟι υποστηριζόμενοι πάροχοι θα επιστρέψουν πληροφορίες χρήσης token στην απάντηση όταν ρυθμιστεί.", "September": "Σεπτέμβριος", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Κλειδί API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Κλειδί API Serply", "Serpstack API Key": "Κλειδί API Serpstack", "Server connection failed": "", "Server connection verified": "Η σύνδεση διακομιστή επαληθεύθηκε", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Ορισμός ως προεπιλογή", "Set as Production": "", "Set embedding model": "Ορισμός μοντέλου ενσωμάτωσης", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Κοινή Χρήση στην Κοινότητα OpenWebUI", "Share your background and interests": "Μοιραστείτε μερικά λόγια για εσάς, όπως τα ενδιαφέροντά σας", + "Shared": "", "Shared Chats": "", "Shared with you": "Μοιρασμένα με εσάς", "Sharing Permissions": "Δικαιώματα Κοινής Χρήσης", "Show": "Εμφάνιση", - "Show \"What's New\" modal on login": "Εμφάνιση του παράθυρου \"Τι νέο υπάρχει\" κατά την είσοδο", + "Show \"What's New\" Modal on Login": "Εμφάνιση του παράθυρου \"Τι νέο υπάρχει\" κατά την είσοδο", "Show Admin Details in Account Pending Overlay": "Εμφάνιση Λεπτομερειών Διαχειριστή στο Υπέρθεση Εκκρεμής Λογαριασμού", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Πηγή", + "Specific users or groups": "", "Speech Playback Speed": "Ταχύτητα Αναπαραγωγής Ομιλίας", "Speech recognition error: {{error}}": "Σφάλμα αναγνώρισης ομιλίας: {{error}}", "Speech-to-Text": "Ομιλία σε Κείμενο", @@ -1999,6 +2154,7 @@ "STT Settings": "Ρυθμίσεις Μετατροπής Ομιλίας σε Κείμενο", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Σύστημα", + "System events only": "", "System Instructions": "Οδηγίες Συστήματος", "System Prompt": "Προτροπή Συστήματος", + "Table": "", "Tag": "Ετικέτα", "Tags": "Ετικέτες", "Tags Generation": "Δημιουργία Ετικετών", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Διαχωριστής Κειμένου", "Text-to-Speech": "Κείμενο σε Ομιλία", "Text-to-Speech Engine": "Μηχανή Ομιλίας σε Κείμενο", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "Το χαρακτηριστικό LDAP που αντιστοιχεί στο όνομα χρήστη που χρησιμοποιούν οι χρήστες για να συνδεθούν.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Η κατάταξη είναι αυτή τη στιγμή σε δοκιμαστική φάση, και ενδέχεται να προσαρμόσουμε τους υπολογισμούς βαθμολογίας καθώς βελτιώνουμε τον αλγόριθμο.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Το μέγιστο μέγεθος αρχείου σε MB. Αν το μέγεθος του αρχείου υπερβαίνει αυτό το όριο, το αρχείο δεν θα ανεβεί.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Ο μέγιστος αριθμός αρχείων που μπορούν να χρησιμοποιηθούν ταυτόχρονα στη συνομιλία. Αν ο αριθμός των αρχείων υπερβαίνει αυτό το όριο, τα αρχεία δεν θα ανεβούν.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Αυτή είναι μια πειραματική λειτουργία, μπορεί να μην λειτουργεί όπως αναμένεται και υπόκειται σε αλλαγές οποιαδήποτε στιγμή.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Αυτό το μοντέλο δεν είναι δημόσια διαθέσιμο. Επιλέξτε ένα άλλο μοντέλο.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Για να μάθετε περισσότερα για τα διαθέσιμα endpoints, δείτε την τεκμηρίωσή μας.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Για να επιλέξετε toolkits εδώ, προσθέστε τα πρώτα στον χώρο εργασίας \"Εργαλεία\".", - "Toast notifications for new updates": "Ειδοποιήσεις Toast για νέες ενημερώσεις", + "Toast Notifications for New Updates": "Ειδοποιήσεις Toast για νέες ενημερώσεις", "Today": "Σήμερα", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Σήμερα στις {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Πολύ λεπτομερές", @@ -2184,14 +2350,19 @@ "Unpin": "Ξεκαρφίτσωμα", "Unpin from Sidebar": "", "Unravel secrets": "Ξετυλίξτε μυστικά", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Χωρίς Ετικέτες", "Untitled": "", "Update": "Ενημέρωση", "Update and Copy Link": "Ενημέρωση και Αντιγραφή Συνδέσμου", + "Update Email": "", "Update for the latest features and improvements.": "Ενημερωθείτε για τις τελευταίες λειτουργίες και βελτιώσεις.", + "Update Name": "", "Update password": "Ενημέρωση κωδικού", + "Update Picture": "", "Update your status": "", "Updated": "Ενημερώθηκε", "Updated at": "Ενημερώθηκε στις", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Χρησιμοποιήστε '#' στην είσοδο προτροπής για φόρτωση και συμπερίληψη της γνώσης σας.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Χρήση LLM", "Use no proxy to fetch page contents.": "Μη χρήση διακομιστή μεσολάβησης για λήψη περιεχομένου σελίδων.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Χρήση διακομιστή μεσολάβησης προορισμένο από τις http_proxy και https_proxy μεταβλητές περιβάλλοντος για λήψη περιεχομένου σελίδων.", + "Use Web Search?": "", "user": "χρήστης", "User": "Χρήστης", + "User Access": "", "User Activity": "", "User Groups": "Ομάδες Χρηστών", "User location successfully retrieved.": "Η τοποθεσία του χρήστη ανακτήθηκε με επιτυχία.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Webhooks Χρήστη", "Username": "Όνομα Χρήστη", + "Username Claim": "", "users": "", "Users": "Χρήστες", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Οι βαλβίδες ενημερώθηκαν", "Valves updated successfully": "Οι βαλβίδες ενημερώθηκαν με επιτυχία", "variable": "μεταβλητή", + "Vector Field": "", "Verify Connection": "Επαλήθευση Σύνδεσης", "Verify SSL Certificate": "Επαλήθευση Πιστοποιητικού SSL", "Version": "Έκδοση", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "Μηχανή Φόρτωσης Διαδικτύου", "Web Search": "Αναζήτηση στο Διαδίκτυο", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Μηχανή Αναζήτησης στο Διαδίκτυο", "Web Search in Chat": "", "Web Search Query Generation": "Δημιουργία Ερωτήματος Αναζήτησης Διαδικτύου", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL Webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Ρυθμίσεις WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Εχθές", "Yesterday at {{LOCALIZED_TIME}}": "Εχθές στις {{LOCALIZED_TIME}}", "You": "Εσείς", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Η ολόκληρη η συνεισφορά σας θα πάει απευθείας στον προγραμματιστή του plugin· το Open WebUI δεν παίρνει κανένα ποσοστό. Ωστόσο, η επιλεγμένη πλατφόρμα χρηματοδότησης μπορεί να έχει τα δικά της τέλη.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Γλώσσα YouTube", diff --git a/src/lib/i18n/locales/en-GB/translation.json b/src/lib/i18n/locales/en-GB/translation.json index a87e9e153e..999dd8a5e9 100644 --- a/src/lib/i18n/locales/en-GB/translation.json +++ b/src/lib/i18n/locales/en-GB/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "", "{{webUIName}} Backend Required": "", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "", @@ -72,6 +83,7 @@ "Activity": "", "Add": "", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "", "Add a tag": "", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "", + "Admin Roles": "", "Admin Settings": "", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "", + "API Key / Token": "", "API Key created.": "", "API Key Endpoint Restrictions": "", "API keys": "", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "", "August": "", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "", - "Auto-playback response": "", + "Auto-Create Groups": "", + "Auto-Playback Response": "", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "", + "Available variables": "", "available!": "", "Away": "", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "", "Banners": "", "Base Model (From)": "", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "", + "Chat Direction": "", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "", + "Collection Field": "", "Collections": "", "Color": "Colour", "ComfyUI": "", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "", "Default model updated": "", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "", + "Default webhook": "", "Defaults": "", "Delete": "", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "", + "Display the Username Instead of You in the Chat": "", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "", "Enter Chunk Size": "", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "Enter Key Behaviour", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "", "No results found": "", "No search query generated": "", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "", "November": "", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "", "Off": "", "Okay, Let's Go!": "", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "", + "Omit": "", "On": "", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalisation", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "", + "Roles Claim": "", "RTL": "", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "", "Send a Message": "", + "Send events for": "", "Send message": "", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "", "Stylized PDF Export": "Stylised PDF Export", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "", + "System events only": "", "System Instructions": "", "System Prompt": "", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index ed6da124f6..4accabe7b4 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "", "{{webUIName}} Backend Required": "", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "", @@ -72,6 +83,7 @@ "Activity": "", "Add": "", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "", "Add a tag": "", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "", + "Admin Roles": "", "Admin Settings": "", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "", + "API Key / Token": "", "API Key created.": "", "API Key Endpoint Restrictions": "", "API keys": "", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "", "August": "", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "", - "Auto-playback response": "", + "Auto-Create Groups": "", + "Auto-Playback Response": "", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "", + "Available variables": "", "available!": "", "Away": "", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "", "Banners": "", "Base Model (From)": "", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "", + "Chat Direction": "", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "", "Default model updated": "", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "", + "Default webhook": "", "Defaults": "", "Delete": "", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "", + "Display the Username Instead of You in the Chat": "", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "", "Enter Chunk Size": "", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "", "No results found": "", "No search query generated": "", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "", "November": "", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "", "Off": "", "Okay, Let's Go!": "", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "", + "Omit": "", "On": "", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "", + "Roles Claim": "", "RTL": "", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "", "Send a Message": "", + "Send events for": "", "Send message": "", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "", + "System events only": "", "System Instructions": "", "System Prompt": "", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/es-ES/translation.json b/src/lib/i18n/locales/es-ES/translation.json index 4f47cf992e..e792ec0937 100644 --- a/src/lib/i18n/locales/es-ES/translation.json +++ b/src/lib/i18n/locales/es-ES/translation.json @@ -9,31 +9,42 @@ "[Today at] h:mm A": "[Hoy a las] h:mm A", "[Yesterday at] h:mm A": "[Ayer a las] h:mm A", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Skills": "", - "{{COUNT}} Available Tools": "{{COUNT}} herramientas disponibles", + "{{COUNT}} Available Skills": "{{COUNT}} Habilidades disponibles", + "{{COUNT}} Available Tools": "{{COUNT}} Herramientas disponibles", "{{COUNT}} characters": "{{COUNT}} caracteres", "{{COUNT}} extracted lines": "{{COUNT}} líneas extraidas", "{{COUNT}} files": "{{COUNT}} archivos", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "Se seleccionaron {{count}} archivos. Solo se subirán los archivos nuevos y modificados. Los archivos borrados se eliminarán. La estructura de carpetas se clonará. ¿Continuar?_únicos", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "Se seleccionaron {{count}} archivos. Solo se subirán los archivos nuevos y modificados. Los archivos borrados se eliminarán. La estructura de carpetas se clonará. ¿Continuar?_multiples", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "Se seleccionaron {{count}} archivos. Solo se subirán los archivos nuevos y modificados. Los archivos borrados se eliminarán. La estructura de carpetas se clonará. ¿Continuar?_otros", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} líneas ocultas", "{{COUNT}} members": "{{COUNT}} miembros", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_many": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}} de {{total}} accessible_únicos", + "{{count}} of {{total}} accessible_many": "{{count}} de {{total}} accessible_multiple", + "{{count}} of {{total}} accessible_other": "{{count}} de {{total}} accessible_otros", "{{COUNT}} Replies": "{{COUNT}} Respuestas", "{{COUNT}} Rows": "{{COUNT}} filas", - "{{count}} selected_one": "{{count}} únicos seleccionados", - "{{count}} selected_many": "{{count}} múltiples seleccionados", - "{{count}} selected_other": "{{count}} otros seleccionados", + "{{count}} selected_one": "{{count}} seleccionados_únicos", + "{{count}} selected_many": "{{count}} seleccionados_multiples", + "{{count}} selected_other": "{{count}} seleccionados_otros", "{{COUNT}} Sources": "{{COUNT}} Fuentes", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} palabras", "{{COUNT}}d_time_ago": "hace_{{COUNT}}d", "{{COUNT}}h_time_ago": "hace_{{COUNT}}h", "{{COUNT}}m_time_ago": "hace_{{COUNT}}m", "{{COUNT}}w_time_ago": "hace_{{COUNT}}s", "{{COUNT}}y_time_ago": "hace_{{COUNT}}a", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} a las {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "La descarga de {{model}} se ha cancelado", "{{modelName}} profile image": "imagen de perfíl de {{modelName}}", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Chats de {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Servidor Requerido", "*Prompt node ID(s) are required for image generation": "Los ID de nodo son requeridos para la generación de imágenes", + "1 group": "", "1 hour before": "hace 1 hora", "1 Source": "1 Fuente", + "1 user": "", "10 minutes before": "hace 10 minutos", "15 minutes before": "hace 15 minutos", "1m_time_ago": "hace_1m", @@ -60,6 +73,7 @@ "Access Control": "Control de Permisos", "Access Grants": "Permisos Otorgados", "Access List": "Lista de Permisos", + "Access prohibited": "", "Access updated": "Permisos actualizados", "Accessible to all users": "Accesible para todos los usuarios", "Account": "Cuenta", @@ -75,6 +89,7 @@ "Activity": "Actividad", "Add": "Añadir", "Add a model ID": "Añadir un ID de modelo", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Añadir una breve descripción sobre lo que hace este modelo", "Add a tag": "Añadir una etiqueta", "Add a tag...": "Añadir una etiqueta...", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Añadir Indicador Personalizado", "Add description": "Añadir descripción", "Add Details": "Añadir Detalles", + "Add durable context for future chats": "", "Add Files": "Añadir Archivos", "Add Image": "Añadir Imagen", + "Add Knowledge Connection": "", "Add location": "Añadir Ubicación", "Add Member": "Añadir Miembro", "Add Members": "Añadir Miembros", @@ -103,6 +120,7 @@ "Add to favorites": "Añade a favoritos", "Add User": "Añadir Usuario", "Add User Group": "Añadir grupo de usuarios", + "Add webhook": "", "Add webpage": "Añadir página Web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Añadir la URL y la clave API de OpenTerminal en Configuración → Integraciones", "Additional Config": "Config Adicional", @@ -115,7 +133,9 @@ "Admin": "Admin", "Admin Contact Email": "Correo Electrónico de Contacto del Admin", "Admin Panel": "Administración", + "Admin Roles": "", "Admin Settings": "Ajustes de Admin", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Los administradores tienen acceso a todas las herramientas en todo momento; los usuarios necesitan que los modelos tengan asignadas las herramientas en el area de trabajo.", "Advanced": "Avanzado", "Advanced Parameters": "Parámetros Avanzados", @@ -126,16 +146,21 @@ "All": "Todos", "All chats have been unarchived.": "Todos los chats han sido desarchivados", "All day": "Todo el día", + "All events": "", "All models are now hidden": "Todos los modelos están ahora ocultos", "All models are now visible": "Todos los modelos están ahora visibles", "All models deleted successfully": "Todos los modelos se han borrados correctamente", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Todo el tiempo", "All Users": "Todos los Usuarios", + "All users and system events": "", "Allow Call": "Permitir Llamada", "Allow Chat Controls": "Permitir Controles del Chat", "Allow Chat Delete": "Permitir Borrar Chat", "Allow Chat Edit": "Permitir Editar Chat", "Allow Chat Export": "Permitir Exportar Chat", + "Allow Chat Import": "", "Allow Chat Params": "Permitir Parametros en Chat", "Allow Chat Share": "Permitir Compartir Chat", "Allow Chat System Prompt": "Permitir Indicador del Sistema en Chat", @@ -155,9 +180,11 @@ "Allow User Location": "Permitir Ubicación del Usuario", "Allow Voice Interruption in Call": "Permitir Interrupción de Voz en Llamada", "Allow Web Upload": "Permitir Subir Web", + "Allowed Domains": "", "Allowed Endpoints": "Endpoints Permitidos", "Allowed File Extensions": "Extensiones de Archivo Permitidas", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Extensiones de archivos permitidas para subir. Si son varias separalas con comas. Dejar vacío para permitir subir archivos con cualquier extensión.", + "Allowed Roles": "", "Already have an account?": "¿Ya tienes una cuenta?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa a top_p, como objetivo garantizar un equilibrio entre calidad y variedad. El parámetro p representa la mínima probabilidad para que un token sea considerado, relativo a la probabilidad del token más probable. Por ejemplo, con p=0.05 y la probabilidad del token más probable de 0.9, los resultados (logits) con un valor inferior a 0.045 son descartados.", "Always": "Siempre", @@ -176,6 +203,7 @@ "API Base URL": "URL Base API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL Base de la API de Datalab Marker service. La Predeterminada es: https://www.datalab.to/api/v1/marker", "API Key": "Clave API", + "API Key / Token": "", "API Key created.": "Clave API creada.", "API Key Endpoint Restrictions": "Clave API para Endpoints Restringidos", "API keys": "Claves de la API", @@ -201,17 +229,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "¿Estás seguro que quieres borrar todos los chats? (¡esta acción NO se puede deshacer!)", "Are you sure you want to delete this channel?": "¿Estás seguro de que quieres eliminar este canal?", "Are you sure you want to delete this connection? This action cannot be undone.": "¿Estás seguro que desea eliminar esta conexión? (¡esta acción NO se puede deshacer!)", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "¿Estás seguro que desea eliminar este directorio?", "Are you sure you want to delete this memory? This action cannot be undone.": "¿Estás seguro que desea eliminar esta memoria? (¡esta acción NO se puede deshacer!)", "Are you sure you want to delete this message?": "¿Estás seguro de que quieres eliminar este mensaje? ", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "¿Estás seguro que desea eliminar esta versión? (las versiones derivadas se vincularán a la versión principal de esta)", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "¿Estás seguro que desea eliminar esto?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "¿Estás seguro de que quieres desarchivar todos los chats archivados?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena de Modelos", "Artifacts": "Artefactos", "Asc": "Asc", "Ask": "Preguntar", "Ask a question": "Haz una pregunta", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistente", "Async Embedding Processing": "Procesado Asíncrono al Incrustrar", "At time of event": "En el momento del evento", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Agosto", "Auth": "Autorización", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentificar", "Authentication": "Autenticación", "Auto": "Auto", "Auto (Random)": "Auto (Aleatorio)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copiar automaticamente la respuesta al Portapapeles", - "Auto-playback response": "Reproducir respuesta automáticamente", + "Auto-Create Groups": "", + "Auto-Playback Response": "Reproducir respuesta automáticamente", "Autocomplete Generation": "Generación de Autocompletado", "Autocomplete Generation Input Max Length": "Max. Longitud de Entrada en Generación de Autocompletado", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "AUTOMATIC1111", "AUTOMATIC1111 Api Auth String": "Auth API para AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL Base de AUTOMATIC1111", @@ -248,9 +287,10 @@ "Automations": "Automatizaciones", "Available list": "Lista disponible", "Available models": "Modelos disponibles", - "Available Skills": "", + "Available Skills": "Habilidades disponibles", "Available Tools": "Herramientas Disponibles", "available users": "usuarios disponibles", + "Available variables": "", "available!": "¡disponible!", "Away": "Ausente", "Awful": "Horrible", @@ -261,16 +301,17 @@ "Bad Response": "Respuesta Errónea", "Banners": "Banners", "Base Model (From)": "Modelo Base (desde)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "La caché de la lista de modelos base acelera el acceso recuperando los modelos base sólo al inicio o en el autoguardado rápido de la configuración, si se activa hay que tener en cuenta que los cambios más recientes en las listas de modelos podrían no reflejarse de manera inmediata.", "Bearer": "Portador (Bearer)", "before": "antes", "Being lazy": "Vaguear", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Endpoint de Bing Search V7", "Bing Search V7 Subscription Key": "Clave de Suscripción de Bing Search V7", "Bio": "Bio", "Birth Date": "Fecha de nacimiento", + "Blocked Groups": "", "BM25 Weight": "Ponderación BM25", "Bocha Search API Key": "Clave de la API de Bocha Search", "Bold": "Negrita", @@ -327,7 +368,7 @@ "Chat Completions": "Completación del Chat", "Chat Conversation": "Conversación del Chat", "Chat deleted.": "Chat eliminado.", - "Chat direction": "Dirección del Chat", + "Chat Direction": "Dirección del Chat", "Chat exported successfully": "Chat exportado correctmente", "Chat History": "Historial del Chat", "Chat ID": "ID del Chat", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Canal de colaboración donde la gente se une como miembro", "Collapse": "Plegar", "Collection": "Colección", + "Collection Field": "", "Collections": "Colecciones", "Color": "Color", "ComfyUI": "ComfyUI", @@ -408,18 +450,20 @@ "ComfyUI Workflow": "Flujo de Trabajo de ComfyUI", "ComfyUI Workflow Nodes": "Nodos del Flujo de Trabajo de ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "IDs de Nodo separados por comas (ej. 1 o 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Lista de extensiones de fichero para procesar con MinerU, separadas por comas(ej. pdf, docx, pptx, xlsx)", "command": "comando", "Command": "Comando", "Comment": "Comentario", "Commit Message": "Corregir Mensaje", "Community Reviews": "Revisiones de la Comunidad", - "Comparing with knowledge base...": "", + "Compacting context": "", + "Comparing with knowledge base...": "Comparando con la base de conocimientos...", "Completions": "Cumplimientos", "Compress Images in Channels": "Comprimir Imágenes en Canales", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_many": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Computando checksums ({{count}} ficheros)_únicos", + "Computing checksums ({{count}} files)_many": "Computando checksums ({{count}} ficheros)_multiples", + "Computing checksums ({{count}} files)_other": "Computando checksums ({{count}} ficheros)_otros", "Concurrent Requests": "Número de Solicitudes Concurrentes", "Config": "Config", "Config imported successfully": "Configuración importada correctamente", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Conéctate a instancias de Open Terminal. Todos los usuarios tendrán acceso a la navegación de archivos y a las utilidades del terminal a través de estos servidores.", "Connect to your own OpenAI compatible API endpoints.": "Conectar a tus propios API endpoints compatibles con OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Conectar a tus propios endpoints externos de herramientas compatibles con OpenAPI.", + "Connected": "", "Connected ({{type}})": "Connectado ({{type}})", "Connection failed": "Conexión fallida", "Connection lost. Reconnecting...": "Conexxión perdida, reconectando...", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contacta con Admin para obtener acceso a WebUI", "Content": "Contenido", "Content Extraction Engine": "Motor para la Extracción de Contenido", + "Content Field": "", "Content lengths (character counts only)": "Longitud del contenido (solo recuento de caracteres)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Tokens en el Contexto", + "Continue": "", "Continue Response": "Continuar Respuesta", "Continue with {{provider}}": "Continuar con {{provider}}", "Continue with Email": "Continuar con Email", @@ -497,6 +550,7 @@ "Create new secret key": "Crear Nueva Clave Secreta", "Create note": "Crear Nota", "Create Note": "Crear Nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Crea indicadores programados para que se ejecuten automáticamente de forma recurrente.", "Create your first note by clicking on the plus button below.": "Crea tu primera nota pulsando el botón + de abajo", "Created at": "Creado en", @@ -514,6 +568,7 @@ "Custom Gender": "Género Personalizado", "Custom Parameter Name": "Nombre del Parámetro Personalizado", "Custom Parameter Value": "Valor del Parámetro Personalizado", + "Custom range": "", "Daily": "Diario", "Daily Messages": "Mensajes Diarios", "Danger Zone": "Zona Peligrosa", @@ -536,7 +591,6 @@ "Default Features": "Características Predeterminadas", "Default Filters": "Filtros Predeterminados", "Default Group": "Grupo Predeterminado", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "El modo predeterminado trabaja con un amplio rango de modelos, llamando a las herramientas una vez antes de la ejecución. El modo nativo aprovecha las capacidades de llamada de herramientas integradas del modelo, pero requiere que el modelo admita inherentemente esta función.", "Default Model": "Modelo Predeterminado", "Default model updated": "El modelo Predeterminado ha sido actualizado", "Default permissions": "Permisos Predeterminados", @@ -546,20 +600,21 @@ "Default to ALL": "Predeterminado a TODOS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Por defecto está predeterminada una segmentación de la recuperación para una extracción de contenido centrado y relevante, recomendado para la mayoría de los casos.", "Default User Role": "Rol predeterminado de los nuevos usuarios", + "Default webhook": "", "Defaults": "Predeterminados", "Delete": "Borrar", "Delete {{name}}": "Borrar {{name}}", "Delete a model": "Borrar un modelo", "Delete All": "Borrar Todo", "Delete All Chats": "Borrar todos los chats", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Borrar todo el contenido de este directorio", "Delete all contents inside this folder": "Borrar todo el contenido de esta carpeta", "Delete automation?": "¿Borrar automatización?", "Delete calendar": "Borrar calendario", "Delete Calendar": "Borrar Calendario", "Delete Chat": "Borrar Chat", "Delete chat?": "¿Borrar el chat?", - "Delete directory?": "", + "Delete directory?": "¿Borrar directorio?", "Delete Event": "Borrar Evento", "Delete File": "Borrar Fichero", "Delete folder?": "¿Borrar carpeta?", @@ -596,16 +651,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Las Conexiones Directas permiten a los usuarios conectar a sus propios endpoints compatibles API OpenAI.", "Direct Message": "Mensaje Directo", "Direct Tool Servers": "Servidores de Herramientas Directos", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Directorio creado", + "Directory deleted.": "Directorio borrado", + "Directory moved.": "Directorio movido", + "Directory name": "Nombre del Directorio", + "Directory renamed.": "Directorio renombrado", "Directory selection was cancelled": "La selección de directorio ha sido cancelada", "Disable All": "Deshabilitar Todo", "Disable Code Interpreter": "Deshabilitar Interprete de Código", "Disable Image Extraction": "Deshabilitar Extracción de Imágenes", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Desabilita la extracción de imágenes del pdf. Si está habilitado Usar LLM las imágenes se capturan automáticamente. Por defecto el valor es Falso (las imágenes se extraen).", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Deshabilitado", "Disconnect OAuth": "Desconectar OAuth", "Discover a function": "Descubrir Funciónes", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Descubre, descarga y explora modelos con preajustados", "Discussion channel where access is based on groups and permissions": "Canal de debate cuyo acceso está basado en grupos y permisos", "Display": "Mostrar", - "Display chat title in tab": "Mostrar título del chat en el tabulador", + "Display Chat Title in Tab": "Mostrar título del chat en el tabulador", "Display Emoji in Call": "Muestra Emojis en Llamada", "Display Multi-model Responses in Tabs": "Mostrar Respuestas de MultiModelos Tabuladas", - "Display the username instead of You in the Chat": "Mostrar en el chat el nombre de usuario en lugar del genérico Tu", + "Display the Username Instead of You in the Chat": "Mostrar en el chat el nombre de usuario en lugar del genérico Tu", "Displays citations in the response": "Mostrar citas en la respuesta", "Displays status updates (e.g., web search progress) in the response": "Muestra actualizaciones de estado (p.ej., progreso de la búsqueda web) en la respuesta", "Dive into knowledge": "Sumérgete en el conocimiento", @@ -634,6 +691,7 @@ "Docling Parameters": "Parámetros de Docling", "Docling Server URL required.": "Docling URL del servidor necesaria.", "Document": "Documento", + "Document ID Field": "", "Document Intelligence": "Azure Doc Intelligence", "Document Intelligence endpoint required.": "Endpoint Azure Doc Intelligence requerido", "Document Intelligence Model": "Modelo para Doc Intelligence", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Editar Permisos Predeterminados", "Edit Folder": "Editar Carpeta", "Edit Image": "Editar Imagen", + "Edit Knowledge Connection": "", "Edit Last Message": "Editar Último Mensaje", "Edit Memory": "Editar Memoria", "Edit Prompt": "Editar Indicador", "Edit Terminal Connection": "Editar Conexión del Terminal", "Edit User": "Editar Usuario", "Edit User Group": "Editar Grupo de Usuarios", + "Edit webhook": "", "Edit workflow.json content": "Editar el contenido de workflow.json", "edited": "editado", "Edited": "Editado", @@ -703,14 +763,16 @@ "Eject model": "Expulsar modelo", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Embarcate en aventuras", "Embedding": "Incrustación", "Embedding Batch Size": "Tamaño del Lote de Incrustación", "Embedding Concurrent Requests": "Número de Peticiones Concurrentes en Incrustración", "Embedding Model": "Modelo de Incrustación", "Embedding Model Engine": "Motor del Modelo de Incrustación", - "Emoji": "", + "Emoji": "Emoticono", "Emojis": "Emoticonos", + "Empty": "", "Empty message": "Mensaje vacío", "Enable All": "Habilitar Todo", "Enable API Keys": "Habilitar Claves API", @@ -718,22 +780,27 @@ "Enable Code Execution": "Habilitar Ejecución de Código", "Enable Code Interpreter": "Habilitar Interprete de Código", "Enable Community Sharing": "Habilitar Compartir con la Comunidad", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Habilitar bloqueo de memoria (mlock) para prevenir que los datos del modelo se intercambien fuera de la RAM. Esta opción bloquea el conjunto de páginas de trabajo del modelo en RAM, asegurando que no se intercambiarán fuera a disco. Esto puede ayudar a mantener el rendimiento evitando fallos de página y asegurando un acceso rápido a los datos.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Habilitar Mapeado de Memoria (mmap) para cargar datos del modelo. Esta opción permite al sistema usar el almacenamiento del disco como una extensión de la RAM al tratar los archivos en disco como si estuvieran en la RAM. Esto puede mejorar el rendimiento del modelo al permitir un acceso más rápido a los datos. Sin embargo, puede no funcionar correctamente con todos los sistemas y puede consumir una cantidad significativa de espacio en disco.", "Enable Message Queue": "Habilitar Cola de Mensajes", "Enable Message Rating": "Habilitar Calificación de los Mensajes", "Enable Mirostat sampling for controlling perplexity.": "Algoritmo de decodificación de texto neuronal que controla activamente el proceso generativo para mantener la perplejidad del texto generado en un valor deseado. Previene las trampas de aburrimiento (por excesivas repeticiones) y de incoherencia (por generación de excesivo texto).", "Enable New Sign Ups": "Habilitar Registros de Nuevos Usuarios", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Habilite, deshabilite o personalice las etiquetas de razonamiento utilizadas por el modelo. \"HAbilitado\" usa etiquetas predeterminadas, \"Deshabilitado\" desactiva las etiquetas de razonamiento y \"Personalizado\" le permite especificar sus propias etiquetas de inicio y fin.", "Enabled": "Habilitado", "End Tag": "Etiqueta de Fin", + "Endpoint": "", "Endpoint URL": "Endpoint URL", "Enforce Temporary Chat": "Forzar el uso de Chat Temporal", "Enhance": "Mejorar", "Enrich Hybrid Search Text": "Texto Enriquecido en la Búqueda Híbrida", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Asegúrese de que su archivo CSV incluya 4 columnas en este orden: Nombre, Correo Electrónico, Contraseña, Rol.", "Enter {{role}} message here": "Ingresar mensaje {{role}} aquí", - "Enter a detail about yourself for your LLMs to recall": "Ingresar detalles sobre ti para que los recuerden sus LLMs", "Enter a title for the pending user info overlay. Leave empty for default.": "Ingresar un título para la sobrecapa informativa de usuario pendiente. Dejar vacío para usar el predeterminado.", "Enter a watermark for the response. Leave empty for none.": "Ingresar una marca de agua para la respuesta. Dejalo vacío para ninguna", "Enter additional headers in JSON format": "Ingresar encabezados adicionales en formato JSON", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Introduce el Tamaño Mínimo de Fragmento", "Enter Chunk Overlap": "Ingresar Superposición de los Fragmentos", "Enter Chunk Size": "Ingresar el Tamaño del Fragmento", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Ingresar pares \"token:valor_sesgo\" separados por comas (ejemplo: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Ingresar contenido para la sobrecapa informativa de usuario pendiente. Dejar vacío para usar el predeterminado.", "Enter coordinates (e.g. 51.505, -0.09)": "Ingresar coordenadas (ej. 51.505, -0.09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Ingresar URL de Jupyter", "Enter Kagi Search API Key": "Ingresar Clave API de Kagi Search", "Enter Key Behavior": "Comportamiento de la Tecla de Envío", + "Enter language": "", "Enter language codes": "Ingresar Códigos de Idioma", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Ingresar Clave API de Linkup", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Ingresar Clave API de MinerU", "Enter Mistral API Base URL": "Ingresar la URL Base de la API de Mistral", "Enter Mistral API Key": "Ingresar Clave API de Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "Ingresar indicador aquí.", "Enter proxy URL (e.g. https://user:password@host:port)": "Ingresar URL del proxy (p.ej. https://user:password@host:port)", "Enter reasoning effort": "Ingresar esfuerzo de razonamiento", + "Enter Redirect URI": "", "Enter Score": "Ingresar Puntuación", "Enter SearchApi API Key": "Ingresar Clave API de SearchApi", "Enter SearchApi Engine": "Ingresar Motor de SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Ingresar Clave API de SerpApi", "Enter SerpApi Engine": "Ingresar Motor de SerpApi", "Enter Serper API Key": "Ingresar Clave API de Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Ingresar Clave API de Serply", "Enter Serpstack API Key": "Ingresar Clave API de Serpstack", "Enter server host": "Ingresar host del servidor", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Ingresar URL del servidor Tika", "Enter timeout in seconds": "Ingresar tiempo límite de espera en segundos", "Enter to Send": "'Enter' para Enviar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Ingresar Top K", "Enter Top K Reranker": "Ingresar Top K Reclasificador", "Enter URL (e.g. http://127.0.0.1:7860/)": "Ingresar URL (p.ej., http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Error: Ya existe un modelo con el ID '{{modelId}}'. Seleccione otro ID para continuar.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Error: El ID del modelo no puede estar vacío. Ingrese un ID válido para continuar.", "Evaluations": "Evaluaciones", + "Event": "", "Event created": "Evento creado", "Event deleted": "Evento borrado", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Titulo del Evento", "Event updated": "Evento actualizado", + "Events": "", "Exa API Key": "Clave API de Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Ejemplo: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Ejemplo: TODOS", "Example: mail": "Ejemplo: correo", @@ -909,12 +989,18 @@ "Export Config": "Exportar Config", "Export Models": "Exportar Modelos", "Export Prompts": "Exportar Indicadores", + "Export Skills": "", "Export to CSV": "Exportar a CSV", "Export Tools": "Exportar Herramientas", "Export Users": "Exportar Usuarios", "External": "Externo", + "External connection not found.": "", "External Document Loader URL required.": "LA URL del Cargador Externo de Documentos es requerida.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Modelo Externo de Herramientas", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Clave API del Cargador Web Externo", "External Web Loader URL": "URL del Cargador Web Externo", "External Web Search API Key": "Clave API del Buscador Web Externo", @@ -925,13 +1011,14 @@ "Failed to archive chat.": "Fallo al archivar el chat", "Failed to attach file": "Fallo al adjuntar el archivo", "Failed to clear status": "Fallo al limpiar el estado", - "Failed to compare files.": "", + "Failed to compare files.": "Fallo al comparar los archivos", "Failed to connect to {{URL}} OpenAPI tool server": "Fallo al conectar al servidor de herramientas: {{URL}}", "Failed to connect to {{URL}} terminal server": "Fallo al conectar al servidor de terminal: {{URL}}", "Failed to copy link": "Fallo al copiar enlace", "Failed to create API Key.": "Fallo al crear la Clave API.", "Failed to delete calendar": "Fallo al borrar el calendario", "Failed to delete note": "Fallo al eliminar nota", + "Failed to delete webhook": "", "Failed to disconnect": "Fallo al desconectar", "Failed to download image": "Fallo al descargar imagen", "Failed to extract content from the file: {{error}}": "Fallo al extraer el contenido del archivo: {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Fallo al obtener los modelos", "Failed to generate title": "Fallo al generar el título", "Failed to import models": "Fallo al importar modelos", + "Failed to load chat": "", "Failed to load chat preview": "Fallo al cargar la previsualización del chat", "Failed to load DOCX file. Please try downloading it instead.": "Fallo al cargar el archivo DOCX. Por favor, en su lugar intente descargarlo", "Failed to load Excel/CSV file. Please try downloading it instead.": "Fallo al cargar el archivo Excel/CSV. Por favor, en su lugar intente descargarlo.", @@ -948,6 +1036,7 @@ "Failed to move chat": "Fallo al mover el chat", "Failed to process URL: {{url}}": "Fallo al procesar la URL", "Failed to read clipboard contents": "Fallo al leer el contenido del portapapeles", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Fallo al eliminar miembro", "Failed to render diagram": "Fallo al renderizar el diagrama", "Failed to render visualization": "Fallo al renderizar la visualización", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Fallo al guardar la configuración de los modelos", "Failed to save policy: {{error}}": "Fallo al guardar las normas: {{error}}", "Failed to save terminal servers": "Fallo al guardar los servidores de terminal", + "Failed to save webhook": "", "Failed to unshare chat.": "Fallo al descompartir chat.", "Failed to update settings": "Fallo al actualizar los ajustes", "Failed to update status": "Fallo al actualizar el estado", + "Failed to update webhook": "", "Failed to upload file.": "Fallo al subir el archivo.", "Features": "Características", "Features Permissions": "Permisos de las Características", @@ -979,18 +1070,20 @@ "File content updated successfully.": "Contenido del archivo actualizado correctamente.", "File Context": "Contexto del Archivo", "File deleted successfully.": "Archivo borrado correctamente.", - "File Extensions": "", + "File Extensions": "Extensiones de Fichero", "File Mode": "Modo de Archivo", - "File moved.": "", + "File moved.": "Archivo movido", "File name": "Nombre del archivo", "File not found.": "Archivo no encontrado.", "File removed successfully.": "Archivo eliminado correctamente.", - "File renamed.": "", + "File renamed.": "Archivo renombrado", "File size should not exceed {{maxSize}} MB.": "Tamaño del archivo no debe exceder {{maxSize}} MB.", "File Upload": "Subir Archivo", "File uploaded successfully": "Archivo subido correctamente", "Filename": "Nombre del Archivo", "Files": "Archivos", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtro", "Filter is now globally disabled": "El filtro ahora está desactivado globalmente", "Filter is now globally enabled": "El filtro ahora está habilitado globalmente", @@ -1013,6 +1106,7 @@ "Folder options": "Opciones de la Carpeta", "Folder updated successfully": "Carpeta actualizada correctamente", "Folders": "Carpetas", + "Folders Sharing": "", "Follow up": "Seguimiento", "Follow Up Generation": "Seguimiento de la Generación", "Follow Up Generation Prompt": "Seguimiento de la Generación del Indicador", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "La Función ahora está habilitada globalmente", "Function Name": "Nombre de la Función", "Function Name Filter List": "Lista del Filtro de Nombres de Función", + "Function starter": "", "Function updated successfully": "Función actualizada correctamente", "Functions": "Funciones", "Functions allow arbitrary code execution.": "Las Funciones habilitan la ejecución de código arbitrario.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Cuadrícula", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Canal de Grupo", + "Group Claim": "", "Group created successfully": "Grupo creado correctamente", "Group deleted successfully": "Grupo eliminado correctamente", "Group Description": "Descripción del Grupo", @@ -1087,6 +1185,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Realimentación Háptica", + "Header variables": "", "Headers": "Encabezados", "Headers must be a valid JSON object": "El Encabezado debe ser un objeto JSON válido", "Height": "Altura", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID no puede contener los caracteres \":\" o \"|\"", "ID copied to clipboard": "ID copiado al portapapeles", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Tiempo de espera por inactividad", "iframe Sandbox Allow Forms": "iframe Sandbox Allow Forms", "iframe Sandbox Allow Same Origin": "iframe Sandbox Allow Same Origin", @@ -1142,6 +1243,7 @@ "Import From Link": "Importar desde Enlace", "Import Models": "Importar Modelos", "Import Prompts": "Importar Indicadores", + "Import Skills": "", "Import successful": "Importación realizada correctamente", "Import Tools": "Importar Herramientas", "Important Update": "Actualización importante", @@ -1199,12 +1301,11 @@ "Keep in Sidebar": "Mantener en Barra Lateral", "Key": "Clave", "Key is required": "La Clave es requerida", - "Keyboard shortcuts": "Atajos de teclado", "Keyboard Shortcuts": "Atajos de Teclado", "Knowledge": "Conocimiento", "Knowledge Access": "Permiso a Conocimiento", "Knowledge Base": "Base de Conocimiento", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "La base de conocimiento ha sido reinicializada", "Knowledge created successfully.": "Conocimiento creado correctamente.", "Knowledge deleted successfully.": "Conocimiento eliminado correctamente.", "Knowledge Description": "Descripción del Conocimiento", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Nombre del Conocimiento", "Knowledge Public Sharing": "Compartir Conocimiento Públicamente", "Knowledge Sharing": "Compartir Conocimiento", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Conocimiento actualizado correctamente.", "Kokoro.js (Browser)": "Kokoro.js (Navegador)", "Kokoro.js Dtype": "Kokoro.js DType", @@ -1228,7 +1331,6 @@ "Last ran": "Última ejecución", "Last reply": "Última Respuesta", "LDAP": "LDAP", - "LDAP server updated": "Servidor LDAP actualizado", "Leaderboard": "Tabla Clasificatoria", "Learn more": "Saber más", "Learn More": "Saber Más", @@ -1250,11 +1352,12 @@ "Legacy": "Heredado", "lexical": "léxica", "License": "Licencia", + "Lifecycle JSON": "", "Lift List": "Desplegar Lista", "Light": "Claro", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limitar consultas de búsqueda simultáneas. 0 = ilimitado (predeterminado). Establécerlo en 1 para ejecución secuencial (recomendado para API con límites de velocidad estrictos, como la versión gratuita de Brave).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Limita el número de peticiones concurrentes al incrustrar. Ajusta a 0 para ilimitadas", - "Linkup API Key": "", + "Linkup API Key": "Clave API de Linkup", "List": "Lista", "List calendars, search, create, update, and delete calendar events": "Listar, buscar, crear, actualizar y borrar eventos en calendarios", "Listening...": "Escuchando...", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Acceso a la Ubicación no permitido", "Lost": "Perdido", "Low": "Bajo", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Creado por la Comunidad Open-WebUI", "Make password visible in the user interface": "Hacer visible la contraseña en la interfaz del usuario.", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gestionar Tuberías", "Manage Tool Servers": "Gestionar Servidores de Herramientas", "Manage your account information.": "Gestionar la información de tu cuenta", + "Mapped Source": "", "March": "Marzo", "Markdown": "Markdown", "Markdown Header Text Splitter": "Divisor de Texto Encabezado de Markdown", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memoria liberada correctamente", "Memory deleted successfully": "Memoria borrada correctamente", "Memory updated successfully": "Memoria actualizada correctamente", + "Merge Accounts by Email": "", "Merge Responses": "Fusionar Respuestas", "Merged Response": "Respuesta combinada", "Message": "Mensaje", @@ -1326,9 +1432,12 @@ "messages": "mensajes", "Messages": "Mensajes", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Los mensajes que envíe después de la creación del enlace no se compartirán. Los usuarios con la URL del enlace podrán ver el chat compartido.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personal)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (trabajo/estudio)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "La clave API de MinerU es necesaria para el modo Cloud API", @@ -1381,6 +1490,7 @@ "Models Sharing": "Compartir Modelos", "Mojeek": "Mojeek", "Mojeek Search API Key": "Clave API de Mojeek Search", + "Monday – Friday": "", "Month": "Mes", "Monthly": "Mensual", "More": "Más", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nombra tu base de conocimientos", "Name, prompt, and model are required": "Nombre, indicador y modelo son necesarios", "Native": "Nativo", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Nunca", "New": "Nuevo", "New Automation": "Nueva Automatización", @@ -1405,8 +1516,8 @@ "New calendar": "Nuevo calendario", "New Calendar": "Nuevo Calendario", "New Chat": "Nuevo Chat", - "New directory": "", - "New Directory": "", + "New directory": "Nuevo directorio", + "New Directory": "Nuevo Directorio", "New Event": "Nuevo Evento", "New File": "Nuevo Archivo", "New Folder": "Nueva Carpeta", @@ -1427,6 +1538,7 @@ "Next run": "Siguiente ejecución", "No access grants. Private to you.": "Sin acceso concedido. Privado para tí.", "No activity data": "Sin datos de actividad", + "No additional headers are sent unless configured.": "", "No authentication": "Sin Autentificación", "No automations found": "No se encontró ninguna automatización", "No chats found": "No se encontró ningún chat", @@ -1439,8 +1551,10 @@ "No data": "Sin datos", "No data found": "No se encontró ningún dato", "No distance available": "No hay distancia disponible", + "No event webhooks configured.": "", "No execution logs available yet": "Todavía no hay registros de ejecución", "No expiration can pose security risks.": "No expiración puede poner la seguridad en riesgo.", + "No external knowledge sources configured.": "", "No feedback found": "No se encontró ninguna opinión", "No file selected": "No se seleccionó archivo", "No files found": "No se encontraron archivos", @@ -1452,13 +1566,13 @@ "No HTML, CSS, or JavaScript content found.": "No se encontró contenido HTML, CSS, o JavaScript.", "No inference engine with management support found": "No se encontró un motor de inferencia que soporte gestión", "No kernel": "Sin núcleo Jupyter", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "Ninguna base de conocimiento accesible", "No knowledge bases found.": "No se encontraron bases de conocimiento", "No knowledge found": "No se encontró ningún conocimiento", "No limit": "Sin límite", "No memories to clear": "No hay memorias para borrar", "No model IDs": "No hay IDs de modelo", - "No models accessible": "", + "No models accessible": "Ningún modelo accesible", "No models available": "No hay modelos disponibles", "No models found": "No se encontraron modelos", "No models selected": "No se seleccionaron modelos", @@ -1468,6 +1582,7 @@ "No output items": "No hay elementos de salida", "No pinned messages": "No hay mensajes fijados", "No prompts found": "No se encontraron indicadores", + "No Repeat": "", "No results": "No se encontraron resultados", "No results found": "No se encontraron resultados", "No search query generated": "No se generó ninguna consulta de búsqueda", @@ -1479,7 +1594,7 @@ "No Terminal connection configured.": "Ninguna conexión configurada a Terminal", "No terminal connections configured.": "No hay conexiones a terminal configuradas.", "No tool server connections configured.": "No hay conexiones a servidores de herramientas configuradas", - "No tools accessible": "", + "No tools accessible": "Ninguna herramienta accesible", "No tools found": "No se encontraron herramientas", "No users were found.": "No se encontraron usuarios.", "No valves": "No hay válvulas", @@ -1487,6 +1602,7 @@ "No webhooks yet": "Todavía no hay webhooks", "Node Ids": "IDs de Nodo", "None": "Ninguno", + "Not configured": "", "Not factually correct": "No es correcto en todos los aspectos", "Not helpful": "No aprovechable", "Not Registered": "No Registrado", @@ -1502,24 +1618,29 @@ "Notifications": "Notificaciones", "November": "Noviembre", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Estático)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL del servidor de OAuth", "OAuth session disconnected": "Sesión OAuth desconectada", "October": "Octubre", "Off": "Desactivado", "Okay, Let's Go!": "Vale, ¡Vamos!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Oscuro OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Ajustes de la API de Ollama actualizados", "Ollama Cloud API Key": "Clave API de Ollama Cloud", "Ollama Version": "Versión de Ollama", + "Omit": "", "On": "Activado", "Once": "Una vez", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Activo únicamente durante el Modo Voz", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Solo activo cuando \"Pegar el Texto Largo como Archivo\" está activado", "Only active when the chat input is in focus and an LLM is generating a response.": "Solo activo con el foco en la entrada del chat y se está generando una respuesta", "Only active when the chat input is in focus.": "Solo activo con el foco en la entrada del chat", @@ -1586,26 +1707,30 @@ "Password": "Contraseña", "Passwords do not match.": "Las contraseñas no coinciden", "Paste Large Text as File": "Pegar el Texto Largo como Archivo", + "Path": "", "Path copied": "Ruta copiada", "Paused": "Pausado", "PDF document (.pdf)": "Documento PDF (.pdf)", "PDF Extract Images (OCR)": "Extraer imágenes del PDF (OCR)", "PDF Loader Mode": "Modo de Carga del PDF", - "pdf, docx, pptx, xlsx": "", + "pdf, docx, pptx, xlsx": "pdf, docx, pptx, xlsx", "pending": "pendiente", "Pending": "Pendiente", + "Pending Accounts": "", "Pending User Overlay Content": "Contenido de la SobreCapa Usuario Pendiente", "Pending User Overlay Title": "Título de la SobreCapa Usuario Pendiente", "Permission denied when accessing media devices": "Permiso denegado accediendo a los dispositivos", "Permission denied when accessing microphone": "Permiso denegado accediendo al micrófono", "Permission denied when accessing microphone: {{error}}": "Permiso denegado accediendo al micrófono: {{error}}", "Permissions": "Permisos", + "Permissions reset to defaults": "", "Perplexity API Key": "Clave API de Perplexity", "Perplexity Model": "Perplexity Modelo", "Perplexity Search API URL": "URL de la API de la Búsqueda de Perplexity", "Perplexity Search Context Usage": "Perplexity Usar Busqueda en Contexto", "Persistent": "Persistente", "Personalization": "Personalización", + "Picture Claim": "", "Pin": "Fijar", "Pin to Sidebar": "Fijar al Panel Lateral", "Pinned": "Fijado", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Por favor rellenar todos los campos.", "Please register the OAuth client": "Por favor, registra el cliente OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Por favor, guarde la conexión para conservar la información del cliente OAuth y no cambie el ID", - "Please select a model first.": "Por favor primero selecciona un modelo.", "Please select a model.": "Por favor selecciona un modelo.", "Please select a reason": "Por favor selecciona un motivo", "Please select a valid JSON file": "Por favor selecciona un archivo JSON válido", "Please select at least one user for Direct Message channel.": "Por favor selecciona al menos un usuario para el canal de Mensajes Directos", "Please wait until all files are uploaded.": "Por favor, espera a que todos los archivos se acaben de subir", "Policy ID": "ID de la Norma", + "Policy ID is required": "", "Port": "Puerto", "Ports": "Puertos", "Positive attitude": "Actitud Positiva", @@ -1653,7 +1778,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "El prefijo ID se utiliza para evitar conflictos con otras conexiones al añadir un prefijo a los IDs de modelo, dejar vacío para deshabilitarlo", "Prevent File Creation": "Prevenir la Creación de Archivos", "Preview": "Previsualización", - "Preview Access": "", + "Preview Access": "Acceso a Previsualización", "Previous 30 days": "30 días previos", "Previous 7 days": "7 días previos", "Previous message": "Mensaje anterior", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Compartir Indicadores Públicamente", "Prompts Sharing": "Compartir Indicadores", "Provider": "Proveedor", + "Provider Name": "", + "Provider URL": "", "Public": "Público", "Pull \"{{searchValue}}\" from Ollama.com": "Extraer \"{{searchValue}}\" desde Ollama.com", "Pull a model from Ollama.com": "Extraer un modelo desde Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Leer", "Read Aloud": "Leer en voz alta", "Read more →": "Leer más →", + "Read only": "", "Read Only": "Solo Lectura", "Read-Only Access": "Acceso Solo-Lectura", "Reason": "Razonamiento", "Reasoning Effort": "Esfuerzo del Razonamiento", "Reasoning Tags": "Etiquetas de Razonamiento", "Reasoning text...": "Texto de Razonamiento...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Usado Recientemente", "Reconnected": "Reconectado", "Record": "Grabar", "Record voice": "Grabar voz", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redireccionando a la Comunidad Open-WebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Reduce la probabilidad de generación sin sentido. Un valor más alto (p.ej. 100) dará respuestas más diversas, mientras que un valor más bajo (p.ej. 10) será más conservador.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referir a ti mismo como \"Usuario\" (p.ej. \"Usuario está aprendiendo Español\")", "Reference Chats": "Referenciar Chats", "Refresh": "Refrescar", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Rechazado cuando no debería haberlo hecho", "Regenerate": "Regenerar", "Regenerate Menu": "Regenerar Menú", @@ -1731,28 +1867,35 @@ "Remove from favorites": "Eliminar de favoritos", "Remove image": "Eliminar imagen", "Remove Model": "Eliminar Modelo", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._many": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "Eliminando {{count}} archivos huérfanos..._únicos", + "Removing {{count}} stale files..._many": "Eliminando {{count}} archivos huérfanos..._multiple", + "Removing {{count}} stale files..._other": "Eliminando {{count}} archivos huérfanos..._otros", "Rename": "Renombrar", "Renamed to {{name}}": "Renombrado como {{name}}", "Render Markdown in Assistant Messages": "Renderizar Marldown en los Mensajes del Asistente", "Render Markdown in Previews": "Renderizar Markdown en Vista Previa", "Render Markdown in User Messages": "Renderizar Markdown en los Mensajes del Usuario", "Reorder Models": "Reordenar Modelos", + "Repeat": "", "Repeats": "Repeticiones", "Reply": "Responder", "Reply in Thread": "Responder en Hilo", "Reply to thread...": "Responder al hilo...", "Replying to {{NAME}}": "Responder a {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "requerido", "Reranking Batch Size": "Tamaño del lote de Reclasificación", "Reranking Engine": "Motor de Reclasificación", "Reranking Model": "Modelo de Reclasificación", + "Research Knowledge": "", "Reset": "Reiniciar", "Reset All Models": "Reiniciar Todos los Modelos", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Restablecer imagen", - "Reset knowledge base?": "", + "Reset knowledge base?": "¿Reinicializar la base de conocimiento?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Reiniciar Directorio de Subidas", "Reset Vector Storage/Knowledge": "Reiniciar Almacenamiento de Vectores/Conocimiento", "Reset view": "Reiniciar Vista", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "Recuperada una fuente", "Rich Text Input for Chat": "Entrada de Texto Enriquecido para el Chat", "Role": "Rol", + "Roles Claim": "", "RTL": "RTL", "Run": "Ejecutar", "Run All": "Ejecutar Todo", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ya no está soportado guardar registros de chat directamente en el almacenamiento del navegador. Por favor, dedica un momento a descargar y eliminar tus registros de chat pulsando en el botón de abajo. No te preocupes, puedes re-importar fácilmente tus registros desde las opciones de configuración", "Schedule": "Programar", "Scheduled time must be in the future": "El tiempo de programado debe ser futuro", + "Scopes": "", "Scroll On Branch Change": "Desplazamiento al Cambiar Rama", "Scroll to Top": "Desplazar al principio", "Search": "Buscar", "Search a model": "Buscar un Modelo", + "Search actions": "", "Search all emojis": "Buscar todos los emojis", "Search and manage user memories": "Buscar y gestionar memorias del usuario", "Search and view user chat history": "Buscr y ver historial de los chat del usuario", @@ -1804,6 +1950,7 @@ "Search Chats": "Buscar Chats", "Search Collection": "Buscar Colección", "Search Files": "Buscar archivos", + "Search filters": "", "Search Filters": "Buscar Filtros", "search for archived chats": "buscar chats archivados", "search for folders": "buscar carpetas", @@ -1818,13 +1965,16 @@ "Search Models": "Buscar Modelos", "Search Notes": "Buscar Notas", "Search options": "Opciones de Búsqueda", + "Search or add pattern": "", "Search Prompts": "Buscar Indicadores", "Search Result Count": "Número de resultados de la búsqueda", + "Search skills": "", "Search Skills": "Buscar Habilidades", - "Search skills...": "", "Search the internet": "Buscar en internet", "Search the web and fetch URLs": "Buscar en la web y obtener URLs", + "Search tools": "", "Search Tools": "Buscar Herramientas", + "Search users or groups": "", "Search, view, and manage user notes": "Buscar, ver y gestionar notas del usuario", "SearchApi API Key": "Clave API de SearchApi", "SearchApi Engine": "Motor SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Semilla", "Select": "Seleccionar", "Select {{modelName}} model": "Seleccionar modelo {{modelName}}", - "Select a base model": "Seleccionar un modelo base", "Select a base model (e.g. llama3, gpt-4o)": "Seleccionar un modelo base (ej. llama3, gpt-4o)", "Select a conversation to preview": "Seleccionar una conversación para previsualizar", "Select a engine": "Seleccionar un motor", @@ -1878,18 +2027,25 @@ "semantic": "semántica", "Send": "Enviar", "Send a Message": "Enviar un Mensaje", + "Send events for": "", "Send message": "Enviar Mensaje", "Send now": "Enviar ahora", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envia en la solicitud de transmisión la opción: `{ include_usage: true }`.\nSi se activa, los proveedores que soporten esta función devolverán en la respuesta información de uso de los token.", "September": "Septiembre", "SerpApi API Key": "Clave API de SerpApi", "SerpApi Engine": "Motor de SerpApi", "Serper API Key": "Clave API de Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Clave API de Serply", "Serpstack API Key": "Clave API de Serpstack", "Server connection failed": "Fallo la conexión al servidor", "Server connection verified": "Conexión al servidor verificada", + "Service Account": "", "Session": "Sesión", + "Session expired. Please sign in again.": "", "Set as default": "Establecer como Predeterminado", "Set as Production": "Establecer como Producción", "Set embedding model": "Establecer Modelo de Incrustación", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "Enlace Compartido copiado al portapapeles", "Share to Open WebUI Community": "Compartir con la Comunidad Open-WebUI", "Share your background and interests": "Compartir tus antecedentes e intereses", + "Shared": "", "Shared Chats": "Chats Compartidos", "Shared with you": "Compartido contigo", "Sharing Permissions": "Permisos al Compartir", "Show": "Mostrar", - "Show \"What's New\" modal on login": "Mostrar modal \"Qué hay de Nuevo\" al iniciar sesión", + "Show \"What's New\" Modal on Login": "Mostrar modal \"Qué hay de Nuevo\" al iniciar sesión", "Show Admin Details in Account Pending Overlay": "Mostrar Detalles Admin en la sobrecapa de 'Cuenta Pendiente'", "Show All": "Mostrar Todo", "Show all ({{COUNT}} characters)": "Mostrar todo ({{COUNT}} caracteres)", "Show Files": "Mostrar Archivos", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Mostrar barra de herramientas de Formateo", "Show image preview": "Mostrar previsualización de imagen", "Show Model": "Mostrar Modelo", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "API sID de Sougou Search", "Sougou Search API SK": "SK API de Sougou Search", "Source": "Fuente", + "Specific users or groups": "", "Speech Playback Speed": "Velocidad de Reproducción de Voz", "Speech recognition error: {{error}}": "Error en reconocimiento de voz: {{error}}", "Speech-to-Text": "Voz a Texto", @@ -2006,6 +2165,7 @@ "STT Settings": "Ajustes Voz a Texto (STT)", "Stylized PDF Export": "Exportar PDF Estilizado", "Su_day_of_week": "los_domingos", + "Sub Claim": "", "Submit question": "Enviar pregunta", "Submit suggestion": "Enviar sugerencia", "Subtitle": "Subtítulo", @@ -2020,8 +2180,8 @@ "Switch to JSON editor": "Cambiar a editor JSON", "Switch to visual editor": "Cambiar a editor visual", "Sync": "Sincronizar", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Sincroniza un directorio local con esta base de conocimientos. Solo se subirán los archivos nuevos y modificados. La estructura de directorios se clonará.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Sincronización completa: {{added}} añadidos, {{modified}} modificados, {{deleted}} eliminados, {{unmodified}} no modificados", "Sync Complete!": "Sincronización Completa", "Sync directory": "Sincroniza Directorio", "Sync Failed": "Fallo al Sincronizar", @@ -2030,8 +2190,10 @@ "Syncing...": "Sincronizando...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sincroniza solo los chats con actualizaciones posteriores a la última sincronización. Desactiva esta opción para volver a sincronizar todos los chats.", "System": "Sistema", + "System events only": "", "System Instructions": "Instrucciones del sistema", "System Prompt": "Indicador del sistema", + "Table": "", "Tag": "Etiqueta", "Tags": "Etiquetas", "Tags Generation": "Generación de Etiquetas", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Chat Temporal Predeterminado", "Terminal": "Terminal", "Terminal servers saved": "Servidores de Terminal guardados", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divisor de Texto", "Text-to-Speech": "Texto a Voz", "Text-to-Speech Engine": "Motor Texto a Voz(TTS)", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "El idioma de la entrada de audio. Proporcionando la entrada de idioma en formato ISO-639-1 (e.g. es) mejora la precisión y la latencia. Lejar en blanco para la autodetección del idioma.", "The LDAP attribute that maps to the mail that users use to sign in.": "El atributo LDAP que mapea el correo que los usuarios utilizan para iniciar sesión.", "The LDAP attribute that maps to the username that users use to sign in.": "El atributo LDAP que mapea el nombre de usuario que los usuarios utilizan para iniciar sesión.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "La tabla clasificatoria está actualmente en beta, por lo que los cálculos de clasificación pueden reajustarse a medida que se refina el algoritmo.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "El tamaño máximo del archivo en MB. Si el tamaño del archivo supera este límite, el archivo no se subirá.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "El número máximo de archivos que se pueden utilizar a la vez en el chat. Si se supera este límite, los archivos no se subirán.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "El formato de salida para el texto. Puede ser 'json', 'markdown' o 'html'. Valor predeterminado: 'markdown'", @@ -2089,6 +2256,7 @@ "This folder is empty": "Esta carpeta está vacía", "This is a default user permission and will remain enabled.": "Este es un permiso predeterminado y se mantentrá activo ", "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, por lo que puede no funcionar como se esperaba y está sujeta a cambios en cualquier momento.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Este modelo no está disponible publicamente. Por favor, selecciona otro modelo.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Esta opción controla cuanto tiempo permanece cargado en memoria el modelo tras la petición (por defecto 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Esta opción controla cuántos tokens se conservan cuando se actualiza el contexto. Por ejemplo, si se establece en 2, se conservarán los primeros 2 tokens del contexto de la conversación. Conservar el contexto puede ayudar a mantener la continuidad de una conversación, pero puede reducir la habilidad para responder a nuevos temas.", @@ -2101,7 +2269,7 @@ "This will delete all models including custom models": "Esto eliminará todos los modelos, incluidos los modelos personalizados", "This will delete all models including custom models and cannot be undone.": "Esto eliminará todos los modelos, incluidos los modelos personalizados y no se puede deshacer.", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Esta acción borará permanentemente el calendario \"{{name}}\" y todos sus eventos. Esta acción no se puede deshacer.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Esto eliminará todos los archivos y directorios de la base de conocimientos. Esta acción no se puede deshacer.", "Thorough explanation": "Explicación exhaustiva", "Thought": "Pensando", "Thought for {{DURATION}}": "Pensando durante {{DURATION}}", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Para aprender más sobre los endpoints disponibles, visite nuestra documentación.", "To select skills here, add them to the \"Skills\" workspace first.": "Para seleccionar habilidades aquí, primero añadelas a \"Habilidades\" en el áreas de trabajo.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Para seleccionar herramientas aquí, primero añadelas a \"Herramientas\" en el área de trabajo.", - "Toast notifications for new updates": "Notificaciones emergentes para nuevas actualizaciones", + "Toast Notifications for New Updates": "Notificaciones emergentes para nuevas actualizaciones", "Today": "Hoy", "Today at": "Hoy a las", "Today at {{LOCALIZED_TIME}}": "Hoy a las {{LOCALIZED_TIME}}", @@ -2137,12 +2305,14 @@ "Toggle 1 source": "Des/Plegar 1 fuente", "Toggle details": "Des/Plegar detalles", "Toggle Dictation": "Des/Plegar Dictado", - "Toggle Mute": "", + "Toggle Mute": "Conmutar Enmudecer", "Toggle Sidebar": "Des/Plegar la Barra Lateral", "Toggle status history": "Des/Plegar historial de estado", "Toggle whether current connection is active.": "Alternar si la conexión actual está activa", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "El recuento de tokens es estimado y puede diferir del uso real de la API", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Demasiado detallado", @@ -2191,14 +2361,19 @@ "Unpin": "Desfijar", "Unpin from Sidebar": "Desfijar de la Barra LAteral", "Unravel secrets": "Desentrañar secretos", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Descompartir Chat", "Unsupported file type.": "Tipo de archivo no soportado", "Untagged": "Sin Etiqueta", "Untitled": "Sin Título", "Update": "Actualizar", "Update and Copy Link": "Actualizar y Copiar Enlace", + "Update Email": "", "Update for the latest features and improvements.": "Actualizar para las últimas características y mejoras.", + "Update Name": "", "Update password": "Actualizar contraseña", + "Update Picture": "", "Update your status": "Actualizar tu estado", "Updated": "Actualizado", "Updated at": "Actualizado el", @@ -2215,8 +2390,8 @@ "Upload profile image": "Subir imagen del perfil", "Upload Progress": "Progreso de la Subida", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progreso de la Subida: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", - "Uploaded files or images": "Archivos o imágenes cargados", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploaded files or images": "Archivos o imágenes subidos", + "Uploading {{current}}/{{total}}: {{file}}": "Subiendo {{current}}/{{total}}: {{file}}", "Uploading...": "Subiendo...", "URL": "URL", "URL is required": "La URL es requerida", @@ -2225,22 +2400,28 @@ "Use": "Usar", "Use '#' in the prompt input to load and include your knowledge.": "Utilizar '#' en el indicador para cargar e incluir tu conocimiento.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Usar el endpoint /v1/chat/completions en vez de /v1/audio/transcriptions para una (posible) mayor precisión.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Usar Chat Completions", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Usar grupos para organizar tus usuarios y asignar permisos", "Use LLM": "Usar LLM", "Use no proxy to fetch page contents.": "No usar proxy para extraer contenidos", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Usar el proxy asignado en las variables del entorno http_proxy y/o https_proxy para extraer contenido", + "Use Web Search?": "", "user": "usuario", "User": "Usuario", + "User Access": "", "User Activity": "Actividad del Usuario", "User Groups": "Grupos de Usuarios", "User location successfully retrieved.": "Ubicación de usuario obtenida correctamente.", "User menu": "Menu de Usuario", - "User Preview": "", + "User Preview": "Previsualizar Usuario", "User ratings (thumbs up/down)": "Calificaciones de los usuarios (pulgares arriba/abajo)", "User Status": "Estado del Usuario", "User Webhooks": "Usuario Webhooks", "Username": "Nombre de Usuario", + "Username Claim": "", "users": "usuarios", "Users": "Usuarios", "Uses DefaultAzureCredential to authenticate": "Usa DefaultAzureCredential para autentificar", @@ -2254,6 +2435,7 @@ "Valves updated": "Válvulas actualizadas", "Valves updated successfully": "Válvulas actualizados correctamente", "variable": "variable", + "Vector Field": "", "Verify Connection": "Verificar Conexión", "Verify SSL Certificate": "Verificar Certificado SSL", "Version": "Versión", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "Motor Cargador Web", "Web Search": "Búsqueda Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motor Búsqueda Web", "Web Search in Chat": "Búsqueda Web en Chat", "Web Search Query Generation": "Generación de Consulta Búsqueda Web", + "Webhook deleted": "", "Webhook Name": "Nombre del Webhook", - "Webhook URL": "URL EnganchesWeb(Webhook)", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URLS de PáginasWeb", "WebUI Settings": "WebUI Ajustes", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "Clave API de la Búsqueda Web de Yandex", "Yandex Web Search config": "Confoguración de la Búsqueda Web de Yantex", "Yandex Web Search URL": "URL de la Búsqueda Web de Yandex", + "Yearly": "", "Yesterday": "Ayer", "Yesterday at {{LOCALIZED_TIME}}": "Ayer a las {{LOCALIZED_TIME}}", "You": "Tu", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "Tu navegador no soporta la etiqueta del video.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tu entera contribución irá directamente al desarrollador del complemento; Open-WebUI no recibe ningún porcentaje. Sin embargo, la plataforma de financiación elegida podría tener sus propias tarifas.", "Your message text or inputs": "Tu mensaje de texto o entrada", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Tu estadistica de uso ha sido sincronizada", "YouTube": "Youtube", "Youtube Language": "Youtube Idioma", diff --git a/src/lib/i18n/locales/et-EE/translation.json b/src/lib/i18n/locales/et-EE/translation.json index 00d37bb5f1..2787fee63e 100644 --- a/src/lib/i18n/locales/et-EE/translation.json +++ b/src/lib/i18n/locales/et-EE/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} faili", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} peidetud rida", "{{COUNT}} members": "{{COUNT}} liiget", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} allikat", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} sõna", "{{COUNT}}d_time_ago": "{{COUNT}}p tagasi", "{{COUNT}}h_time_ago": "{{COUNT}}t tagasi", "{{COUNT}}m_time_ago": "{{COUNT}}m tagasi", "{{COUNT}}w_time_ago": "{{COUNT}}n tagasi", "{{COUNT}}y_time_ago": "{{COUNT}}a tagasi", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} kell {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} allalaadimine on tühistatud", "{{modelName}} profile image": "{{modelName}} profiilipilt", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} vestlused", "{{webUIName}} Backend Required": "{{webUIName}} taustaserver on vajalik", "*Prompt node ID(s) are required for image generation": "*Sisendi sõlme ID(d) on piltide genereerimiseks vajalikud", + "1 group": "", "1 hour before": "", "1 Source": "1 allikas", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "1m tagasi", @@ -57,6 +67,7 @@ "Access Control": "Juurdepääsu kontroll", "Access Grants": "Juurdepääsu andmine", "Access List": "Juurdepääsu nimekiri", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Kättesaadav kõigile kasutajatele", "Account": "Konto", @@ -72,6 +83,7 @@ "Activity": "Tegevus", "Add": "Lisa", "Add a model ID": "Lisa mudeli ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Lisa lühike kirjeldus, mida see mudel teeb", "Add a tag": "Lisa silt", "Add a tag...": "Lisa silt...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Lisa kohandatud sisend", "Add description": "", "Add Details": "Lisa üksikasjad", + "Add durable context for future chats": "", "Add Files": "Lisa faile", "Add Image": "Lisa pilt", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "Lisa liige", "Add Members": "Lisa liikmeid", @@ -100,6 +114,7 @@ "Add to favorites": "Lisa lemmikutesse", "Add User": "Lisa kasutaja", "Add User Group": "Lisa kasutajagrupp", + "Add webhook": "", "Add webpage": "Lisa veebileht", "Add your Open Terminal URL and API key in Settings → Integrations.": "Lisage oma Open Terminali URL ja API võti menüüs Seaded → Integratsioonid.", "Additional Config": "Täiendav seadistus", @@ -112,7 +127,9 @@ "Admin": "Administraator", "Admin Contact Email": "Administraatori kontakt-e-post", "Admin Panel": "Administraatori paneel", + "Admin Roles": "", "Admin Settings": "Administraatori seaded", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administraatoritel on alati juurdepääs kõigile tööriistadele; kasutajatele tuleb tööriistad määrata mudeli põhiselt tööruumis.", "Advanced": "Täpsemad", "Advanced Parameters": "Täpsemad parameetrid", @@ -123,16 +140,21 @@ "All": "Kõik", "All chats have been unarchived.": "Kõik vestlused on arhiivist eemaldatud.", "All day": "", + "All events": "", "All models are now hidden": "Kõik mudelid on nüüd peidetud", "All models are now visible": "Kõik mudelid on nüüd nähtavad", "All models deleted successfully": "Kõik mudelid edukalt kustutatud", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Kogu aeg", "All Users": "Kõik kasutajad", + "All users and system events": "", "Allow Call": "Luba kõne", "Allow Chat Controls": "Luba vestluse kontrollnupud", "Allow Chat Delete": "Luba vestluse kustutamine", "Allow Chat Edit": "Luba vestluse muutmine", "Allow Chat Export": "Luba vestluse eksport", + "Allow Chat Import": "", "Allow Chat Params": "Luba vestluse parameetrid", "Allow Chat Share": "Luba vestluse jagamine", "Allow Chat System Prompt": "Luba vestluse süsteemi sisend", @@ -152,9 +174,11 @@ "Allow User Location": "Luba kasutaja asukoht", "Allow Voice Interruption in Call": "Luba hääle katkestamine kõnes", "Allow Web Upload": "Luba veebi üleslaadimine", + "Allowed Domains": "", "Allowed Endpoints": "Lubatud lõpp-punktid", "Allowed File Extensions": "Lubatud faililaiendid", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Üleslaadimiseks lubatud faililaiendid. Eralda mitu laiendit komadega. Kõigi failitüüpide jaoks jäta tühjaks.", + "Allowed Roles": "", "Already have an account?": "Kas teil on juba konto?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatiiv top_p-le ja eesmärk on tagada kvaliteedi ja mitmekesisuse tasakaal. Parameeter p esindab minimaalset tõenäosust tokeni arvesse võtmiseks, võrreldes kõige tõenäolisema tokeni tõenäosusega. Näiteks p=0.05 korral, kui kõige tõenäolisema tokeni tõenäosus on 0.9, filtreeritakse välja logitid väärtusega alla 0.045.", "Always": "Alati", @@ -173,6 +197,7 @@ "API Base URL": "API baas-URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker teenuse API baas-URL. Vaikimisi: https://www.datalab.to/api/v1/marker", "API Key": "API võti", + "API Key / Token": "", "API Key created.": "API võti loodud.", "API Key Endpoint Restrictions": "API võtme lõpp-punkti piirangud", "API keys": "API võtmed", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Kas olete kindel, et soovite selle sõnumi kustutada?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Kas olete kindel, et soovite selle versiooni kustutada? Alamversioonid seotakse uuesti selle versiooni vanemaga.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Kas olete kindel, et soovite selle kustutada?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Kas olete kindel, et soovite kõik arhiveeritud vestlused arhiivist eemaldada?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Areena mudelid", "Artifacts": "Tekkinud objektid", "Asc": "Kasvav", "Ask": "Küsi", "Ask a question": "Esita küsimus", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "Asünkroonne manustamise töötlemine", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Heli", "August": "August", "Auth": "Autentimine", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autendi", "Authentication": "Autentimine", "Auto": "Auto", "Auto (Random)": "Auto (juhuslik)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Kopeeri vastus automaatselt lõikelauale", - "Auto-playback response": "Esita vastus automaatselt", + "Auto-Create Groups": "", + "Auto-Playback Response": "Esita vastus automaatselt", "Autocomplete Generation": "Automaattäitmise genereerimine", "Autocomplete Generation Input Max Length": "Automaattäitmise genereerimise sisendi maksimaalne pikkus", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API autentimise string", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 baas-URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Saadaolevad tööriistad", "available users": "saadaolevad kasutajad", + "Available variables": "", "available!": "saadaval!", "Away": "Eemal", "Awful": "Kohutav", @@ -258,16 +295,17 @@ "Bad Response": "Halb vastus", "Banners": "Bännerid", "Base Model (From)": "Baas mudel (Allikas)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Baasmudelite nimekirja vahemälu kiirendab juurdepääsu, tuues baasmudelid ainult käivitamisel või seadete salvestamisel—kiirem, kuid ei pruugi näidata hiljutisi muudatusi.", "Bearer": "Bearer", "before": "enne", "Being lazy": "Laisklemine", - "Beta": "Beeta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 lõpp-punkt", "Bing Search V7 Subscription Key": "Bing Search V7 tellimuse võti", "Bio": "Bio", "Birth Date": "Sünnikuupäev", + "Blocked Groups": "", "BM25 Weight": "BM25 kaal", "Bocha Search API Key": "Bocha otsingu API võti", "Bold": "Paks", @@ -324,7 +362,7 @@ "Chat Completions": "Vestluse lõpetamised", "Chat Conversation": "Vestlusseanss", "Chat deleted.": "", - "Chat direction": "Vestluse suund", + "Chat Direction": "Vestluse suund", "Chat exported successfully": "Vestlus edukalt eksporditud", "Chat History": "Vestluse ajalugu", "Chat ID": "Vestlus ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Koostöökanal, kuhu inimesed liituvad liikmetena", "Collapse": "Ahenda", "Collection": "Kogu", + "Collection Field": "", "Collections": "Kogud", "Color": "Värv", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI töövoog", "ComfyUI Workflow Nodes": "ComfyUI töövoo sõlmed", "Comma separated Node Ids (e.g. 1 or 1,2)": "Komadega eraldatud sõlme ID-d (nt 1 või 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "käsk", "Command": "Käsk", "Comment": "Kommentaar", "Commit Message": "Commiti teade", "Community Reviews": "Kogukonna ülevaated", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Lõpetamised", "Compress Images in Channels": "Tihenda pildid kanalites", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Ühenduge Open Terminali instantsidega. Kõigil kasutajatel on juurdepääs failide sirvimisele ja terminali tööriistadele nende serverite kaudu.", "Connect to your own OpenAI compatible API endpoints.": "Ühendu oma OpenAI-ga ühilduvate API lõpp-punktidega.", "Connect to your own OpenAPI compatible external tool servers.": "Ühendu oma OpenAPI-ga ühilduvate väliste tööriistaserveritega.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Ühendus ebaõnnestus", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Võtke WebUI juurdepääsu saamiseks ühendust administraatoriga", "Content": "Sisu", "Content Extraction Engine": "Sisu ekstraheerimise mootor", + "Content Field": "", "Content lengths (character counts only)": "Sisu pikkused (ainult tähemärkide arv)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Jätka vastust", "Continue with {{provider}}": "Jätka {{provider}}-ga", "Continue with Email": "Jätka e-postiga", @@ -493,6 +543,7 @@ "Create new secret key": "Loo uus salavõti", "Create note": "Loo märge", "Create Note": "Loo märge", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Loo oma esimene märge, klõpsates all olevat plussnuppu.", "Created at": "Loomise aeg", @@ -510,6 +561,7 @@ "Custom Gender": "Kohandatud sugu", "Custom Parameter Name": "Kohandatud parameetri nimi", "Custom Parameter Value": "Kohandatud parameetri väärtus", + "Custom range": "", "Daily": "", "Daily Messages": "Päevased sõnumid", "Danger Zone": "Ohutsoon", @@ -532,7 +584,6 @@ "Default Features": "Vaikefunktsioonid", "Default Filters": "Vaikimisi filtrid", "Default Group": "Vaikimisi grupp", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Vaikimisi režiim töötab laiema mudelite valikuga, kutsudes tööriistu kord enne täitmist. Omane režiim kasutab mudeli sisseehitatud tööriistade kutsumise võimalusi, kuid nõuab, et mudel toetaks seda funktsiooni olemuslikult.", "Default Model": "Vaikimisi mudel", "Default model updated": "Vaikimisi mudel uuendatud", "Default permissions": "Vaikimisi õigused", @@ -542,6 +593,7 @@ "Default to ALL": "Vaikimisi KÕIK", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Vaikimisi kasutada segmenteeritud päringut keskendunud ja asjakohase sisu eraldamiseks; soovitatav enamikel juhtudel.", "Default User Role": "Vaikimisi kasutaja roll", + "Default webhook": "", "Defaults": "Vaikeväärtused", "Delete": "Kustuta", "Delete {{name}}": "Kustuta {{name}}", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Keela koodi interpretaator", "Disable Image Extraction": "Keela piltide väljavõte", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Keela piltide eraldamine PDF-ist. Kui 'Kasuta LLM-i' on lubatud, lisatakse piltidele automaatselt pealdised. Vaikimisi välja lülitatud.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Keelatud", "Disconnect OAuth": "", "Discover a function": "Avasta funktsioon", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Avasta, laadi alla ja uuri mudeli eelseadistusi", "Discussion channel where access is based on groups and permissions": "Arutelukanal, kus juurdepääs põhineb gruppidel ja õigustel", "Display": "Kuva", - "Display chat title in tab": "Kuva vestluse pealkiri vahekaardil", + "Display Chat Title in Tab": "Kuva vestluse pealkiri vahekaardil", "Display Emoji in Call": "Kuva kõnes emoji", "Display Multi-model Responses in Tabs": "Kuva mitme mudeli vastused vahekaartidel", - "Display the username instead of You in the Chat": "Kuva vestluses 'Sina' asemel kasutajanimi", + "Display the Username Instead of You in the Chat": "Kuva vestluses 'Sina' asemel kasutajanimi", "Displays citations in the response": "Kuvab vastuses viited", "Displays status updates (e.g., web search progress) in the response": "Kuvab vastuses olekuuendusi (nt veebiotsingu edenemine)", "Dive into knowledge": "Sukeldu teadmistesse", @@ -630,6 +684,7 @@ "Docling Parameters": "Doclingu parameetrid", "Docling Server URL required.": "Docling serveri URL on nõutav.", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Dokumendi intelligentsus", "Document Intelligence endpoint required.": "Document Intelligence lõpp-punkt on nõutav.", "Document Intelligence Model": "Dokumendi intelligentsuse mudel", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Muuda vaikimisi õigusi", "Edit Folder": "Muuda kausta", "Edit Image": "Muuda pilti", + "Edit Knowledge Connection": "", "Edit Last Message": "Muuda viimast sõnumit", "Edit Memory": "Muuda mälu", "Edit Prompt": "Muuda sisendit", "Edit Terminal Connection": "Muuda terminaliühendust", "Edit User": "Muuda kasutajat", "Edit User Group": "Muuda kasutajagruppi", + "Edit webhook": "", "Edit workflow.json content": "Muuda workflow.json sisu", "edited": "muudetud", "Edited": "Muudetud", @@ -699,6 +756,7 @@ "Eject model": "Väljuta mudel", "ElevenLabs": "ElevenLabs", "Email": "E-post", + "Email Claim": "", "Embark on adventures": "Alusta seiklusi", "Embedding": "Manustamine", "Embedding Batch Size": "Manustamise partii suurus", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Manustamise mudeli mootor", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "Tühi sõnum", "Enable All": "Luba kõik", "Enable API Keys": "Luba API võtmed", @@ -714,22 +773,27 @@ "Enable Code Execution": "Luba koodi täitmine", "Enable Code Interpreter": "Luba koodi interpretaator", "Enable Community Sharing": "Luba kogukonnaga jagamine", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Luba mälu lukustamine (mlock), et vältida mudeli andmete vahetamist RAM-ist välja. See valik lukustab mudeli töökomplekti lehed RAM-i, tagades, et neid ei vahetata kettale. See aitab säilitada jõudlust, vältides lehevigu ja tagades kiire andmete juurdepääsu.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Luba mälu kaardistamine (mmap) mudeli andmete laadimiseks. See valik võimaldab süsteemil kasutada kettamahtu RAM-i laiendusena, koheldes kettafaile nii, nagu need oleksid RAM-is. See võib parandada mudeli jõudlust, võimaldades kiiremat andmete juurdepääsu. See ei pruugi siiski kõigi süsteemidega õigesti töötada ja võib tarbida märkimisväärse koguse kettaruumi.", "Enable Message Queue": "Luba sõnumite järjekord", "Enable Message Rating": "Luba sõnumite hindamine", "Enable Mirostat sampling for controlling perplexity.": "Luba Mirostat'i valim perplekssuse juhtimiseks.", "Enable New Sign Ups": "Luba uued registreerimised", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Luba, keela või kohanda mudeli kasutatavaid arutlussilte. \"Lubatud\" kasutab vaikimisi silte, \"Keelatud\" lülitab arutlussildid välja ja \"Kohandatud\" võimaldab määrata oma algus- ja lõpusildid.", "Enabled": "Lubatud", "End Tag": "Lõpusilt", + "Endpoint": "", "Endpoint URL": "Lõpp-punkt URL", "Enforce Temporary Chat": "Sunni ajutine vestlus", "Enhance": "Täiusta", "Enrich Hybrid Search Text": "Rikasta hübriidotsingu teksti", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Veenduge, et teie CSV-fail sisaldab 4 veergu selles järjekorras: Nimi, E-post, Parool, Roll.", "Enter {{role}} message here": "Sisestage {{role}} sõnum siia", - "Enter a detail about yourself for your LLMs to recall": "Sisestage detail enda kohta, mida teie LLM-id saavad meenutada", "Enter a title for the pending user info overlay. Leave empty for default.": "Sisestage pealkiri ootava kasutaja info kattekihi jaoks. Jätke tühjaks vaikimisi jaoks.", "Enter a watermark for the response. Leave empty for none.": "Sisestage vastusele vesimärk. Jätke tühjaks, kui vesimärki pole vaja.", "Enter additional headers in JSON format": "Sisestage lisapäised JSON-vormingus", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Sisestage tüki minimaalne sihtsuurus", "Enter Chunk Overlap": "Sisestage tükkide ülekate", "Enter Chunk Size": "Sisestage tüki suurus", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Sisestage komadega eraldatud \"token:kallutuse_väärtus\" paarid (näide: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Sisestage sisu ootava kasutaja info kattekihi jaoks. Jätke tühjaks vaikimisi jaoks.", "Enter coordinates (e.g. 51.505, -0.09)": "Sisestage koordinaadid (nt 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Sisestage Jupyter URL", "Enter Kagi Search API Key": "Sisestage Kagi Search API võti", "Enter Key Behavior": "Sisestage võtme käitumine", + "Enter language": "", "Enter language codes": "Sisestage keelekoodid", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Sisestage MinerU API võti", "Enter Mistral API Base URL": "Sisestage Mistral API baas-URL", "Enter Mistral API Key": "Sisestage Mistral API võti", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Sisestage puhverserveri URL (nt https://kasutaja:parool@host:port)", "Enter reasoning effort": "Sisestage arutluspingutus", + "Enter Redirect URI": "", "Enter Score": "Sisestage skoor", "Enter SearchApi API Key": "Sisestage SearchApi API võti", "Enter SearchApi Engine": "Sisestage SearchApi mootor", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Sisestage SerpApi API võti", "Enter SerpApi Engine": "Sisestage SerpApi mootor", "Enter Serper API Key": "Sisestage Serper API võti", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Sisestage Serply API võti", "Enter Serpstack API Key": "Sisestage Serpstack API võti", "Enter server host": "Sisestage serveri host", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Sisestage Tika serveri URL", "Enter timeout in seconds": "Sisestage aegumine sekundites", "Enter to Send": "Enter saatmiseks", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Sisestage Top K", "Enter Top K Reranker": "Sisestage Top K ümberjärjestaja", "Enter URL (e.g. http://127.0.0.1:7860/)": "Sisestage URL (nt http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Viga: mudel ID-ga '{{modelId}}' on juba olemas. Palun valige jätkamiseks erinev ID.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Viga: mudeli ID ei saa olla tühi. Palun sisestage jätkamiseks kehtiv ID.", "Evaluations": "Hindamised", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API võti", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Näide: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Näide: ALL", "Example: mail": "Näide: mail", @@ -905,12 +982,18 @@ "Export Config": "Ekspordi seadistus", "Export Models": "Ekspordi mudelid", "Export Prompts": "Ekspordi sisendid", + "Export Skills": "", "Export to CSV": "Ekspordi CSV-na", "Export Tools": "Ekspordi tööriistad", "Export Users": "Ekspordi kasutajad", "External": "Väline", + "External connection not found.": "", "External Document Loader URL required.": "Välise dokumendilaadija URL on nõutav.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Väline ülesannete mudel", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Välise veebilaadija API võti", "External Web Loader URL": "Välise veebilaadija URL", "External Web Search API Key": "Välise veebiotsingu API võti", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API võtme loomine ebaõnnestus.", "Failed to delete calendar": "", "Failed to delete note": "Märkme kustutamine ebaõnnestus", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "Pildi allalaadimine ebaõnnestus", "Failed to extract content from the file: {{error}}": "Failist sisu eraldamine ebaõnnestus: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Mudelite toomine ebaõnnestus", "Failed to generate title": "Pealkirja genereerimine ebaõnnestus", "Failed to import models": "Mudelite importimine ebaõnnestus", + "Failed to load chat": "", "Failed to load chat preview": "Vestluse eelvaate laadimine ebaõnnestus", "Failed to load DOCX file. Please try downloading it instead.": "DOCX-faili laadimine ebaõnnestus. Palun proovige selle asemel alla laadida.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-faili laadimine ebaõnnestus. Palun proovige selle asemel alla laadida.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Vestluse teisaldamine ebaõnnestus", "Failed to process URL: {{url}}": "URL-i töötlemine ebaõnnestus: {{url}}", "Failed to read clipboard contents": "Lõikelaua sisu lugemine ebaõnnestus", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Liikme eemaldamine ebaõnnestus", "Failed to render diagram": "Diagrammi renderdamine ebaõnnestus", "Failed to render visualization": "Visualiseerimise renderdamine ebaõnnestus", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Mudelite konfiguratsiooni salvestamine ebaõnnestus", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "Terminali serverite salvestamine ebaõnnestus", + "Failed to save webhook": "", "Failed to unshare chat.": "Vestluse jagamise lõpetamine ebaõnnestus.", "Failed to update settings": "Seadete uuendamine ebaõnnestus", "Failed to update status": "Oleku uuendamine ebaõnnestus", + "Failed to update webhook": "", "Failed to upload file.": "Faili üleslaadimine ebaõnnestus.", "Features": "Funktsioonid", "Features Permissions": "Funktsioonide õigused", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Fail edukalt üles laaditud", "Filename": "Failinimi", "Files": "Failid", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filter", "Filter is now globally disabled": "Filter on nüüd globaalselt keelatud", "Filter is now globally enabled": "Filter on nüüd globaalselt lubatud", @@ -1009,6 +1099,7 @@ "Folder options": "Kausta valikud", "Folder updated successfully": "Kaust edukalt uuendatud", "Folders": "Kaustad", + "Folders Sharing": "", "Follow up": "Järelküsimus", "Follow Up Generation": "Järelküsimuste genereerimine", "Follow Up Generation Prompt": "Järelküsimuse genereerimise sisend", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funktsioon on nüüd globaalselt lubatud", "Function Name": "Funktsiooni nimi", "Function Name Filter List": "Funktsiooni nime filtrite nimekiri", + "Function starter": "", "Function updated successfully": "Funktsioon edukalt uuendatud", "Functions": "Funktsioonid", "Functions allow arbitrary code execution.": "Funktsioonid võimaldavad suvalise koodi käivitamist.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Ruudustik", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Grupi kanal", + "Group Claim": "", "Group created successfully": "Grupp edukalt loodud", "Group deleted successfully": "Grupp edukalt kustutatud", "Group Description": "Grupi kirjeldus", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptiline tagasiside", + "Header variables": "", "Headers": "Päised", "Headers must be a valid JSON object": "Päised peavad olema kehtiv JSON-objekt", "Height": "Kõrgus", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID ei tohi sisaldada märke \":\" ega \"|\"", "ID copied to clipboard": "ID kopeeritud lõikelauale", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe liivakast: luba vormid", "iframe Sandbox Allow Same Origin": "iframe liivakast: luba sama päritolu", @@ -1138,6 +1236,7 @@ "Import From Link": "Impordi lingist", "Import Models": "Impordi mudelid", "Import Prompts": "Impordi sisendid", + "Import Skills": "", "Import successful": "Import õnnestus", "Import Tools": "Impordi tööriistad", "Important Update": "Oluline värskendus", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Hoia külgribal", "Key": "Võti", "Key is required": "Võti on nõutav", - "Keyboard shortcuts": "Klaviatuuri otseteed", "Keyboard Shortcuts": "Klaviatuuri otseteed", "Knowledge": "Teadmised", "Knowledge Access": "Teadmiste juurdepääs", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Teadmiste nimi", "Knowledge Public Sharing": "Teadmiste avalik jagamine", "Knowledge Sharing": "Teadmiste jagamine", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Teadmised edukalt uuendatud", "Kokoro.js (Browser)": "Kokoro.js (brauser)", "Kokoro.js Dtype": "Kokoro.js andmetüüp", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Viimane vastus", "LDAP": "LDAP", - "LDAP server updated": "LDAP server uuendatud", "Leaderboard": "Edetabel", "Learn more": "Lisateave", "Learn More": "Lisateave", @@ -1246,6 +1345,7 @@ "Legacy": "Pärand", "lexical": "leksikaalne", "License": "Litsents", + "Lifecycle JSON": "", "Lift List": "Tõsta nimekirja", "Light": "Hele", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Piira samaaegseid otsingupäringuid. 0 = piiramatu (vaikimisi). Määrake 1 järjestikuse täitmise jaoks (soovitatav API-de puhul, millel on ranged piirangud, nagu Brave tasuta tase).", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Asukoha juurdepääs pole lubatud", "Lost": "Kaotanud", "Low": "Madal", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Loodud Open WebUI kogukonna poolt", "Make password visible in the user interface": "Muuda parool kasutajaliideses nähtavaks", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Halda torustikke", "Manage Tool Servers": "Halda tööriistaservereid", "Manage your account information.": "Halda oma konto teavet.", + "Mapped Source": "", "March": "Märts", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown päise teksti tükeldaja", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Mälu edukalt tühjendatud", "Memory deleted successfully": "Mälu edukalt kustutatud", "Memory updated successfully": "Mälu edukalt uuendatud", + "Merge Accounts by Email": "", "Merge Responses": "Ühenda vastused", "Merged Response": "Kombineeritud vastus", "Message": "Sõnum", @@ -1322,9 +1425,12 @@ "messages": "sõnumid", "Messages": "Sõnumid", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Teie saadetud sõnumeid pärast lingi loomist ei jagata. Kasutajad, kellel on URL, saavad vaadata jagatud vestlust.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (isiklik)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (töö/kool)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Pilve API režiimis on nõutav MinerU API võti.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Mudelite jagamine", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API võti", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Rohkem", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Nimetage oma teadmiste baas", "Name, prompt, and model are required": "", "Native": "Omane", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "Uus", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "Pole juurdepääsuõigusi. Privaatne teile.", "No activity data": "Tegevusandmed puuduvad", + "No additional headers are sent unless configured.": "", "No authentication": "Autentimist pole", "No automations found": "", "No chats found": "Vestlusi ei leitud", @@ -1435,8 +1544,10 @@ "No data": "Andmed puuduvad", "No data found": "Andmeid ei leitud", "No distance available": "Kaugus pole saadaval", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "Aegumise puudumine võib kujutada turvariske.", + "No external knowledge sources configured.": "", "No feedback found": "Tagasisidet ei leitud", "No file selected": "Faili pole valitud", "No files found": "Faile ei leitud", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "Kinnitatud sõnumeid pole", "No prompts found": "Sisendeid ei leitud", + "No Repeat": "", "No results": "Tulemusi ei leitud", "No results found": "Tulemusi ei leitud", "No search query generated": "Otsingupäringut ei genereeritud", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Webhook'e veel pole", "Node Ids": "Sõlmede ID-d", "None": "Mitte ühtegi", + "Not configured": "", "Not factually correct": "Faktiliselt ebakorrektne", "Not helpful": "Ei ole kasulik", "Not Registered": "Pole registreeritud", @@ -1498,20 +1611,25 @@ "Notifications": "Teavitused", "November": "November", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktoober", "Off": "Väljas", "Okay, Let's Go!": "Hea küll, lähme!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED tume", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API seaded uuendatud", "Ollama Cloud API Key": "Ollama Cloud API Võti", "Ollama Version": "Ollama versioon", + "Omit": "", "On": "Sees", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Parool", "Passwords do not match.": "Paroolid ei ühti.", "Paste Large Text as File": "Kleebi suur tekst failina", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokument (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "ootel", "Pending": "Ootel", + "Pending Accounts": "", "Pending User Overlay Content": "Ootava kasutaja kattekihi sisu", "Pending User Overlay Title": "Ootava kasutaja kattekihi pealkiri", "Permission denied when accessing media devices": "Juurdepääs meediumiseadmetele keelatud", "Permission denied when accessing microphone": "Juurdepääs mikrofonile keelatud", "Permission denied when accessing microphone: {{error}}": "Juurdepääs mikrofonile keelatud: {{error}}", "Permissions": "Õigused", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API võti", "Perplexity Model": "Perplexity mudel", "Perplexity Search API URL": "Perplexity otsingu API URL", "Perplexity Search Context Usage": "Perplexity otsingu konteksti kasutus", "Persistent": "", "Personalization": "Isikupärastamine", + "Picture Claim": "", "Pin": "Kinnita", "Pin to Sidebar": "", "Pinned": "Kinnitatud", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Palun täitke kõik väljad.", "Please register the OAuth client": "Palun registreerige OAuth klient", "Please save the connection to persist the OAuth client information and do not change the ID": "Palun salvestage ühendus, et säilitada OAuth kliendi teave, ja ärge muutke ID-d", - "Please select a model first.": "Palun valige esmalt mudel.", "Please select a model.": "Palun valige mudel.", "Please select a reason": "Palun valige põhjus", "Please select a valid JSON file": "Palun valige kehtiv JSON-fail", "Please select at least one user for Direct Message channel.": "Palun valige otsesõnumi kanali jaoks vähemalt üks kasutaja.", "Please wait until all files are uploaded.": "Palun oodake, kuni kõik failid on üles laaditud.", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "Pordid", "Positive attitude": "Positiivne suhtumine", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Sisendite avalik jagamine", "Prompts Sharing": "Sisendite jagamine", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Avalik", "Pull \"{{searchValue}}\" from Ollama.com": "Tõmba \"{{searchValue}}\" Ollama.com-ist", "Pull a model from Ollama.com": "Tõmba mudel Ollama.com-ist", @@ -1687,21 +1811,29 @@ "Read": "Loe", "Read Aloud": "Loe valjult", "Read more →": "Loe lisaks →", + "Read only": "", "Read Only": "Ainult lugemine", "Read-Only Access": "Ainult lugemisõigus", "Reason": "Põhjus", "Reasoning Effort": "Arutluspingutus", "Reasoning Tags": "Arutlussildid", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Salvesta", "Record voice": "Salvesta hääl", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Suunamine Open WebUI kogukonda", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Vähendab mõttetuste genereerimise tõenäosust. Kõrgem väärtus (nt 100) annab mitmekesisemaid vastuseid, samas kui madalam väärtus (nt 10) on konservatiivsem.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Viita endale kui \"Kasutaja\" (nt \"Kasutaja õpib hispaania keelt\")", "Reference Chats": "Viitevestlused", "Refresh": "Värskenda", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Keeldus, kui ei oleks pidanud", "Regenerate": "Regenereeri", "Regenerate Menu": "Regenereeri menüü", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "Renderda Markdown eelvaadetes", "Render Markdown in User Messages": "", "Reorder Models": "Muuda mudelite järjekorda", + "Repeat": "", "Repeats": "", "Reply": "Vasta", "Reply in Thread": "Vasta lõimes", "Reply to thread...": "Vasta lõimele...", "Replying to {{NAME}}": "Vastamine kasutajale {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "nõutav", "Reranking Batch Size": "", "Reranking Engine": "Ümberjärjestamise mootor", "Reranking Model": "Ümberjärjestamise mudel", + "Research Knowledge": "", "Reset": "Lähtesta", "Reset All Models": "Lähtesta kõik mudelid", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Lähtesta pilt", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Lähtesta üleslaadimiste kataloog", "Reset Vector Storage/Knowledge": "Lähtesta vektormälu/teadmised", "Reset view": "Lähtesta vaade", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "Hangitud 1 allikas", "Rich Text Input for Chat": "Rikasteksti sisend vestluse jaoks", "Role": "Roll", + "Roles Claim": "", "RTL": "RTL", "Run": "Käivita", "Run All": "Käivita kõik", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Vestluslogi salvestamine otse teie brauseri mällu pole enam toetatud. Palun võtke hetk, et alla laadida ja kustutada oma vestluslogi, klõpsates allpool olevat nuppu. Ärge muretsege, saate hõlpsasti oma vestluslogi tagarakendusse uuesti importida, kasutades", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Keri haru muutmisel", "Scroll to Top": "", "Search": "Otsing", "Search a model": "Otsi mudelit", + "Search actions": "", "Search all emojis": "Otsi kõigist emotikonidest", "Search and manage user memories": "Otsi ja halda kasutaja mälestusi", "Search and view user chat history": "Otsi ja vaata kasutaja vestluste ajalugu", @@ -1798,6 +1940,7 @@ "Search Chats": "Otsi vestlusi", "Search Collection": "Otsi kogust", "Search Files": "Otsi faile", + "Search filters": "", "Search Filters": "Otsingu filtrid", "search for archived chats": "otsi arhiveeritud vestlusi", "search for folders": "otsi kaustu", @@ -1812,13 +1955,16 @@ "Search Models": "Otsi mudeleid", "Search Notes": "Otsi märkmeid", "Search options": "Otsingu valikud", + "Search or add pattern": "", "Search Prompts": "Otsi sisendeid", "Search Result Count": "Otsingutulemuste arv", + "Search skills": "", "Search Skills": "Otsi oskusi", - "Search skills...": "", "Search the internet": "Otsi internetist", "Search the web and fetch URLs": "Otsi veebist ja hangi URL-e", + "Search tools": "", "Search Tools": "Otsi tööriistu", + "Search users or groups": "", "Search, view, and manage user notes": "Otsi, vaata ja halda kasutaja märkmeid", "SearchApi API Key": "SearchApi API võti", "SearchApi Engine": "SearchApi mootor", @@ -1834,7 +1980,6 @@ "Seed": "Seeme", "Select": "Vali", "Select {{modelName}} model": "Vali {{modelName}} mudel", - "Select a base model": "Valige baas mudel", "Select a base model (e.g. llama3, gpt-4o)": "Valige baas mudel (nt llama3, gpt-4o)", "Select a conversation to preview": "Valige vestlus eelvaateks", "Select a engine": "Valige mootor", @@ -1872,18 +2017,25 @@ "semantic": "semantiline", "Send": "Saada", "Send a Message": "Saada sõnum", + "Send events for": "", "Send message": "Saada sõnum", "Send now": "Saada kohe", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Saadab `stream_options: { include_usage: true }` päringus.\nToetatud teenusepakkujad tagastavad määramisel vastuses tokeni kasutuse teabe.", "September": "September", "SerpApi API Key": "SerpApi API võti", "SerpApi Engine": "SerpApi mootor", "Serper API Key": "Serper API võti", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API võti", "Serpstack API Key": "Serpstack API võti", "Server connection failed": "", "Server connection verified": "Serveri ühendus kontrollitud", + "Service Account": "", "Session": "Seanss", + "Session expired. Please sign in again.": "", "Set as default": "Määra vaikimisi", "Set as Production": "Määra tootmisversiooniks", "Set embedding model": "Määra manustamise mudel", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Jagamislink kopeeritud lõikelauale.", "Share to Open WebUI Community": "Jaga Open WebUI kogukonnaga", "Share your background and interests": "Jagage oma tausta ja huvisid", + "Shared": "", "Shared Chats": "Jagatud vestlused", "Shared with you": "Teiega jagatud", "Sharing Permissions": "Jagamise õigused", "Show": "Näita", - "Show \"What's New\" modal on login": "Näita \"Mis on uut\" modaalakent sisselogimisel", + "Show \"What's New\" Modal on Login": "Näita \"Mis on uut\" modaalakent sisselogimisel", "Show Admin Details in Account Pending Overlay": "Näita administraatori üksikasju konto ootel kattekihil", "Show All": "Näita kõik", "Show all ({{COUNT}} characters)": "Näita kõik ({{COUNT}} märki)", "Show Files": "Kuva failid", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Kuva vormindamise tööriistariba", "Show image preview": "Kuva pildi eelvaade", "Show Model": "Kuva mudel", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou otsingu API sID", "Sougou Search API SK": "Sougou otsingu API SK", "Source": "Allikas", + "Specific users or groups": "", "Speech Playback Speed": "Kõne taasesituse kiirus", "Speech recognition error: {{error}}": "Kõnetuvastuse viga: {{error}}", "Speech-to-Text": "Speech-to-Text", @@ -1999,6 +2154,7 @@ "STT Settings": "STT seaded", "Stylized PDF Export": "Stiliseeritud PDF eksport", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "Esita küsimus", "Submit suggestion": "Esita soovitus", "Subtitle": "Alampealkiri", @@ -2023,8 +2179,10 @@ "Syncing...": "Sünkroonimine...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sünkroonib ainult vestlused, mis on uuendatud pärast teie viimast sünkroonimist. Keelake kõigi vestluste uuesti sünkroonimiseks.", "System": "Süsteem", + "System events only": "", "System Instructions": "Süsteemi juhised", "System Prompt": "Süsteemi sisend", + "Table": "", "Tag": "Silt", "Tags": "Sildid", "Tags Generation": "Siltide genereerimine", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Ajutine vestlus vaikimisi", "Terminal": "Terminal", "Terminal servers saved": "Terminali serverid salvestatud", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Teksti tükeldaja", "Text-to-Speech": "Text-to-Speech", "Text-to-Speech Engine": "Tekst-kõneks mootor", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Sisend-heli keel. Sisendkeele esitamine ISO-639-1 (nt en) formaadis parandab täpsust ja latentsust. Jätke tühjaks keele automaatseks tuvastamiseks.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP atribuut, mis kaardistab e-posti, mida kasutajad kasutavad sisselogimiseks.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP atribuut, mis kaardistab kasutajanime, mida kasutajad kasutavad sisselogimiseks.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Edetabel on praegu beetaversioonina ja me võime kohandada hindamisarvutusi algoritmi täiustamisel.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Maksimaalne failisuurus MB-des. Kui failisuurus ületab seda piiri, faili ei laadita üles.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maksimaalne failide arv, mida saab korraga vestluses kasutada. Kui failide arv ületab selle piiri, faile ei laadita üles.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Teksti väljundformaat. Võib olla 'json', 'markdown' või 'html'. Vaikimisi 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "See kaust on tühi", "This is a default user permission and will remain enabled.": "See on vaikimisi kasutajaõigus ja jääb lubatuks.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "See on katsetuslik funktsioon, see ei pruugi toimida ootuspäraselt ja võib igal ajal muutuda.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "See mudel pole avalikult saadaval. Palun valige teine mudel.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "See valik kontrollib, kui kaua mudel jääb pärast päringut mällu laadituna (vaikimisi: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "See valik kontrollib, mitu tokenit säilitatakse konteksti värskendamisel. Näiteks kui see on määratud 2-le, säilitatakse vestluse konteksti viimased 2 tokenit. Konteksti säilitamine võib aidata säilitada vestluse järjepidevust, kuid võib vähendada võimet reageerida uutele teemadele.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Saadaolevate lõpp-punktide kohta rohkem teada saamiseks külastage meie dokumentatsiooni.", "To select skills here, add them to the \"Skills\" workspace first.": "Oskuste siit valimiseks lisage need esmalt \"Oskuste\" tööalale.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Tööriistakomplektide siit valimiseks lisage need esmalt \"Tööriistade\" tööalale.", - "Toast notifications for new updates": "Hüpikmärguanded uuenduste kohta", + "Toast Notifications for New Updates": "Hüpikmärguanded uuenduste kohta", "Today": "Täna", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Täna kell {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Lülita, kas praegune ühendus on aktiivne.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Tokenite arvud on hinnangulised ega pruugi kajastada tegelikku API kasutust", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokenit", "Tokens": "Tokenid", "Too verbose": "Liiga paljusõnaline", @@ -2184,14 +2350,19 @@ "Unpin": "Eemalda kinnitus", "Unpin from Sidebar": "", "Unravel secrets": "Ava saladused", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Lõpeta vestluse jagamine", "Unsupported file type.": "Toetamata failitüüp.", "Untagged": "Sildistamata", "Untitled": "Pealkirjata", "Update": "Uuenda", "Update and Copy Link": "Uuenda ja kopeeri link", + "Update Email": "", "Update for the latest features and improvements.": "Uuendage, et saada uusimad funktsioonid ja täiustused.", + "Update Name": "", "Update password": "Uuenda parooli", + "Update Picture": "", "Update your status": "Uuenda oma olekut", "Updated": "Uuendatud", "Updated at": "Uuendamise aeg", @@ -2218,13 +2389,18 @@ "Use": "Kasuta", "Use '#' in the prompt input to load and include your knowledge.": "Kasutage '#' sisendi väljal, et laadida ja kaasata oma teadmised.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Kasuta /v1/chat/completions lõpp-punkti /v1/audio/transcriptions asemel potentsiaalselt parema täpsuse saavutamiseks.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Kasuta Chat Completions API-t", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Kasutage gruppe oma kasutajate korraldamiseks ja õiguste määramiseks.", "Use LLM": "Kasuta LLM-i", "Use no proxy to fetch page contents.": "Ärge kasutage puhverserverit lehe sisu hankimiseks.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Kasutage http_proxy ja https_proxy keskkonnamuutujates määratud puhverserverit lehe sisu hankimiseks.", + "Use Web Search?": "", "user": "kasutaja", "User": "Kasutaja", + "User Access": "", "User Activity": "Kasutaja tegevus", "User Groups": "Kasutajagrupid", "User location successfully retrieved.": "Kasutaja asukoht edukalt hangitud.", @@ -2234,6 +2410,7 @@ "User Status": "Kasutaja olek", "User Webhooks": "Kasutaja webhook'id", "Username": "Kasutajanimi", + "Username Claim": "", "users": "kasutajad", "Users": "Kasutajad", "Uses DefaultAzureCredential to authenticate": "Kasutab autentimiseks DefaultAzureCredential'i", @@ -2247,6 +2424,7 @@ "Valves updated": "Klapid uuendatud", "Valves updated successfully": "Klapid edukalt uuendatud", "variable": "muutuja", + "Vector Field": "", "Verify Connection": "Kontrolli ühendust", "Verify SSL Certificate": "Kontrolli SSL-sertifikaati", "Version": "Versioon", @@ -2276,11 +2454,14 @@ "Web API": "Veebi API", "Web Loader Engine": "Veebilaadija mootor", "Web Search": "Veebiotsing", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Veebi otsingumootor", "Web Search in Chat": "Veebiotsing vestluses", "Web Search Query Generation": "Veebi otsingupäringu genereerimine", + "Webhook deleted": "", "Webhook Name": "Webhook'i nimi", - "Webhook URL": "Webhooki URL", + "Webhook saved": "", "Webhooks": "Webhook'id", "Webpage URLs": "Veebilehtede URL-id", "WebUI Settings": "WebUI seaded", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex veebiotsingu API võti", "Yandex Web Search config": "Yandex veebiotsingu seadistus", "Yandex Web Search URL": "Yandex veebiotsingu URL", + "Yearly": "", "Yesterday": "Eile", "Yesterday at {{LOCALIZED_TIME}}": "Eile kell {{LOCALIZED_TIME}}", "You": "Sina", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Teie brauser ei toeta video silti.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Kogu teie toetus läheb otse pistikprogrammi arendajale; Open WebUI ei võta mingit protsenti. Kuid valitud rahastamisplatvormil võivad olla oma tasud.", "Your message text or inputs": "Teie sõnumi tekst või sisendid", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Teie kasutusstatistika on edukalt sünkroonitud.", "YouTube": "YouTube", "Youtube Language": "Youtube keel", diff --git a/src/lib/i18n/locales/eu-ES/translation.json b/src/lib/i18n/locales/eu-ES/translation.json index 6d8ec3bcd4..72c2350c0f 100644 --- a/src/lib/i18n/locales/eu-ES/translation.json +++ b/src/lib/i18n/locales/eu-ES/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}-ren Txatak", "{{webUIName}} Backend Required": "{{webUIName}} Backend-a Beharrezkoa", "*Prompt node ID(s) are required for image generation": "Prompt nodoaren IDa(k) beharrezkoak dira irudiak sortzeko", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Sarbide Kontrola", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Erabiltzaile guztientzat eskuragarri", "Account": "Kontua", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Gehitu", "Add a model ID": "Gehitu eredu ID bat", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Gehitu eredu honek egiten duenaren deskribapen labur bat", "Add a tag": "Gehitu etiketa bat", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Gehitu Fitxategiak", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Gehitu Erabiltzailea", "Add User Group": "Gehitu Erabiltzaile Taldea", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Administratzailea", "Admin Contact Email": "", "Admin Panel": "Administrazio Panela", + "Admin Roles": "", "Admin Settings": "Administrazio Ezarpenak", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratzaileek tresna guztietarako sarbidea dute beti; erabiltzaileek lan-eremuan eredu bakoitzeko esleituak behar dituzte tresnak.", "Advanced": "", "Advanced Parameters": "Parametro Aurreratuak", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Eredu guztiak ongi ezabatu dira", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "Baimendu Txata Ezabatzea", "Allow Chat Edit": "Baimendu Txata Editatzea", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Baimendu Erabiltzailearen Kokapena", "Allow Voice Interruption in Call": "Baimendu Ahots Etena Deietan", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Baduzu kontu bat?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API Oinarri URLa", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API Gakoa", + "API Key / Token": "", "API Key created.": "API Gakoa sortu da.", "API Key Endpoint Restrictions": "", "API keys": "API gakoak", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Ziur zaude artxibatutako txat guztiak desartxibatu nahi dituzula?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena Ereduak", "Artifacts": "Artefaktuak", "Asc": "", "Ask": "", "Ask a question": "Egin galdera bat", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Laguntzailea", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audioa", "August": "Abuztua", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentifikatu", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatikoki Kopiatu Erantzuna Arbelera", - "Auto-playback response": "Automatikoki erreproduzitu erantzuna", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatikoki erreproduzitu erantzuna", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Autentifikazio Katea", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Oinarri URLa", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "erabilgarri dauden erabiltzaileak", + "Available variables": "", "available!": "eskuragarri!", "Away": "Kanpoan", "Awful": "Penagarria", @@ -258,16 +295,17 @@ "Bad Response": "Erantzun Txarra", "Banners": "Bannerrak", "Base Model (From)": "Oinarrizko Eredua (Nondik)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "aurretik", "Being lazy": "Alferra izatea", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "Bing Bilaketa V7 Endpointua", "Bing Search V7 Subscription Key": "Bing Bilaketa V7 Harpidetza Gakoa", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Txataren norabidea", + "Chat Direction": "Txataren norabidea", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Bilduma", + "Collection Field": "", "Collections": "", "Color": "Kolorea", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI Lan-fluxua", "ComfyUI Workflow Nodes": "ComfyUI Lan-fluxu Nodoak", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Komandoa", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Osatzeak", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Jarri harremanetan Administratzailearekin WebUI Sarbiderako", "Content": "Edukia", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Jarraitu Erantzuna", "Continue with {{provider}}": "Jarraitu {{provider}}-rekin", "Continue with Email": "Jarraitu Posta Elektronikoarekin", @@ -493,6 +543,7 @@ "Create new secret key": "Sortu gako sekretu berria", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Sortze data", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Eredu Lehenetsia", "Default model updated": "Eredu lehenetsia eguneratu da", "Default permissions": "Baimen lehenetsiak", @@ -542,6 +593,7 @@ "Default to ALL": "Lehenetsi GUZTIAK", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Erabiltzaile Rol Lehenetsia", + "Default webhook": "", "Defaults": "", "Delete": "Ezabatu", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Desgaituta", "Disconnect OAuth": "", "Discover a function": "Aurkitu funtzio bat", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Aurkitu, deskargatu eta esploratu ereduen aurrezarpenak", "Discussion channel where access is based on groups and permissions": "", "Display": "Bistaratu", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Bistaratu Emojiak Deietan", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Erakutsi erabiltzaile-izena Zu-ren ordez Txatean", + "Display the Username Instead of You in the Chat": "Erakutsi erabiltzaile-izena Zu-ren ordez Txatean", "Displays citations in the response": "Erakutsi aipamenak erantzunean", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Murgildu ezagutzan", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokumentua", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Editatu Baimen Lehenetsiak", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Editatu Memoria", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Editatu Erabiltzailea", "Edit User Group": "Editatu Erabiltzaile Taldea", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Posta elektronikoa", + "Email Claim": "", "Embark on adventures": "Hasi abenturak", "Embedding": "", "Embedding Batch Size": "Embedding Batch Tamaina", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Embedding Eredu Motorea", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Gaitu Komunitatearen Partekatzea", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Gaitu Memoria Blokeatzea (mlock) ereduaren datuak RAM memoriatik kanpo ez trukatzeko. Aukera honek ereduaren lan-orri multzoa RAMean blokatzen du, diskora ez direla trukatuko ziurtatuz. Honek errendimendua mantentzen lagun dezake, orri-hutsegiteak saihestuz eta datuen sarbide azkarra bermatuz.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Gaitu Memoria Mapaketa (mmap) ereduaren datuak kargatzeko. Aukera honek sistemari disko-biltegiratzea RAM memoriaren luzapen gisa erabiltzea ahalbidetzen dio, diskoko fitxategiak RAMean baleude bezala tratatuz. Honek ereduaren errendimendua hobe dezake, datuen sarbide azkarragoa ahalbidetuz. Hala ere, baliteke sistema guztietan behar bezala ez funtzionatzea eta disko-espazio handia kontsumitu dezake.", "Enable Message Queue": "", "Enable Message Rating": "Gaitu Mezuen Balorazioa", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Gaitu Izena Emate Berriak", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Gaituta", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Ziurtatu zure CSV fitxategiak 4 zutabe dituela ordena honetan: Izena, Posta elektronikoa, Pasahitza, Rola.", "Enter {{role}} message here": "Sartu {{role}} mezua hemen", - "Enter a detail about yourself for your LLMs to recall": "Sartu zure buruari buruzko xehetasun bat LLMek gogoratzeko", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Sartu Zatien Gainjartzea (chunk overlap)", "Enter Chunk Size": "Sartu Zati Tamaina", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Sartu hizkuntza kodeak", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Sartu Puntuazioa", "Enter SearchApi API Key": "Sartu SearchApi API Gakoa", "Enter SearchApi Engine": "Sartu SearchApi Motorea", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Sartu Serper API Gakoa", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Sartu Serply API Gakoa", "Enter Serpstack API Key": "Sartu Serpstack API Gakoa", "Enter server host": "Sartu zerbitzariaren ostalaria", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Sartu Tika Zerbitzari URLa", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Sartu Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Sartu URLa (adib. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Ebaluazioak", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Adibidea: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Adibidea: GUZTIAK", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Esportatu CSVra", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Huts egin du API Gakoa sortzean.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Huts egin du arbelaren edukia irakurtzean", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Huts egin du ereduen konfigurazioa gordetzean", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Huts egin du ezarpenak eguneratzean", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Huts egin du fitxategia igotzean.", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Fitxategiak", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Iragazkia orain globalki desgaituta dago", "Filter is now globally enabled": "Iragazkia orain globalki gaituta dago", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funtzioa orain globalki gaituta dago", "Function Name": "Funtzioaren Izena", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funtzioa ongi eguneratu da", "Functions": "Funtzioak", "Functions allow arbitrary code execution.": "Funtzioek kode arbitrarioa exekutatzea ahalbidetzen dute.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Taldea ongi sortu da", "Group deleted successfully": "Taldea ongi ezabatu da", "Group Description": "Taldearen Deskribapena", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Feedback Haptikoa", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "IDa", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Eguneratze garrantzitsua", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Gakoa", "Key is required": "", - "Keyboard shortcuts": "Teklatuko lasterbideak", "Keyboard Shortcuts": "", "Knowledge": "Ezagutza", "Knowledge Access": "Ezagutzarako Sarbidea", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Ezagutza ongi eguneratu da.", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "LDAP", - "LDAP server updated": "LDAP zerbitzaria eguneratu da", "Leaderboard": "Sailkapena", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Argia", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "Galduta", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "OpenWebUI Komunitateak egina", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Kudeatu Pipeline-ak", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Martxoa", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Memoria ongi garbitu da", "Memory deleted successfully": "Memoria ongi ezabatu da", "Memory updated successfully": "Memoria ongi eguneratu da", + "Merge Accounts by Email": "", "Merge Responses": "Batu erantzunak", "Merged Response": "Erantzun bateratua", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Esteka sortu ondoren bidaltzen dituzun mezuak ez dira partekatuko. URLa duten erabiltzaileek partekatutako txata ikusi ahal izango dute.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Mojeek bilaketa API gakoa", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Gehiago", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Izendatu zure ezagutza-basea", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Ez dago distantziarik eskuragarri", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ez da fitxategirik hautatu", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Ez da emaitzarik aurkitu", "No results found": "Ez da emaitzarik aurkitu", "No search query generated": "Ez da bilaketa kontsultarik sortu", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Bat ere ez", + "Not configured": "", "Not factually correct": "Ez da faktikoki zuzena", "Not helpful": "Ez da lagungarria", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Jakinarazpenak", "November": "Azaroa", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Urria", "Off": "Itzalita", "Okay, Let's Go!": "Ados, Goazen!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED iluna", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API ezarpenak eguneratu dira", "Ollama Cloud API Key": "", "Ollama Version": "Ollama bertsioa", + "Omit": "", "On": "Piztuta", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "Pasahitza", "Passwords do not match.": "", "Paste Large Text as File": "Itsatsi testu luzea fitxategi gisa", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokumentua (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "zain", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Baimena ukatu da multimedia gailuak atzitzean", "Permission denied when accessing microphone": "Baimena ukatu da mikrofonoa atzitzean", "Permission denied when accessing microphone: {{error}}": "Baimena ukatu da mikrofonoa atzitzean: {{error}}", "Permissions": "Baimenak", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Pertsonalizazioa", + "Picture Claim": "", "Pin": "Ainguratu", "Pin to Sidebar": "", "Pinned": "Ainguratuta", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Mesedez, bete eremu guztiak.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "Mesedez, hautatu arrazoi bat", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Ataka", "Ports": "", "Positive attitude": "Jarrera positiboa", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Ekarri \"{{searchValue}}\" Ollama.com-etik", "Pull a model from Ollama.com": "Ekarri modelo bat Ollama.com-etik", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "Irakurri ozen", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Grabatu ahotsa", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI Komunitatera berbideratzen", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Egin erreferentzia zure buruari \"Erabiltzaile\" gisa (adib., \"Erabiltzailea gaztelania ikasten ari da\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Ukatu duenean ukatu behar ez zuenean", "Regenerate": "Bersortu", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Berrantolatu modeloak", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Berrantolatze modeloa", + "Research Knowledge": "", "Reset": "Berrezarri", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Berrezarri irudia", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Berrezarri karga direktorioa", "Reset Vector Storage/Knowledge": "Berrezarri bektore biltegia/ezagutza", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Testu aberastuko sarrera txaterako", "Role": "Rola", + "Roles Claim": "", "RTL": "RTL", "Run": "Exekutatu", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Txat erregistroak zuzenean zure nabigatzailearen biltegian gordetzea ez da jadanik onartzen. Mesedez, hartu une bat zure txat erregistroak deskargatu eta ezabatzeko beheko botoia sakatuz. Ez kezkatu, zure txat erregistroak erraz inportatu ditzakezu berriro backendera honen bidez", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Bilatu", "Search a model": "Bilatu modelo bat", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Bilatu txatak", "Search Collection": "Bilatu bilduma", "Search Files": "", + "Search filters": "", "Search Filters": "Bilaketa iragazkiak", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Bilatu modeloak", "Search Notes": "", "Search options": "Bilaketa aukerak", + "Search or add pattern": "", "Search Prompts": "Bilatu prompt-ak", "Search Result Count": "Bilaketa emaitzen kopurua", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Bilaketa tresnak", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API gakoa", "SearchApi Engine": "SearchApi motorra", @@ -1834,7 +1980,6 @@ "Seed": "Hazia", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Hautatu oinarrizko modeloa", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Hautatu motor bat", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Bidali", "Send a Message": "Bidali mezu bat", + "Send events for": "", "Send message": "Bidali mezua", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Bidaltzen du `stream_options: { include_usage: true }` eskaeran.\nOnartutako hornitzaileek token erabileraren informazioa itzuliko dute erantzunean ezarrita dagoenean.", "September": "Iraila", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API gakoa", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API gakoa", "Serpstack API Key": "Serpstack API gakoa", "Server connection failed": "", "Server connection verified": "Zerbitzari konexioa egiaztatuta", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Ezarri lehenetsi gisa", "Set as Production": "", "Set embedding model": "Ezarri txertatze modeloa", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Partekatu OpenWebUI komunitatearekin", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Erakutsi", - "Show \"What's New\" modal on login": "Erakutsi \"Berritasunak\" modala saioa hastean", + "Show \"What's New\" Modal on Login": "Erakutsi \"Berritasunak\" modala saioa hastean", "Show Admin Details in Account Pending Overlay": "Erakutsi administratzaile xehetasunak kontu zain geruzan", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Iturria", + "Specific users or groups": "", "Speech Playback Speed": "Ahots erreprodukzio abiadura", "Speech recognition error: {{error}}": "Ahots ezagutze errorea: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT ezarpenak", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "Sistema jarraibideak", "System Prompt": "Sistema prompta", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Testu banatzailea", "Text-to-Speech": "", "Text-to-Speech Engine": "Testutik-ahotsera motorra", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "Erabiltzaileek saioa hasteko erabiltzen duten erabiltzaile-izenarekin mapeatzen den LDAP atributua.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Sailkapena beta fasean dago, eta balorazioen kalkuluak doitu ditzakegu algoritmoa fintzen dugun heinean.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Fitxategiaren gehienezko tamaina MB-tan. Fitxategiaren tamainak muga hau gainditzen badu, fitxategia ez da kargatuko.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Txatean aldi berean erabili daitezkeen fitxategien gehienezko kopurua. Fitxategi kopuruak muga hau gainditzen badu, fitxategiak ez dira kargatuko.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Hau funtzionalitate esperimental bat da, baliteke espero bezala ez funtzionatzea eta edozein unetan aldaketak izatea.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Tresna-multzoak hemen hautatzeko, gehitu itzazu lehenik \"Tresnak\" lan-eremura.", - "Toast notifications for new updates": "Toast jakinarazpenak eguneraketa berrientzat", + "Toast Notifications for New Updates": "Toast jakinarazpenak eguneraketa berrientzat", "Today": "Gaur", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Tokena", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Luzeegia", @@ -2184,14 +2350,19 @@ "Unpin": "Kendu aingura", "Unpin from Sidebar": "", "Unravel secrets": "Askatu sekretuak", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Etiketatu gabea", "Untitled": "", "Update": "Eguneratu", "Update and Copy Link": "Eguneratu eta kopiatu esteka", + "Update Email": "", "Update for the latest features and improvements.": "Eguneratu azken ezaugarri eta hobekuntzak izateko.", + "Update Name": "", "Update password": "Eguneratu pasahitza", + "Update Picture": "", "Update your status": "", "Updated": "Eguneratuta", "Updated at": "Noiz eguneratuta", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Erabili '#' prompt sarreran zure ezagutza kargatu eta sartzeko.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "erabiltzailea", "User": "Erabiltzailea", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Erabiltzailearen kokapena ongi berreskuratu da.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "Erabiltzaile-izena", + "Username Claim": "", "users": "", "Users": "Erabiltzaileak", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Balbulak eguneratuta", "Valves updated successfully": "Balbulak ongi eguneratu dira", "variable": "aldagaia", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Bertsioa", @@ -2276,11 +2454,14 @@ "Web API": "Web APIa", "Web Loader Engine": "", "Web Search": "Web bilaketa", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Web bilaketa motorra", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URLa", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI ezarpenak", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Atzo", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Zu", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Zure ekarpen osoa zuzenean plugin garatzaileari joango zaio; Open WebUI-k ez du ehunekorik hartzen. Hala ere, aukeratutako finantzaketa plataformak bere komisioak izan ditzake.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/fa-IR/translation.json b/src/lib/i18n/locales/fa-IR/translation.json index a556d73ec1..033267c9be 100644 --- a/src/lib/i18n/locales/fa-IR/translation.json +++ b/src/lib/i18n/locales/fa-IR/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} خط پنهان", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} منبع", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} کلمه", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} در {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "دانلود {{model}} لغو شده است", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} گفتگوهای", "{{webUIName}} Backend Required": "بکند {{webUIName}} نیاز است.", "*Prompt node ID(s) are required for image generation": "*شناسه(های) گره پرامپت برای تولید تصویر مورد نیاز است", + "1 group": "", "1 hour before": "", "1 Source": "۱ منبع", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "کنترل دسترسی", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "قابل دسترسی برای همه کاربران", "Account": "حساب کاربری", @@ -72,6 +83,7 @@ "Activity": "", "Add": "اضافه کردن", "Add a model ID": "افزودن شناسه مدل", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "افزودن توضیحات کوتاه در مورد انچه که این مدل انجام می دهد", "Add a tag": "افزودن یک برچسب", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "افزودن پرامپت سفارشی", "Add description": "", "Add Details": "افزودن جزئیات", + "Add durable context for future chats": "", "Add Files": "افزودن فایل\u200cها", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "افزودن کاربر", "Add User Group": "افزودن گروه کاربری", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "تنظیمات اضافی", @@ -112,7 +127,9 @@ "Admin": "مدیر", "Admin Contact Email": "", "Admin Panel": "پنل مدیریت", + "Admin Roles": "", "Admin Settings": "تنظیمات مدیریت", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "مدیران همیشه به تمام ابزارها دسترسی دارند؛ کاربران نیاز به ابزارهای اختصاص داده شده برای هر مدل در فضای کاری دارند.", "Advanced": "", "Advanced Parameters": "پارامترهای پیشرفته", @@ -123,16 +140,21 @@ "All": "همه", "All chats have been unarchived.": "همه چت\u200cها از حالت بایگانی خارج شدند.", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "همه مدل\u200cها با موفقیت حذف شدند", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "اجازه تماس", "Allow Chat Controls": "اجازه کنترل\u200cهای گفتگو", "Allow Chat Delete": "اجازه حذف گفتگو", "Allow Chat Edit": "اجازه ویرایش گفتگو", "Allow Chat Export": "مجاز کردن خروجی گرفتن از چت", + "Allow Chat Import": "", "Allow Chat Params": "مجاز کردن پارامترهای چت", "Allow Chat Share": "مجاز کردن اشتراک\u200cگذاری چت", "Allow Chat System Prompt": "مجاز کردن پرامپت سیستمی چت", @@ -152,9 +174,11 @@ "Allow User Location": "اجازهٔ موقعیت مکانی کاربر", "Allow Voice Interruption in Call": "اجازه قطع صدا در تماس", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "نقاط پایانی مجاز", "Allowed File Extensions": "پسوندهای فایل مجاز", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "پسوندهای فایل مجاز برای آپلود. چندین پسوند را با کاما از هم جدا کنید. برای همه انواع فایل\u200cها خالی بگذارید.", + "Allowed Roles": "", "Already have an account?": "از قبل حساب کاربری دارید؟", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "جایگزینی برای top_p و هدف آن اطمینان از تعادل کیفیت و تنوع است. پارامتر p نشان\u200cدهنده حداقل احتمال برای در نظر گرفتن یک توکن نسبت به احتمال محتمل\u200cترین توکن است. به عنوان مثال، با p=0.05 و محتمل\u200cترین توکن با احتمال 0.9، لاگیت\u200cهای با مقدار کمتر از 0.045 فیلتر می\u200cشوند.", "Always": "همیشه", @@ -173,6 +197,7 @@ "API Base URL": "نشانی پایهٔ API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "آدرس پایه API برای سرویس مارکر دیتا\u200cلب. پیش\u200cفرض: https://www.datalab.to/api/v1/marker", "API Key": "کلید API", + "API Key / Token": "", "API Key created.": "کلید API ساخته شد.", "API Key Endpoint Restrictions": "محدودیت\u200cهای نقطه پایانی کلید API", "API keys": "کلیدهای API", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "آیا مطمئن هستید که می\u200cخواهید این پیام را حذف کنید؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "آیا مطمئن هستید که می\u200cخواهید همه گفتگوهای بایگانی شده را از بایگانی خارج کنید؟", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "مدل\u200cهای آرنا", "Artifacts": "مصنوعات", "Asc": "", "Ask": "بپرس", "Ask a question": "سوالی بپرسید", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "دستیار", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "صدا", "August": "آگوست", "Auth": "احراز هویت", + "Auth Mode": "", + "Auth required": "", "Authenticate": "احراز هویت", "Authentication": "احراز هویت", "Auto": "خودکار", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "کپی خودکار پاسخ به کلیپ بورد", - "Auto-playback response": "پخش خودکار پاسخ", + "Auto-Create Groups": "", + "Auto-Playback Response": "پخش خودکار پاسخ", "Autocomplete Generation": "تولید تکمیل خودکار", "Autocomplete Generation Input Max Length": "حداکثر طول ورودی تولید تکمیل خودکار", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "اتوماتیک1111", "AUTOMATIC1111 Api Auth String": "رشته احراز هویت API اتوماتیک1111", "AUTOMATIC1111 Base URL": "پایه URL AUTOMATIC1111 ", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "ابزارهای موجود", "available users": "کاربران در دسترس", + "Available variables": "", "available!": "در دسترس!", "Away": "غایب", "Awful": "وحشتناک", @@ -258,16 +295,17 @@ "Bad Response": "پاسخ خوب نیست", "Banners": "بنر", "Base Model (From)": "مدل پایه (از)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "کش لیست مدل پایه، با واکشی مدل\u200cهای پایه فقط در هنگام راه\u200cاندازی یا ذخیره تنظیمات، دسترسی را سرعت می\u200cبخشد – سریع\u200cتر است، اما ممکن است تغییرات اخیر مدل پایه را نشان ندهد.", "Bearer": "حامل", "before": "قبل", "Being lazy": "حالت سازنده", - "Beta": "بتا", "Bing": "", "Bing Search V7 Endpoint": "نقطه پایانی جستجوی Bing V7", "Bing Search V7 Subscription Key": "کلید اشتراک جستجوی Bing V7", "Bio": "بیوگرافی", "Birth Date": "تاریخ تولد", + "Blocked Groups": "", "BM25 Weight": "وزن BM25", "Bocha Search API Key": "کلید API جستجوی Bocha", "Bold": "ضخیم", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "مکالمه چت", "Chat deleted.": "", - "Chat direction": "جهت\u200cگفتگو", + "Chat Direction": "جهت\u200cگفتگو", "Chat exported successfully": "", "Chat History": "", "Chat ID": "شناسه چت", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "جمع کردن", "Collection": "مجموعه", + "Collection Field": "", "Collections": "", "Color": "رنگ", "ComfyUI": "کومیوآی", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "گردش کار کومیوآی", "ComfyUI Workflow Nodes": "گره\u200cهای گردش کار کومیوآی", "Comma separated Node Ids (e.g. 1 or 1,2)": "شناسه\u200cهای گره که با کاما جدا شده\u200cاند (مثلاً ۱ یا ۱,۲)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "دستور", "Comment": "نظر", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "تکمیل\u200cها", "Compress Images in Channels": "فشرده\u200cسازی تصاویر در کانال\u200cها", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "به نقاط پایانی API سازگار با OpenAI خود متصل شوید.", "Connect to your own OpenAPI compatible external tool servers.": "به سرورهای ابزار خارجی سازگار با OpenAPI خود متصل شوید.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "اتصال ناموفق بود", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "برای دسترسی به WebUI با مدیر تماس بگیرید", "Content": "محتوا", "Content Extraction Engine": "موتور استخراج محتوا", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ادامه پاسخ", "Continue with {{provider}}": "با {{provider}} ادامه دهید", "Continue with Email": "با ایمیل ادامه دهید", @@ -493,6 +543,7 @@ "Create new secret key": "ساخت کلید مخفی جدید", "Create note": "", "Create Note": "ایجاد یادداشت", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "با کلیک روی دکمه به\u200cعلاوه در زیر، اولین یادداشت خود را ایجاد کنید.", "Created at": "ایجاد شده در", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "نام پارامتر سفارشی", "Custom Parameter Value": "مقدار پارامتر سفارشی", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "منطقه خطر", @@ -532,7 +584,6 @@ "Default Features": "ویژگی\u200cهای پیش\u200cفرض", "Default Filters": "فیلترهای پیش\u200cفرض", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "حالت پیش\u200cفرض با فراخوانی ابزارها یک بار قبل از اجرا، با طیف وسیع\u200cتری از مدل\u200cها کار می\u200cکند. حالت بومی از قابلیت\u200cهای داخلی فراخوانی ابزار مدل استفاده می\u200cکند، اما مدل باید به طور ذاتی این ویژگی را پشتیبانی کند.", "Default Model": "مدل پیشفرض", "Default model updated": "مدل پیشفرض به\u200cروزرسانی شد", "Default permissions": "مجوزهای پیش\u200cفرض", @@ -542,6 +593,7 @@ "Default to ALL": "پیش\u200cفرض به همه", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "پیش\u200cفرض به بازیابی قطعه\u200cای برای استخراج محتوای متمرکز و مرتبط، این برای اکثر موارد توصیه می\u200cشود.", "Default User Role": "نقش کاربر پیش فرض", + "Default webhook": "", "Defaults": "", "Delete": "حذف", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "غیرفعال کردن مفسر کد", "Disable Image Extraction": "غیرفعال کردن استخراج تصویر", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "غیرفعال کردن استخراج تصویر از PDF. اگر «استفاده از LLM» فعال باشد، تصاویر به\u200cطور خودکار زیرنویس خواهند شد. پیش\u200cفرض: False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "غیرفعال", "Disconnect OAuth": "", "Discover a function": "کشف یک تابع", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید", "Discussion channel where access is based on groups and permissions": "", "Display": "نمایش", - "Display chat title in tab": "نمایش عنوان چت در تب", + "Display Chat Title in Tab": "نمایش عنوان چت در تب", "Display Emoji in Call": "نمایش اموجی در تماس", "Display Multi-model Responses in Tabs": "نمایش پاسخ\u200cهای چند مدلی در تب\u200cها", - "Display the username instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت", + "Display the Username Instead of You in the Chat": "نمایش نام کاربری به جای «شما» در چت", "Displays citations in the response": "نمایش استنادها در پاسخ", "Displays status updates (e.g., web search progress) in the response": "نمایش به\u200cروزرسانی\u200cهای وضعیت (مثلاً پیشرفت جستجوی وب) در پاسخ", "Dive into knowledge": "غوطه\u200cور شدن در دانش", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "آدرس سرور داکلینگ مورد نیاز است.", "Document": "سند", + "Document ID Field": "", "Document Intelligence": "هوش اسناد", "Document Intelligence endpoint required.": "نقطه پایانی هوش سند مورد نیاز است.", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "ویرایش مجوزهای پیش\u200cفرض", "Edit Folder": "ویرایش پوشه", "Edit Image": "ویرایش تصویر", + "Edit Knowledge Connection": "", "Edit Last Message": "ویرایش آخرین پیام", "Edit Memory": "ویرایش حافظه", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ویرایش کاربر", "Edit User Group": "ویرایش گروه کاربری", + "Edit webhook": "", "Edit workflow.json content": "ویرایش محتوای workflow.json", "edited": "ویرایش شد", "Edited": "ویرایش شده", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "الون\u200cلبز", "Email": "ایمیل", + "Email Claim": "", "Embark on adventures": "شروع ماجراجویی\u200cها", "Embedding": "پیدائش", "Embedding Batch Size": "اندازه دسته پیدائش", @@ -707,6 +765,7 @@ "Embedding Model Engine": "محرک مدل پیدائش", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "فعال\u200cسازی اجرای کد", "Enable Code Interpreter": "فعال\u200cسازی مفسر کد", "Enable Community Sharing": "فعالسازی اشتراک انجمن", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "فعال\u200cسازی قفل حافظه (mlock) برای جلوگیری از تعویض داده\u200cهای مدل از RAM. این گزینه مجموعه صفحات کاری مدل را در RAM قفل می\u200cکند و اطمینان می\u200cدهد که به دیسک منتقل نمی\u200cشوند. این می\u200cتواند با جلوگیری از خطاهای صفحه و تضمین دسترسی سریع به داده\u200cها، عملکرد را حفظ کند.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "فعال\u200cسازی نگاشت حافظه (mmap) برای بارگیری داده\u200cهای مدل. این گزینه به سیستم اجازه می\u200cدهد از فضای دیسک به عنوان گسترش RAM استفاده کند با در نظر گرفتن فایل\u200cهای دیسک مانند اینکه در RAM هستند. این می\u200cتواند با اجازه دادن به دسترسی سریع\u200cتر به داده\u200cها، عملکرد مدل را بهبود بخشد. با این حال، ممکن است با همه سیستم\u200cها به درستی کار نکند و می\u200cتواند مقدار قابل توجهی از فضای دیسک را مصرف کند.", "Enable Message Queue": "", "Enable Message Rating": "فعال\u200cسازی امتیازدهی پیام", "Enable Mirostat sampling for controlling perplexity.": "فعال\u200cسازی نمونه\u200cبرداری میروستات برای کنترل سردرگمی", "Enable New Sign Ups": "فعال کردن ثبت نام\u200cهای جدید", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "تگ\u200cهای استدلال مورد استفاده مدل را فعال، غیرفعال یا سفارشی کنید. «فعال» از تگ\u200cهای پیش\u200cفرض استفاده می\u200cکند، «غیرفعال» تگ\u200cهای استدلال را خاموش می\u200cکند، و «سفارشی» به شما امکان می\u200cدهد تگ\u200cهای شروع و پایان خود را مشخص کنید.", "Enabled": "فعال شده", "End Tag": "تگ پایان", + "Endpoint": "", "Endpoint URL": "آدرس URL نقطه پایانی", "Enforce Temporary Chat": "اجبار چت موقت", "Enhance": "بهبود", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "اطمینان حاصل کنید که فایل CSV شما شامل چهار ستون در این ترتیب است: نام، ایمیل، رمز عبور، نقش.", "Enter {{role}} message here": "پیام {{role}} را اینجا وارد کنید", - "Enter a detail about yourself for your LLMs to recall": "برای ذخیره سازی اطلاعات خود، یک توضیح کوتاه درباره خود را وارد کنید", "Enter a title for the pending user info overlay. Leave empty for default.": "یک عنوان برای پوشش اطلاعات کاربر در حال انتظار وارد کنید. برای پیش\u200cفرض خالی بگذارید.", "Enter a watermark for the response. Leave empty for none.": "یک واترمارک برای پاسخ وارد کنید. برای هیچ\u200cکدام خالی بگذارید.", "Enter additional headers in JSON format": "هدرهای اضافی را در قالب JSON وارد کنید", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "مقدار Chunk Overlap را وارد کنید", "Enter Chunk Size": "مقدار Chunk Size را وارد کنید", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "جفت\u200cهای \"توکن:مقدار_بایاس\" را با کاما جدا شده وارد کنید (مثال: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "محتوا برای پوشش اطلاعات کاربر در حال انتظار وارد کنید. برای پیش\u200cفرض خالی بگذارید.", "Enter coordinates (e.g. 51.505, -0.09)": "مختصات را وارد کنید (مثلاً ۵۱.۵۰۵, -۰.۰۹)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "آدرس ژوپیتر را وارد کنید", "Enter Kagi Search API Key": "کلید API جستجوی کاگی را وارد کنید", "Enter Key Behavior": "رفتار کلید را وارد کنید", + "Enter language": "", "Enter language codes": "کد زبان را وارد کنید", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "آدرس پایه API میسترال را وارد کنید", "Enter Mistral API Key": "کلید API میسترال را وارد کنید", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "آدرس پراکسی را وارد کنید (مثال: https://user:password@host:port)", "Enter reasoning effort": "تلاش استدلال را وارد کنید", + "Enter Redirect URI": "", "Enter Score": "امتیاز را وارد کنید", "Enter SearchApi API Key": "کلید API جستجو را وارد کنید", "Enter SearchApi Engine": "موتور جستجو را وارد کنید", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "کلید API سرپ را وارد کنید", "Enter SerpApi Engine": "موتور سرپ را وارد کنید", "Enter Serper API Key": "کلید API سرپر را وارد کنید", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "کلید API سرپلی را وارد کنید", "Enter Serpstack API Key": "کلید API سرپ\u200cاستک را وارد کنید", "Enter server host": "میزبان سرور را وارد کنید", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "آدرس سرور تیکا را وارد کنید", "Enter timeout in seconds": "مهلت زمانی را به ثانیه وارد کنید", "Enter to Send": "برای ارسال اینتر را بزنید", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "مقدار Top K را وارد کنید", "Enter Top K Reranker": "مقدار Top K بازچینش\u200cگر را وارد کنید", "Enter URL (e.g. http://127.0.0.1:7860/)": "مقدار URL را وارد کنید (مثال http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "خطا: مدلی با شناسه '{{modelId}}' قبلاً وجود دارد. لطفاً برای ادامه، یک شناسه متفاوت انتخاب کنید.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "خطا: شناسه مدل نمی\u200cتواند خالی باشد. لطفاً برای ادامه، یک شناسه معتبر وارد کنید.", "Evaluations": "ارزیابی\u200cها", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "کلید API اکسا", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "مثال: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "مثال: ALL", "Example: mail": "مثال: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "برون\u200cریزی به CSV", "Export Tools": "", "Export Users": "خروجی گرفتن از کاربران", "External": "خارجی", + "External connection not found.": "", "External Document Loader URL required.": "آدرس URL بارگذار سند خارجی مورد نیاز است.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "مدل وظیفه خارجی", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "کلید API بارگذار وب خارجی", "External Web Loader URL": "آدرس URL بارگذار وب خارجی", "External Web Search API Key": "کلید API جستجوی وب خارجی", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "ایجاد کلید API با خطا مواجه شد.", "Failed to delete calendar": "", "Failed to delete note": "حذف یادداشت ناموفق بود", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "استخراج محتوا از فایل ناموفق بود: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "خطا در دریافت مدل\u200cها", "Failed to generate title": "تولید عنوان ناموفق بود", "Failed to import models": "وارد کردن مدل\u200cها ناموفق بود", + "Failed to load chat": "", "Failed to load chat preview": "بارگیری پیش\u200cنمایش چت ناموفق بود", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "انتقال چت ناموفق بود", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "خواندن محتوای کلیپ بورد ناموفق بود", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "رندر دیاگرام ناموفق بود", "Failed to render visualization": "رندر بصری\u200cسازی ناموفق بود", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "خطا در ذخیره\u200cسازی پیکربندی مدل\u200cها", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "خطا در به\u200cروزرسانی تنظیمات", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "خطا در بارگذاری پرونده", "Features": "ویژگی\u200cها", "Features Permissions": "مجوزهای ویژگی\u200cها", @@ -987,6 +1075,8 @@ "File uploaded successfully": "پرونده با موفقیت بارگذاری شد", "Filename": "", "Files": "پرونده\u200cها", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "فیلتر", "Filter is now globally disabled": "فیلتر به صورت سراسری غیرفعال شد", "Filter is now globally enabled": "فیلتر به صورت سراسری فعال شد", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "پوشه با موفقیت به\u200cروز شد", "Folders": "پوشه\u200cها", + "Folders Sharing": "", "Follow up": "پیگیری", "Follow Up Generation": "تولید پیگیری", "Follow Up Generation Prompt": "پرامپت تولید پیگیری", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "تابع به صورت سراسری فعال شد", "Function Name": "نام تابع", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "تابع با موفقیت به\u200cروز شد", "Functions": "توابع", "Functions allow arbitrary code execution.": "توابع اجازه اجرای کد دلخواه را می\u200cدهند.", @@ -1071,7 +1163,10 @@ "Gravatar": "گراواتار", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "گروه با موفقیت ایجاد شد", "Group deleted successfully": "گروه با موفقیت حذف شد", "Group Description": "توضیحات گروه", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "بازخورد لمسی", + "Header variables": "", "Headers": "هدرها", "Headers must be a valid JSON object": "هدرها باید یک شیء JSON معتبر باشند", "Height": "ارتفاع", @@ -1113,6 +1209,8 @@ "ID": "شناسه", "ID cannot contain \":\" or \"|\" characters": "شناسه نمی\u200cتواند حاوی کاراکترهای \":\" یا \"|\" باشد", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "اجازه فرم\u200cها در سندباکس iframe", "iframe Sandbox Allow Same Origin": "اجازه منشأ یکسان در سندباکس iframe", @@ -1138,6 +1236,7 @@ "Import From Link": "وارد کردن از لینک", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "وارد کردن با موفقیت انجام شد", "Import Tools": "", "Important Update": "به\u200cروزرسانی مهم", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "نگه داشتن در نوار کناری", "Key": "کلید", "Key is required": "کلید مورد نیاز است", - "Keyboard shortcuts": "میانبرهای صفحه کلید", "Keyboard Shortcuts": "میانبرهای صفحه کلید", "Knowledge": "دانش", "Knowledge Access": "دسترسی به دانش", @@ -1208,6 +1306,8 @@ "Knowledge Name": "نام دانش", "Knowledge Public Sharing": "اشتراک\u200cگذاری عمومی دانش", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "دانش با موفقیت به\u200cروز شد", "Kokoro.js (Browser)": "Kokoro.js (مرورگر)", "Kokoro.js Dtype": "نوع داده Kokoro.js", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "آخرین پاسخ", "LDAP": "LDAP", - "LDAP server updated": "سرور LDAP به\u200cروز شد", "Leaderboard": "تابلوی امتیازات", "Learn more": "", "Learn More": "بیشتر بدانید", @@ -1246,6 +1345,7 @@ "Legacy": "قدیمی", "lexical": "لغوی", "License": "مجوز", + "Lifecycle JSON": "", "Lift List": "لیست ارتقا", "Light": "روشن", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "دسترسی به موقعیت مکانی مجاز نیست", "Lost": "گم شده", "Low": "پایین", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "ساخته شده توسط OpenWebUI Community", "Make password visible in the user interface": "رمز عبور را در رابط کاربری قابل مشاهده کنید", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "مدیریت خطوط لوله", "Manage Tool Servers": "مدیریت سرورهای ابزار", "Manage your account information.": "اطلاعات حساب خود را مدیریت کنید.", + "Mapped Source": "", "March": "مارچ", "Markdown": "مارک\u200cداون", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "حافظه با موفقیت پاک شد", "Memory deleted successfully": "حافظه با موفقیت حذف شد", "Memory updated successfully": "حافظه با موفقیت به\u200cروز شد", + "Merge Accounts by Email": "", "Merge Responses": "ادغام پاسخ\u200cها", "Merged Response": "پاسخ ادغام شده", "Message": "پیام", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "پیام های شما بعد از ایجاد لینک شما به اشتراک نمی گردد. کاربران با لینک URL می توانند چت اشتراک را مشاهده کنند.", + "Metadata Field": "", "Microsoft OneDrive": "وان\u200cدرایو مایکروسافت", "Microsoft OneDrive (personal)": "وان\u200cدرایو مایکروسافت (شخصی)", "Microsoft OneDrive (work/school)": "وان\u200cدرایو مایکروسافت (کار/مدرسه)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "کلید API MinerU برای حالت Cloud API مورد نیاز است.", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "کلید API جستجوی موجیک", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "بیشتر", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "پایگاه دانش خود را نام\u200cگذاری کنید", "Name, prompt, and model are required": "", "Native": "بومی", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "بدون احراز هویت", "No automations found": "", "No chats found": "هیچ چتی یافت نشد", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "فاصله\u200cای در دسترس نیست", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "عدم انقضا می\u200cتواند خطرات امنیتی ایجاد کند.", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "فایلی انتخاب نشده است", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "هیچ پرامپتی یافت نشد", + "No Repeat": "", "No results": "نتیجه\u200cای یافت نشد", "No results found": "نتیجه\u200cای یافت نشد", "No search query generated": "پرسوجوی جستجویی ایجاد نشده است", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "شناسه\u200cهای گره", "None": "هیچ کدام", + "Not configured": "", "Not factually correct": "اشتباهی فکری نیست", "Not helpful": "مفید نیست", "Not Registered": "ثبت نشده", @@ -1498,20 +1611,25 @@ "Notifications": "اعلان", "November": "نوامبر", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "شناسه OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "اکتبر", "Off": "خاموش", "Okay, Let's Go!": "باشه، بزن بریم!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED تیره", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "تنظیمات API ollama به\u200cروز شد", "Ollama Cloud API Key": "کلید API ابری اُلاما", "Ollama Version": "نسخه ollama", + "Omit": "", "On": "روشن", "Once": "", "OneDrive": "وان\u200cدرایو", @@ -1582,6 +1700,7 @@ "Password": "رمز عبور", "Passwords do not match.": "رمزهای عبور مطابقت ندارند.", "Paste Large Text as File": "چسباندن متن بزرگ به عنوان فایل", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF سند (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "در انتظار", "Pending": "در انتظار", + "Pending Accounts": "", "Pending User Overlay Content": "محتوای پوشش کاربر در انتظار", "Pending User Overlay Title": "عنوان پوشش کاربر در انتظار", "Permission denied when accessing media devices": "دسترسی به دستگاه\u200cهای رسانه رد شد", "Permission denied when accessing microphone": "دسترسی به میکروفون رد شد", "Permission denied when accessing microphone: {{error}}": "هنگام دسترسی به میکروفون، اجازه داده نشد: {{error}}", "Permissions": "مجوزها", + "Permissions reset to defaults": "", "Perplexity API Key": "کلید API پرپلکسیتی", "Perplexity Model": "مدل پرپلکسیتی", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "استفاده از زمینه جستجوی پرپلکسیتی", "Persistent": "", "Personalization": "شخصی سازی", + "Picture Claim": "", "Pin": "پین کردن", "Pin to Sidebar": "", "Pinned": "پین شده", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "لطفاً همه فیلدها را پر کنید.", "Please register the OAuth client": "لطفاً کلاینت OAuth را ثبت کنید", "Please save the connection to persist the OAuth client information and do not change the ID": "لطفاً اتصال را ذخیره کنید تا اطلاعات کلاینت OAuth ماندگار شود و شناسه را تغییر ندهید", - "Please select a model first.": "لطفاً ابتدا یک مدل انتخاب کنید.", "Please select a model.": "لطفاً یک مدل انتخاب کنید.", "Please select a reason": "لطفاً یک دلیل انتخاب کنید", "Please select a valid JSON file": "لطفاً یک فایل JSON معتبر انتخاب کنید", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "لطفاً منتظر بمانید تا همه فایل\u200cها آپلود شوند.", "Policy ID": "", + "Policy ID is required": "", "Port": "پورت", "Ports": "", "Positive attitude": "نظرات مثبت", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "اشتراک\u200cگذاری عمومی پرامپت\u200cها", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "عمومی", "Pull \"{{searchValue}}\" from Ollama.com": "بازگرداندن \"{{searchValue}}\" از Ollama.com", "Pull a model from Ollama.com": "دریافت یک مدل از Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "خواندن", "Read Aloud": "خواندن به صورت صوتی", "Read more →": "بیشتر بخوانید ←", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "دلیل", "Reasoning Effort": "تلاش استدلال", "Reasoning Tags": "تگ\u200cهای استدلال", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "ضبط", "Record voice": "ضبط صدا", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "در حال هدایت به OpenWebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "احتمال تولید محتوای بی\u200cمعنی را کاهش می\u200cدهد. مقدار بالاتر (مثلاً 100) پاسخ\u200cهای متنوع\u200cتری می\u200cدهد، در حالی که مقدار پایین\u200cتر (مثلاً 10) محافظه\u200cکارانه\u200cتر خواهد بود.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "به خود به عنوان \"کاربر\" اشاره کنید (مثلاً، \"کاربر در حال یادگیری اسپانیایی است\")", "Reference Chats": "چت\u200cهای مرجع", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "رد شده زمانی که باید نباشد", "Regenerate": "تولید مجدد", "Regenerate Menu": "منوی بازتولید", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "ترتیب مجدد مدل\u200cها", + "Repeat": "", "Repeats": "", "Reply": "پاسخ", "Reply in Thread": "پاسخ در رشته", "Reply to thread...": "پاسخ به رشته...", "Replying to {{NAME}}": "در حال پاسخ به {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "مورد نیاز", "Reranking Batch Size": "", "Reranking Engine": "موتور رتبه\u200cبندی مجدد", "Reranking Model": "مدل ری\u200cشناسی مجدد غیرفعال است", + "Research Knowledge": "", "Reset": "بازنشانی", "Reset All Models": "بازنشانی همه مدل\u200cها", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "بازنشانی تصویر", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "بازنشانی پوشه آپلود", "Reset Vector Storage/Knowledge": "بازنشانی ذخیره\u200cسازی برداری/دانش", "Reset view": "بازنشانی نما", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "۱ منبع بازیابی شد", "Rich Text Input for Chat": "ورودی متن غنی برای چت", "Role": "نقش", + "Roles Claim": "", "RTL": "RTL", "Run": "اجرا", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "ذخیره گزارش\u200cهای چت مستقیماً در حافظه مرورگر شما دیگر پشتیبانی نمی\u200cشود. لطفاً با کلیک بر روی دکمه زیر، چند لحظه برای دانلود و حذف گزارش های چت خود وقت بگذارید. نگران نباشید، شما به راحتی می توانید گزارش های چت خود را از طریق بکند دوباره وارد کنید", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "اسکرول هنگام تغییر شاخه", "Scroll to Top": "", "Search": "جستجو", "Search a model": "جستجوی یک مدل", + "Search actions": "", "Search all emojis": "جستجوی همه ایموجی\u200cها", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "جستجو گفتگوها", "Search Collection": "جستجوی مجموعه\u200cها", "Search Files": "", + "Search filters": "", "Search Filters": "فیلترهای جستجو", "search for archived chats": "جستجو برای چت\u200cهای بایگانی شده", "search for folders": "جستجو برای پوشه\u200cها", @@ -1812,13 +1955,16 @@ "Search Models": "جستجوی مدل\u200cها", "Search Notes": "جستجوی یادداشت\u200cها", "Search options": "گزینه\u200cهای جستجو", + "Search or add pattern": "", "Search Prompts": "جستجوی پرامپت\u200cها", "Search Result Count": "تعداد نتایج جستجو", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "جستجوی اینترنت", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "ابزارهای جستجو", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "کلید API SearchApi", "SearchApi Engine": "موتور SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "هسته", "Select": "انتخاب", "Select {{modelName}} model": "", - "Select a base model": "انتخاب یک مدل پایه", "Select a base model (e.g. llama3, gpt-4o)": "یک مدل پایه انتخاب کنید (مثلاً llama3, gpt-4o)", "Select a conversation to preview": "یک مکالمه برای پیش\u200cنمایش انتخاب کنید", "Select a engine": "انتخاب یک موتور", @@ -1872,18 +2017,25 @@ "semantic": "معنایی", "Send": "ارسال", "Send a Message": "ارسال یک پیام", + "Send events for": "", "Send message": "ارسال پیام", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "ارسال `stream_options: { include_usage: true }` در درخواست.\nارائه دهندگان پشتیبانی شده در صورت تنظیم، اطلاعات استفاده از توکن را در پاسخ برمی گردانند.", "September": "سپتامبر", "SerpApi API Key": "کلید API سرپ\u200cای\u200cپی\u200cآی", "SerpApi Engine": "موتور سرپ\u200cای\u200cپی\u200cآی", "Serper API Key": "کلید API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "کلید API سرپلی", "Serpstack API Key": "کلید API Serpstack", "Server connection failed": "", "Server connection verified": "اتصال سرور تأیید شد", + "Service Account": "", "Session": "جلسه", + "Session expired. Please sign in again.": "", "Set as default": "تنظیم به عنوان پیشفرض", "Set as Production": "", "Set embedding model": "تنظیم مدل جاسازی", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "اشتراک گذاری با OpenWebUI Community", "Share your background and interests": "پیشینه و علایق خود را به اشتراک بگذارید", + "Shared": "", "Shared Chats": "", "Shared with you": "به اشتراک گذاشته شده با شما", "Sharing Permissions": "مجوزهای اشتراک\u200cگذاری", "Show": "نمایش", - "Show \"What's New\" modal on login": "نمایش مودال \"موارد جدید\" هنگام ورود", + "Show \"What's New\" Modal on Login": "نمایش مودال \"موارد جدید\" هنگام ورود", "Show Admin Details in Account Pending Overlay": "نمایش جزئیات مدیر در پوشش حساب در انتظار", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "نمایش نوار ابزار قالب\u200cبندی", "Show image preview": "نمایش پیش\u200cنمایش تصویر", "Show Model": "نمایش مدل", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "شناسه API جستجوی سوگو", "Sougou Search API SK": "کلید SK API جستجوی سوگو", "Source": "منبع", + "Specific users or groups": "", "Speech Playback Speed": "سرعت پخش گفتار", "Speech recognition error: {{error}}": "خطای تشخیص گفتار: {{error}}", "Speech-to-Text": "گفتار به متن", @@ -1999,6 +2154,7 @@ "STT Settings": "تنظیمات تبدیل صدا به متن", "Stylized PDF Export": "خروجی گرفتن از PDF با استایل", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "سیستم", + "System events only": "", "System Instructions": "دستورالعمل\u200cهای سیستم", "System Prompt": "پرامپت سیستم", + "Table": "", "Tag": "تگ", "Tags": "برچسب\u200cها", "Tags Generation": "تولید برچسب\u200cها", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "چت موقت به صورت پیش\u200cفرض", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "تقسیم\u200cکننده متن", "Text-to-Speech": "متن به گفتار", "Text-to-Speech Engine": "موتور تبدیل متن به گفتار", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "زبان صدای ورودی. ارائه زبان ورودی در قالب ISO-639-1 (مثلاً en) دقت و تأخیر را بهبود می\u200cبخشد. برای تشخیص خودکار زبان، خالی بگذارید.", "The LDAP attribute that maps to the mail that users use to sign in.": "ویژگی LDAP که به ایمیلی که کاربران برای ورود استفاده می\u200cکنند نگاشت می\u200cشود.", "The LDAP attribute that maps to the username that users use to sign in.": "ویژگی LDAP که به نام کاربری که کاربران برای ورود استفاده می\u200cکنند نگاشت می\u200cشود.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "تابلوی امتیازات در حال حاضر در نسخه بتا است و ممکن است محاسبات رتبه\u200cبندی را با بهبود الگوریتم تنظیم کنیم.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "حداکثر اندازه فایل به مگابایت. اگر اندازه فایل از این حد بیشتر باشد، فایل آپلود نخواهد شد.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "حداکثر تعداد فایل\u200cهایی که می\u200cتوانند همزمان در چت استفاده شوند. اگر تعداد فایل\u200cها از این حد بیشتر باشد، فایل\u200cها آپلود نخواهند شد.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "قالب خروجی برای متن. می\u200cتواند 'json'، 'markdown' یا 'html' باشد. پیش\u200cفرض: 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "این یک مجوز کاربر پیش\u200cفرض است و فعال باقی خواهد ماند.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "این یک ویژگی آزمایشی است، ممکن است طبق انتظار کار نکند و در هر زمان ممکن است تغییر کند.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "این مدل به صورت عمومی در دسترس نیست. لطفاً مدل دیگری انتخاب کنید.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "این گزینه مدت زمانی را کنترل می\u200cکند که مدل پس از درخواست در حافظه بارگذاری شده باقی می\u200cماند (پیش\u200cفرض: ۵ دقیقه)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "این گزینه کنترل می\u200cکند که هنگام تازه\u200cسازی متن، چند توکن حفظ شوند. برای مثال، اگر روی 2 تنظیم شود، 2 توکن آخر متن مکالمه حفظ خواهند شد. حفظ متن می\u200cتواند به حفظ پیوستگی مکالمه کمک کند، اما ممکن است توانایی پاسخ به موضوعات جدید را کاهش دهد.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "برای کسب اطلاعات بیشتر در مورد نقاط پایانی موجود، به مستندات ما مراجعه کنید.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "برای انتخاب ابزارها در اینجا، ابتدا آنها را به فضای کاری \"ابزارها\" اضافه کنید.", - "Toast notifications for new updates": "اعلان\u200cهای پاپ\u200cآپ برای به\u200cروزرسانی\u200cهای جدید", + "Toast Notifications for New Updates": "اعلان\u200cهای پاپ\u200cآپ برای به\u200cروزرسانی\u200cهای جدید", "Today": "امروز", "Today at": "", "Today at {{LOCALIZED_TIME}}": "امروز در {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "تغییر وضعیت فعال بودن اتصال فعلی.", "Token": "توکن", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "خیلی طولانی", @@ -2184,14 +2350,19 @@ "Unpin": "برداشتن پین", "Unpin from Sidebar": "", "Unravel secrets": "کشف رازها", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "نوع فایل پشتیبانی نمی\u200cشود.", "Untagged": "بدون برچسب", "Untitled": "بدون عنوان", "Update": "به\u200cروزرسانی", "Update and Copy Link": "به روزرسانی و کپی لینک", + "Update Email": "", "Update for the latest features and improvements.": "برای آخرین ویژگی\u200cها و بهبودها به\u200cروزرسانی کنید.", + "Update Name": "", "Update password": "به روزرسانی رمزعبور", + "Update Picture": "", "Update your status": "", "Updated": "بارگذاری شد", "Updated at": "بارگذاری در", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "از '#' در ورودی پرامپت برای بارگیری و شامل کردن دانش خود استفاده کنید.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "از نقطه پایانی /v1/chat/completions به جای /v1/audio/transcriptions برای دقت بالقوه بهتر استفاده کنید.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "استفاده از API تکمیل چت", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "استفاده از LLM", "Use no proxy to fetch page contents.": "از هیچ پراکسی برای دریافت محتوای صفحه استفاده نکنید.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "از پراکسی تعیین شده توسط متغیرهای محیطی http_proxy و https_proxy برای دریافت محتوای صفحه استفاده کنید.", + "Use Web Search?": "", "user": "کاربر", "User": "کاربر", + "User Access": "", "User Activity": "", "User Groups": "گروه\u200cهای کاربری", "User location successfully retrieved.": "موقعیت مکانی کاربر با موفقیت دریافت شد.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "وب\u200cهوک\u200cهای کاربر", "Username": "نام کاربری", + "Username Claim": "", "users": "", "Users": "کاربران", "Uses DefaultAzureCredential to authenticate": "از DefaultAzureCredential برای احراز هویت استفاده می\u200cکند", @@ -2247,6 +2424,7 @@ "Valves updated": "شیرها به\u200cروزرسانی شدند", "Valves updated successfully": "شیرها با موفقیت به\u200cروزرسانی شدند", "variable": "متغیر", + "Vector Field": "", "Verify Connection": "تأیید اتصال", "Verify SSL Certificate": "تأیید گواهی SSL", "Version": "نسخه", @@ -2276,11 +2454,14 @@ "Web API": "API وب", "Web Loader Engine": "موتور بارگذاری وب", "Web Search": "جستجوی وب", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "موتور جستجوی وب", "Web Search in Chat": "جستجوی وب در گفتگو", "Web Search Query Generation": "تولید کوئری جستجوی وب", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "نشانی وب\u200cهوک", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "تنظیمات WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "دیروز", "Yesterday at {{LOCALIZED_TIME}}": "دیروز در {{LOCALIZED_TIME}}", "You": "شما", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "تمام مشارکت شما مستقیماً به توسعه\u200cدهنده افزونه می\u200cرسد؛ Open WebUI هیچ درصدی دریافت نمی\u200cکند. با این حال، پلتفرم تأمین مالی انتخاب شده ممکن است کارمزد خود را داشته باشد.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "یوتیوب", "Youtube Language": "زبان یوتیوب", diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index fba699ec4d..ceba7b4570 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -9,28 +9,36 @@ "[Today at] h:mm A": "[Tänään] h:mm A", "[Yesterday at] h:mm A": "[Eilen] h:mm A", "{{ models }}": "{{ mallit }}", - "{{COUNT}} Available Skills": "", - "{{COUNT}} Available Tools": "{{COUNT}} työkalua saatavilla", + "{{COUNT}} Available Skills": "{{COUNT}} taitoa käytettävissä", + "{{COUNT}} Available Tools": "{{COUNT}} työkalua käytettävissä", "{{COUNT}} characters": "{{COUNT}} kirjainta", "{{COUNT}} extracted lines": "{{COUNT}} poimittua riviä", "{{COUNT}} files": "{{COUNT}} tiedostoa", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "{{count}} tiedostoa on valittu. Vain uudet ja muokatut tiedostot ladataan. Poistetut tiedostot poistetaan. Hakemistorakenne peilataan. Haluatko jatkaa?_one", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "{{count}} tiedostoa on valittu. Vain uudet ja muokatut tiedostot ladataan. Poistetut tiedostot poistetaan. Hakemistorakenne peilataan. Haluatko jatkaa?_other", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} piilotettua riviä", "{{COUNT}} members": "{{COUNT}} jäsentä", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}}/{{total}} käytettävissä_one", + "{{count}} of {{total}} accessible_other": "{{count}}/{{total}} käytettävissä_other", "{{COUNT}} Replies": "{{COUNT}} vastausta", "{{COUNT}} Rows": "{{COUNT}} riviä", "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} lähdettä", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} sanaa", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} lataus peruttu", "{{modelName}} profile image": "{{modelName}} profiilikuva", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}:n keskustelut", "{{webUIName}} Backend Required": "{{webUIName}}-backend vaaditaan", "*Prompt node ID(s) are required for image generation": "Kuvan luomiseen vaaditaan kehote-solmun ID(t)", + "1 group": "", "1 hour before": "1 tunti ennen", "1 Source": "1 lähde", + "1 user": "", "10 minutes before": "10 minuuttia ennen", "15 minutes before": "15 minuuttia ennen", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Käyttöoikeuksien hallinta", "Access Grants": "Käyttöoikeudet", "Access List": "Pääsylista", + "Access prohibited": "", "Access updated": "Käyttöoikeus päivitetty", "Accessible to all users": "Käytettävissä kaikille käyttäjille", "Account": "Tili", @@ -72,6 +83,7 @@ "Activity": "Toiminta", "Add": "Lisää", "Add a model ID": "Lisää mallitunnus", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Lisää lyhyt kuvaus siitä, mitä tämä malli tekee", "Add a tag": "Lisää tagi", "Add a tag...": "Lisää tagi...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Lisää mukautettu kehote", "Add description": "Lisää kuvaus", "Add Details": "Lisää yksityiskohtia", + "Add durable context for future chats": "", "Add Files": "Lisää tiedostoja", "Add Image": "Lisää kuva", + "Add Knowledge Connection": "", "Add location": "Lisää sijainti", "Add Member": "Lisää jäsen", "Add Members": "Lisää jäseniä", @@ -100,6 +114,7 @@ "Add to favorites": "Lisää suosikkeihin", "Add User": "Lisää käyttäjä", "Add User Group": "Lisää käyttäjäryhmä", + "Add webhook": "", "Add webpage": "Lisää verkkosivu", "Add your Open Terminal URL and API key in Settings → Integrations.": "Lisää Open Terminal verkko-osoite ja API-avain Asetukset → Integraatiot", "Additional Config": "Lisäasetukset", @@ -112,7 +127,9 @@ "Admin": "Ylläpito", "Admin Contact Email": "Ylläpidon sähköposti", "Admin Panel": "Ylläpitopaneeli", + "Admin Roles": "", "Admin Settings": "Ylläpitoasetukset", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Ylläpitäjillä on pääsy kaikkiin työkaluihin koko ajan; käyttäjät tarvitsevat työkaluja mallille määritettynä työtilassa.", "Advanced": "Edistynyt", "Advanced Parameters": "Edistyneet parametrit", @@ -123,16 +140,21 @@ "All": "Kaikki", "All chats have been unarchived.": "Kaikki keskustelut poistettu arkistosta.", "All day": "Koko päivä", + "All events": "", "All models are now hidden": "Kaikki mallit ovat nyt piilotettu", "All models are now visible": "Kaikki mallit ovat nyt näkyvissä", "All models deleted successfully": "Kaikki mallit poistettu onnistuneesti", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Kokoajalta", "All Users": "Kaikki käyttäjät", + "All users and system events": "", "Allow Call": "Salli puhelut", "Allow Chat Controls": "Salli keskustelujen hallinta", "Allow Chat Delete": "Salli keskustelujen poisto", "Allow Chat Edit": "Salli keskustelujen muokkaus", "Allow Chat Export": "Salli keskustelujen vienti", + "Allow Chat Import": "", "Allow Chat Params": "Salli keskustelujen parametrit", "Allow Chat Share": "Salli keskustelujen jako", "Allow Chat System Prompt": "Salli keskustelujen järjestelmä kehotteet", @@ -152,9 +174,11 @@ "Allow User Location": "Salli käyttäjän sijainti", "Allow Voice Interruption in Call": "Salli äänen keskeytys puhelussa", "Allow Web Upload": "Salli verkko lataukset", + "Allowed Domains": "", "Allowed Endpoints": "Hyväksytyt päätepisteet", "Allowed File Extensions": "Hyväksytyt tiedostomuodot", - "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Hyväksyty tiedostomuodot. Erittele tiedostomuodot pilkulla. Jätä tyhjäksi kaikille tiedostomuodoille.", + "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Hyväksytyt tiedostomuodot. Erittele tiedostomuodot pilkulla. Jätä tyhjäksi kaikille tiedostomuodoille.", + "Allowed Roles": "", "Already have an account?": "Onko sinulla jo tili?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Vaihtoehto top_p:lle, ja sen tavoitteena on varmistaa laadun ja monimuotoisuuden tasapaino. Parametri p edustaa vähimmäistodennäköisyyttä, jonka on oltava tokenin huomioimiseksi suhteessa todennäköisimmän tokenin todennäköisyyteen. Esimerkiksi, kun p=0.05 ja todennäköisin tokenilla on todennäköisyys 0.9, logitit, joiden arvo on alle 0.045, suodatetaan pois.", "Always": "Aina", @@ -173,6 +197,7 @@ "API Base URL": "API:n verkko-osoite", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API verkko-osoite Datalabb Marker palveluun. Oletuksena: https://www.datalab.to/api/v1/marker", "API Key": "API-avain", + "API Key / Token": "", "API Key created.": "API-avain luotu.", "API Key Endpoint Restrictions": "API-avaimen päätepiste rajoitukset", "API keys": "API-avaimet", @@ -198,17 +223,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "Haluatko varmasti poistaa kaikki keskustelut? Tätä toimintoa ei voi peruuttaa.", "Are you sure you want to delete this channel?": "Haluatko varmasti poistaa tämän kanavan?", "Are you sure you want to delete this connection? This action cannot be undone.": "Haluatko varmasti poistaa yhteyden? Tätä toimintoa ei voi peruuttaa.", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "Haluatko varmasti poistaa tämän hakemiston?", "Are you sure you want to delete this memory? This action cannot be undone.": "Haluatko varmasti poistaa muiston? Tätä toimintoa ei voi peruuttaa.", "Are you sure you want to delete this message?": "Haluatko varmasti poistaa tämän viestin?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Haluatko varmasti poistaa tämän version? Alaversiot linkitetään uudelleen tämän version ylätason versioon.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Haluatko varmasti poistää tämän?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Haluatko varmasti purkaa kaikkien arkistoitujen keskustelujen arkistoinnin?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena-mallit", "Artifacts": "Artefaktit", "Asc": "Nouseva", "Ask": "Kysy", "Ask a question": "Kysy kysymys", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Avustaja", "Async Embedding Processing": "Asynkroninen upotus prosessointi", "At time of event": "Tapahtumahetkellä", @@ -223,14 +253,20 @@ "Audio": "Ääni", "August": "elokuu", "Auth": "Todennus", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Todentaa", "Authentication": "Todennus", "Auto": "Automaattinen", "Auto (Random)": "Automaattinen (satunnainen)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Kopioi vastaus automaattisesti leikepöydälle", - "Auto-playback response": "Toista vastaus automaattisesti", + "Auto-Create Groups": "", + "Auto-Playback Response": "Toista vastaus automaattisesti", "Autocomplete Generation": "Automaattisen täydennyksen luonti", "Autocomplete Generation Input Max Length": "Automaattisen täydennyksen syötteen enimmäispituus", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API:n todennusmerkkijono", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 verkko-osoite", @@ -245,9 +281,10 @@ "Automations": "Automaatiot", "Available list": "Käytettävissä oleva luettelo", "Available models": "Käytettävissä olevat mallit", - "Available Skills": "", + "Available Skills": "Käytettävissä olevat taidot", "Available Tools": "Käytettävissä olevat työkalut", "available users": "käytettävissä olevat käyttäjät", + "Available variables": "", "available!": "saatavilla!", "Away": "Poissa", "Awful": "Kauhea", @@ -258,16 +295,17 @@ "Bad Response": "Huono vastaus", "Banners": "Bannerit", "Base Model (From)": "Perusmalli (alkaen)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Malliluettelon välimuisti nopeuttaa käyttöä hakemalla mallit vain käynnistyksen yhteydessä, tai asetusten tallentamisen yhteydessä - nopeampaa, mutta ei välttämättä näytä viimeisimpiä malli muutoksia.", "Bearer": "Bearer", "before": "ennen", "Being lazy": "Oli laiska", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 -päätepisteen osoite", "Bing Search V7 Subscription Key": "Bing Search V7 -tilauskäyttäjäavain", "Bio": "Elämänkerta", "Birth Date": "Syntymäpäivä", + "Blocked Groups": "", "BM25 Weight": "BM25 paino", "Bocha Search API Key": "Bocha Search API -avain", "Bold": "Lihavointi", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "Chat-keskustelut", "Chat deleted.": "Keskustelu poistettu.", - "Chat direction": "Keskustelun suunta", + "Chat Direction": "Keskustelun suunta", "Chat exported successfully": "Keskustelut viety onnistuneesti", "Chat History": "Keskusteluhistoria", "Chat ID": "Keskustelu ID", @@ -360,13 +398,13 @@ "Click here to select": "Klikkaa tästä valitaksesi", "Click here to select a csv file.": "Klikkaa tästä valitaksesi CSV-tiedosto.", "Click here to select a py file.": "Klikkaa tästä valitaksesi py-tiedosto.", - "Click here to upload a workflow.json file.": "Klikkaa tästä ladataksesi workflow.json-tiedosto.", + "Click here to upload a workflow.json file.": "Lataa workflow.json-tiedosto klikkaamalla tätä.", "click here.": "klikkaa tästä.", "Click on the user role button to change a user's role.": "Klikkaa käyttäjän roolipainiketta vaihtaaksesi käyttäjän roolia.", "Click to connect": "Klikkaa yhdistääksesi", "Click to copy ID": "Klikkaa kopioidaksesi ID", - "Client ID": "", - "Client Secret": "", + "Client ID": "Client ID", + "Client Secret": "Client Secret", "Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Leikepöydälle kirjoitusoikeus evätty. Tarkista selaimesi asetukset ja myönnä tarvittavat käyttöoikeudet.", "Clone": "Kloonaa", "Clone Chat": "Kloonaa keskustelu", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Yhteistyökanava, johon ihmiset liittyvät jäseninä", "Collapse": "Pienennä", "Collection": "Kokoelma", + "Collection Field": "", "Collections": "Kokoelmat", "Color": "Väri", "ComfyUI": "ComfyUI", @@ -405,17 +444,19 @@ "ComfyUI Workflow": "ComfyUI-työnkulku", "ComfyUI Workflow Nodes": "ComfyUI-työnkulun solmut", "Comma separated Node Ids (e.g. 1 or 1,2)": "Pilkulla erotellut Node Id:t (esim. 1 tai 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Pilkulla eroteltu luettelo tiedostomuodoista, joita MinerU käsittelee (esim. pdf, docx, pptx, xlsx)", "command": "komento", "Command": "Komento", "Comment": "Kommentti", "Commit Message": "Vahvistusviesti", "Community Reviews": "Yhteisön arvostelut", - "Comparing with knowledge base...": "", + "Compacting context": "", + "Comparing with knowledge base...": "Vertaillaan tietokantaan...", "Completions": "Täydennykset", "Compress Images in Channels": "Pakkaa kuvat kanavissa", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Tarkistussummien laskenta ({{count}} tiedostoa)_one", + "Computing checksums ({{count}} files)_other": "Tarkistussummien laskenta ({{count}} tiedostoa)_other", "Concurrent Requests": "Samanaikaiset pyynnöt", "Config": "Määritykset", "Config imported successfully": "Määritysten tuonti onnistui", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Yhdistä Open Terminal -instansseihin. Kaikilla käyttäjillä on pääsy tiedostojen selaamiseen ja päätetyökaluihin näiden palvelimien kautta.", "Connect to your own OpenAI compatible API endpoints.": "Yhdistä omat OpenAI yhteensopivat API päätepisteet.", "Connect to your own OpenAPI compatible external tool servers.": "Yhdistä omat ulkopuoliset OpenAPI yhteensopivat työkalu palvelimet.", + "Connected": "", "Connected ({{type}})": "Yhdistetty ({{type}})", "Connection failed": "Yhteys epäonnistui", "Connection lost. Reconnecting...": "Yhteys katkaistu. Yhdistetään uudelleen...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Ota yhteyttä ylläpitäjään WebUI-käyttöä varten", "Content": "Sisältö", "Content Extraction Engine": "Sisällönpoimintamoottori", + "Content Field": "", "Content lengths (character counts only)": "Sisällön pituus (vain merkkimäärä)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Konteksti tokenit", + "Continue": "", "Continue Response": "Jatka vastausta", "Continue with {{provider}}": "Jatka palvelulla {{provider}}", "Continue with Email": "Jatka sähköpostilla", @@ -493,6 +543,7 @@ "Create new secret key": "Luo uusi salainen avain", "Create note": "Luo muistiinpano", "Create Note": "Luo muistiinpano", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Luo aikataulutettuja kehotteita, jotka suoritetaan automaattisesti toistuvasti.", "Create your first note by clicking on the plus button below.": "Luo ensimmäinen muistiinpanosi painamalla alla olevaa plus painiketta.", "Created at": "Luotu", @@ -510,6 +561,7 @@ "Custom Gender": "Muu sukupuoli", "Custom Parameter Name": "Mukautetun parametrin nimi", "Custom Parameter Value": "Mukautetun parametrin arvo", + "Custom range": "", "Daily": "Päivittäin", "Daily Messages": "Päivittäiset viestit", "Danger Zone": "Vaara-alue", @@ -532,7 +584,6 @@ "Default Features": "Oletus ominaisuudet", "Default Filters": "Oletus suodattimet", "Default Group": "Oletusryhmä", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Oletustila toimii laajemman mallivalikoiman kanssa kutsumalla työkaluja kerran ennen suorittamista. Natiivitila hyödyntää mallin sisäänrakennettuja työkalujen kutsumisominaisuuksia, mutta edellyttää, että malli tukee tätä ominaisuutta.", "Default Model": "Oletusmalli", "Default model updated": "Oletusmalli päivitetty", "Default permissions": "Oletuskäyttöoikeudet", @@ -542,20 +593,21 @@ "Default to ALL": "Oletus KAIKKI", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Segmentoitu haku on oletuksena kohdennettua ja relevanttia sisällön poimimista varten. Tätä suositellaan useimmissa tapauksissa.", "Default User Role": "Oletuskäyttäjärooli", + "Default webhook": "", "Defaults": "Oletukset", "Delete": "Poista", "Delete {{name}}": "Poista {{name}}", "Delete a model": "Poista malli", "Delete All": "Poista kaikki", "Delete All Chats": "Poista kaikki keskustelut", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Poista kaikki sisällöt tästä hakemistosta", "Delete all contents inside this folder": "Poista kaikki sisällöt tästä kansiosta", "Delete automation?": "Poista automaatio?", "Delete calendar": "Poista kalenteri", "Delete Calendar": "Poista kalenteri", "Delete Chat": "Poista keskustelu", "Delete chat?": "Haluatko varmasti poistaa tämän keskustelun?", - "Delete directory?": "", + "Delete directory?": "Poista hakemiston?", "Delete Event": "Poista tapahtuma?", "Delete File": "Poista tiedosto", "Delete folder?": "Haluatko varmasti poistaa tämän kansion?", @@ -592,16 +644,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Suorat yhteydet mahdollistavat käyttäjien yhdistää omia OpenAI-yhteensopivia API-päätepisteitä.", "Direct Message": "Suora viesti", "Direct Tool Servers": "Suorat työkalu palvelimet", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Hakemisto luotu.", + "Directory deleted.": "Hakemisto poistettu.", + "Directory moved.": "Hakemisto siirretty.", + "Directory name": "Hakemiston nimi", + "Directory renamed.": "Hakemisto uudelleennimetty.", "Directory selection was cancelled": "Hakemiston valinta keskeytettiin", "Disable All": "Poista kaikki käytöstä", "Disable Code Interpreter": "Poista Koodin suoritus käytöstä", "Disable Image Extraction": "Poista kuvien poiminta käytöstä", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Poista kuvien poiminta käytöstä PDF tiedostoista. Jos LLM on käytössä, kuvat tekstitetään automaattisesti. Oletuksena ei käytössä.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Ei käytössä", "Disconnect OAuth": "Katkaise OAuth", "Discover a function": "Löydä toiminto", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Löydä ja lataa mallien esiasetuksia", "Discussion channel where access is based on groups and permissions": "Keskustelukanava, jonka käyttöoikeus perustuu ryhmiin ja käyttöoikeuksiin", "Display": "Näytä", - "Display chat title in tab": "Näytä keskustelu otiskko välilehdessä", + "Display Chat Title in Tab": "Näytä keskustelu otiskko välilehdessä", "Display Emoji in Call": "Näytä hymiöitä puhelussa", "Display Multi-model Responses in Tabs": "Näytä usean mallin vastaukset välilehdissä", - "Display the username instead of You in the Chat": "Näytä käyttäjänimi keskustelussa \"Sinä\" -tekstin sijaan", + "Display the Username Instead of You in the Chat": "Näytä käyttäjänimi keskustelussa \"Sinä\" -tekstin sijaan", "Displays citations in the response": "Näyttää lähdeviitteet vastauksessa", "Displays status updates (e.g., web search progress) in the response": "Näyttä tilapäivityksiä (esim. verkkohaku) vastauksissa", "Dive into knowledge": "Uppoudu tietoon", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling parametrit", "Docling Server URL required.": "Docling palvelimen verkko-osoite vaaditaan.", "Document": "Asiakirja", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Document Intelligence pääte vaaditaan", "Document Intelligence Model": "Document Intelligence malli", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Muokkaa oletuskäyttöoikeuksia", "Edit Folder": "Muokkaa kansiota", "Edit Image": "Kuvan muokkaus", + "Edit Knowledge Connection": "", "Edit Last Message": "Muokkaa viimeisintä viestiä", "Edit Memory": "Muokkaa muistia", "Edit Prompt": "Muokkaa kehotetta", "Edit Terminal Connection": "Muokkaa pääteyhteyttä", "Edit User": "Muokkaa käyttäjää", "Edit User Group": "Muokkaa käyttäjäryhmää", + "Edit webhook": "", "Edit workflow.json content": "Muokkaa workflow.json sisältöä", "edited": "muokattu", "Edited": "Muokattu", @@ -699,14 +756,16 @@ "Eject model": "Irroita malli", "ElevenLabs": "ElevenLabs", "Email": "Sähköposti", + "Email Claim": "", "Embark on adventures": "Lähde seikkailuille", "Embedding": "Upotus", "Embedding Batch Size": "Upotuksen eräkoko", "Embedding Concurrent Requests": "Samanaikaiset upotuspyynnöt", "Embedding Model": "Upotusmalli", "Embedding Model Engine": "Upotusmallin moottori", - "Emoji": "", + "Emoji": "Emoji", "Emojis": "Emojit", + "Empty": "", "Empty message": "Tyhjä viesti", "Enable All": "Ota kaikki käyttöön", "Enable API Keys": "Ota API-avaimet käyttöön", @@ -714,22 +773,27 @@ "Enable Code Execution": "Ota koodin suoritus käyttöön", "Enable Code Interpreter": "Ota ohjelmatulkki käyttöön", "Enable Community Sharing": "Ota yhteisön jakaminen käyttöön", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Ota Memory Locking (mlock) käyttöön estääksesi mallidatan vaihtamisen pois RAM-muistista. Tämä lukitsee mallin työsivut RAM-muistiin, varmistaen että niitä ei vaihdeta levylle. Tämä voi parantaa suorituskykyä välttämällä sivuvikoja ja varmistamalla nopean tietojen käytön.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Ota Memory Mapping (mmap) käyttöön ladataksesi mallidataa. Tämä vaihtoehto sallii järjestelmän käyttää levytilaa RAM-laajennuksena käsittelemällä levytiedostoja kuin ne olisivat RAM-muistissa. Tämä voi parantaa mallin suorituskykyä sallimalla nopeamman tietojen käytön. Kuitenkin se ei välttämättä toimi oikein kaikissa järjestelmissä ja voi kuluttaa huomattavasti levytilaa.", "Enable Message Queue": "Ota viestijono käyttöön", "Enable Message Rating": "Ota viestiarviointi käyttöön", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Salli uudet rekisteröitymiset", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Käytä, poista käytöstä, tai kustomoi mallin päättely tageja. \"Käytä\" käyttää oletus tageja, \"Ei käytössä\" ottaa päätely tagit pois käytöstä, ja \"Mukautettu\" antaa sinun määritellä aloitus ja lopetus tagit.", "Enabled": "Käytössä", "End Tag": "Lopetus tagi", + "Endpoint": "", "Endpoint URL": "Päätepiste verkko-osoite", "Enforce Temporary Chat": "Pakota väliaikaiset keskustelut", "Enhance": "Paranna", "Enrich Hybrid Search Text": "Rikasta hybridihakutekstiä", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Varmista, että CSV-tiedostossasi on 4 saraketta tässä järjestyksessä: Nimi, Sähköposti, Salasana, Rooli.", "Enter {{role}} message here": "Kirjoita {{role}}-viesti tähän", - "Enter a detail about yourself for your LLMs to recall": "Kirjoita yksityiskohta itsestäsi, jonka LLM-ohjelmat voivat muistaa", "Enter a title for the pending user info overlay. Leave empty for default.": "Kirjoita infon otsikko odottaville käyttäjille. Käytä oletusta jättämällä tyhjäksi.", "Enter a watermark for the response. Leave empty for none.": "Kirjoita vastauksen vesileima. Jätä tyhjäksi, jos et halua mitään.", "Enter additional headers in JSON format": "Kirjoita lisä ylätunnisteita JSON muodossa", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Kirjoita osien vähimmäiskoko", "Enter Chunk Overlap": "Syötä osien päällekkäisyys", "Enter Chunk Size": "Syötä osien koko", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Syötä pilkulla erottaen \"token:bias_value\" parit (esim. 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Kirjoita odottavien käyttäjien infon tekstisisältö. Käytä oletusta jättämällä tyhjäksi.", "Enter coordinates (e.g. 51.505, -0.09)": "Kirjoita kordinaatit (esim. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Kirjoita Jupyter verkko-osoite", "Enter Kagi Search API Key": "Kirjoita Kagi Search API -avain", "Enter Key Behavior": "Enter näppäimen käyttäytyminen", + "Enter language": "", "Enter language codes": "Kirjoita kielikoodit", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Kirjoita Linkup API-avain", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Kirjoita MinerU API-avain", "Enter Mistral API Base URL": "Kirjoita Mistral API verkko-osoite", "Enter Mistral API Key": "Kirjoita Mistral API-avain", @@ -804,6 +873,7 @@ "Enter prompt here.": "Kirjoita kehote tähän.", "Enter proxy URL (e.g. https://user:password@host:port)": "Kirjoita välityspalvelimen verkko-osoite (esim. https://käyttäjä:salasana@host:portti)", "Enter reasoning effort": "Kirjoita päättelyn määrä", + "Enter Redirect URI": "", "Enter Score": "Kirjoita pistemäärä", "Enter SearchApi API Key": "Kirjoita SearchApi API -avain", "Enter SearchApi Engine": "Kirjoita SearchApi-moottori", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Kirjoita SerpApi API -avain", "Enter SerpApi Engine": "Valitse SerpApi Moottori", "Enter Serper API Key": "Kirjoita Serper API -avain", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Kirjoita Serply API -avain", "Enter Serpstack API Key": "Kirjoita Serpstack API -avain", "Enter server host": "Kirjoita palvelimen isäntänimi", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Kirjoita Tika Server URL", "Enter timeout in seconds": "Aseta aikakatkaisu sekunneissa", "Enter to Send": "Enter lähetys", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Kirjoita Top K", "Enter Top K Reranker": "Kirjoita Top K uudelleen sijoittaja", "Enter URL (e.g. http://127.0.0.1:7860/)": "Kirjoita verkko-osoite (esim. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Virhe: Malli '{{modelId}}' on jo käytössä. Valitse toinen ID jatkaaksesi.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Virhe: Mallin ID ei voi olla tyhjä. Kirjoita ID jatkaaksesi.", "Evaluations": "Arvioinnit", + "Event": "", "Event created": "Tapahtuma luotu", "Event deleted": "Tapahtuma poistettu", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Tapahtuman otsikko", "Event updated": "Tapahtuma päivitetty", + "Events": "", "Exa API Key": "Exa API -avain", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Esimerkki: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Esimerkki: KAIKKI", "Example: mail": "Esimerkki: posti", @@ -905,12 +982,18 @@ "Export Config": "Vie asetukset", "Export Models": "Vie mallit", "Export Prompts": "Vie kehotteet", + "Export Skills": "", "Export to CSV": "Vie CSV-tiedostoon", "Export Tools": "Vie työkalut", "Export Users": "Vie käyttäjät", "External": "Ulkoiset", + "External connection not found.": "", "External Document Loader URL required.": "Ulkoisen Document Loader:n verkko-osoite on vaaditaan.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Ulkoinen työmalli", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Ulkoinen Web Loader API-avain", "External Web Loader URL": "Ulkoinen Web Loader verkko-osoite", "External Web Search API Key": "Ulkoinen Web Search API-avain", @@ -921,13 +1004,14 @@ "Failed to archive chat.": "Keskustelun arkistointi epäonnistui.", "Failed to attach file": "Tiedoston liittäminen epäonnistui", "Failed to clear status": "Tilan tyhjentäminen epäonnistui", - "Failed to compare files.": "", + "Failed to compare files.": "Tiedostojen vertaaminen epäonnistui.", "Failed to connect to {{URL}} OpenAPI tool server": "Yhdistäminen {{URL}} OpenAPI työkalu palvelimeen epäonnistui", "Failed to connect to {{URL}} terminal server": "Yhdistäminen {{URL}} päätepalvelimeen epäonnistui", "Failed to copy link": "Linkin kopiointi epäonnistui", "Failed to create API Key.": "API-avaimen luonti epäonnistui.", "Failed to delete calendar": "Kalenterin poistaminen epäonnistui", "Failed to delete note": "Muistiinpanon poistaminen epäonnistui", + "Failed to delete webhook": "", "Failed to disconnect": "Yhteyden katkaiseminen epäonnistui", "Failed to download image": "Kuvan lataaminen epäonnistui", "Failed to extract content from the file: {{error}}": "Tiedoston sisällön pomiminen epäonnistui: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Mallien hakeminen epäonnistui", "Failed to generate title": "Otsikon luonti epäonnistui", "Failed to import models": "Mallien tuonti epäonnistui", + "Failed to load chat": "", "Failed to load chat preview": "Keskustelun esikatselun lataaminen epäonnistui", "Failed to load DOCX file. Please try downloading it instead.": "DOCX-tiedoston avaaminen epäonnistui. Yritä ladata se sen sijaan.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV tiedoston lataaminen epäonnistui. Yritä ladata se sen sijaan.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Keskustelun siirto epäonnistui", "Failed to process URL: {{url}}": "Verkko-osoitteen käsittely epäonnistui: {{url}}", "Failed to read clipboard contents": "Leikepöydän sisällön lukeminen epäonnistui", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Jäsenen poistaminen epäonnistui", "Failed to render diagram": "Diagrammin renderöinti epäonnistui", "Failed to render visualization": "Visualisoinnin renderöinti epäonnistui", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Mallien määrityksen tallentaminen epäonnistui", "Failed to save policy: {{error}}": "Käytännön tallentaminen epäonnistui: {{error}}", "Failed to save terminal servers": "Päätepalvelimien tallennus epäonnistui", + "Failed to save webhook": "", "Failed to unshare chat.": "Jaon lopettaminen epäonnistui.", "Failed to update settings": "Asetusten päivittäminen epäonnistui", "Failed to update status": "Tilan päivittäminen epäonnistui", + "Failed to update webhook": "", "Failed to upload file.": "Tiedoston lataaminen epäonnistui.", "Features": "Ominaisuudet", "Features Permissions": "Ominaisuuksien käyttöoikeudet", @@ -975,18 +1063,20 @@ "File content updated successfully.": "Tiedoston sisältö päivitetty onnistuneesti.", "File Context": "Tiedoston konteksti", "File deleted successfully.": "Tiedosto poistettiin onnistuneesti.", - "File Extensions": "", + "File Extensions": "Tiedostomuodot", "File Mode": "Tiedostotila", - "File moved.": "", + "File moved.": "Tiedosto siirretty.", "File name": "Tiedostonimi", "File not found.": "Tiedostoa ei löytynyt.", "File removed successfully.": "Tiedosto poistettu onnistuneesti.", - "File renamed.": "", + "File renamed.": "Tiedosto uudelleennimetty.", "File size should not exceed {{maxSize}} MB.": "Tiedoston koko ei saa ylittää {{maxSize}} MB.", "File Upload": "Tiedoston lataus", "File uploaded successfully": "Tiedosto ladattiin onnistuneesti", "Filename": "Tiedostonimi", "Files": "Tiedostot", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Suodata", "Filter is now globally disabled": "Suodatin on nyt poistettu käytöstä globaalisti", "Filter is now globally enabled": "Suodatin on nyt otettu käyttöön globaalisti", @@ -1009,6 +1099,7 @@ "Folder options": "Kansion asetukset", "Folder updated successfully": "Kansio päivitettiin onnistuneesti", "Folders": "Kansiot", + "Folders Sharing": "", "Follow up": "Jatkokysymykset", "Follow Up Generation": "Jatkokysymysten luonti", "Follow Up Generation Prompt": "Jatkokysymysten luonti kehote", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Toiminto on nyt otettu käyttöön globaalisti", "Function Name": "Toiminnon nimi", "Function Name Filter List": "Toiminnon nimi Suodatinluettelo", + "Function starter": "", "Function updated successfully": "Toiminto päivitetty onnistuneesti", "Functions": "Toiminnot", "Functions allow arbitrary code execution.": "Toiminnot sallivat mielivaltaisen koodin suorittamisen.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Ruudukko", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "Ryhmäkanava", + "Group Claim": "", "Group created successfully": "Ryhmä luotu onnistuneesti", "Group deleted successfully": "Ryhmä poistettu onnistuneesti", "Group Description": "Ryhmän kuvaus", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptinen palaute", + "Header variables": "", "Headers": "Ylätunnisteet", "Headers must be a valid JSON object": "Ylätunnisteet täytyy olla kelvollisia JSON-objekteja", "Height": "Korkeus", @@ -1113,6 +1209,8 @@ "ID": "Tunnus", "ID cannot contain \":\" or \"|\" characters": "ID ei voi sisältää \":\" tai \"|\" kirjaimia", "ID copied to clipboard": "ID kopioitu leikepöydälle", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Aikakatkaisu", "iframe Sandbox Allow Forms": "Salli lomakkeet iframe hiekkalaatikossa", "iframe Sandbox Allow Same Origin": "Salli iframe hiekkalaatikko samasta alkuperästä", @@ -1138,6 +1236,7 @@ "Import From Link": "Tuo verkko-osoitteesta", "Import Models": "Tuo mallit", "Import Prompts": "Tuo kehotteet", + "Import Skills": "", "Import successful": "Tuonti onnistui", "Import Tools": "Tuo työkalut", "Important Update": "Tärkeä päivitys", @@ -1195,12 +1294,11 @@ "Keep in Sidebar": "Pidä sivupalkissa", "Key": "Avain", "Key is required": "Avain vaaditaan", - "Keyboard shortcuts": "Pikanäppäimet", "Keyboard Shortcuts": "Pikanäppäimet", "Knowledge": "Tietämys", "Knowledge Access": "Tiedon käyttöoikeus", "Knowledge Base": "Tietokanta", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "Tietokanta on nollattu", "Knowledge created successfully.": "Tietokanta luotu onnistuneesti.", "Knowledge deleted successfully.": "Tietokanta poistettu onnistuneesti.", "Knowledge Description": "Tietokannan kuvaus", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Tietokannan nimi", "Knowledge Public Sharing": "Tietokannan julkinen jakaminen", "Knowledge Sharing": "Tietokannan jakaminen", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Tietokanta päivitetty onnistuneesti", "Kokoro.js (Browser)": "Kokoro.js (selain)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Viimeksi suoritettu", "Last reply": "Viimeksi vastattu", "LDAP": "LDAP", - "LDAP server updated": "LDAP-palvelin päivitetty", "Leaderboard": "Tulosluettelo", "Learn more": "Lue lisää", "Learn More": "Lue lisää", @@ -1246,11 +1345,12 @@ "Legacy": "Legacy", "lexical": "leksikaalinen", "License": "Lisenssi", + "Lifecycle JSON": "", "Lift List": "Nostolista", "Light": "Vaalea", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Rajoita samanaikaisia hakukyselyitä. 0 = rajoittamaton (oletus). Aseta arvoon 1 peräkkäistä suoritusta varten (suositellaan API-rajapinnoille, joilla on tiukat nopeusrajoitukset, kuten Brave-ilmaistaso).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Rajoittaa samanaikaisten upotuspyyntöjen määrää. Arvolla 0 ei rajoituksia.", - "Linkup API Key": "", + "Linkup API Key": "Linkup API-avain", "List": "Lista", "List calendars, search, create, update, and delete calendar events": "Listaa kalenterit, hae, luo, päivitä ja poista kalenteritapahtumia", "Listening...": "Kuuntelee...", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Ei pääsyä sijaintitietoihin", "Lost": "Mennyt", "Low": "Matala", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Tehnyt OpenWebUI-yhteisö", "Make password visible in the user interface": "Näytä salasana käyttöliittymässä", @@ -1285,11 +1386,12 @@ "Manage Pipelines": "Hallitse putkia", "Manage Tool Servers": "Hallitse työkalu palvelimia", "Manage your account information.": "Hallitse tilitietojasi", + "Mapped Source": "", "March": "maaliskuu", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown-otsikkotekstin jakaja", "Max Speakers": "Puhujien enimmäismäärä", - "Max tokens to retrieve (1024-32768, default 8192)": "", + "Max tokens to retrieve (1024-32768, default 8192)": "Haettavien tokenien enimmäismäärä (1024–32768, oletus 8192)", "Max Upload Count": "Latausten enimmäismäärä", "Max Upload Size": "Latausten enimmäiskoko", "Maximum characters to return from fetched URLs. Leave empty for no limit.": "Maksimimerkkimäärä haetuista URL-osoitteista. Jätä tyhjäksi, jos et halua rajoitusta.", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Muisti tyhjennetty onnistuneesti", "Memory deleted successfully": "Muisti poistettu onnistuneesti", "Memory updated successfully": "Muisti päivitetty onnistuneesti", + "Merge Accounts by Email": "", "Merge Responses": "Yhdistä vastaukset", "Merged Response": "Yhdistetty vastaus", "Message": "Viesti", @@ -1322,9 +1425,12 @@ "messages": "viestit", "Messages": "Viestit", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Linkin luomisen jälkeen lähettämäsi viestit eivät ole jaettuja. Käyttäjät, joilla on verkko-osoite, voivat tarkastella jaettua keskustelua.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API-avain vaaditaan pilvi API:ssa", @@ -1377,6 +1483,7 @@ "Models Sharing": "Mallien jako", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search API -avain", + "Monday – Friday": "", "Month": "Kuukausi", "Monthly": "Kuukausittain", "More": "Lisää", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Anna tietokannalle nimi", "Name, prompt, and model are required": "Nimi, kehote ja malli ovat pakollisia", "Native": "Natiivi", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Ei koskaan", "New": "Uusi", "New Automation": "Uusi automaatio", @@ -1401,8 +1509,8 @@ "New calendar": "Uusi kalenteri", "New Calendar": "Uusi kalenteri", "New Chat": "Uusi keskustelu", - "New directory": "", - "New Directory": "", + "New directory": "Uusi hakemisto", + "New Directory": "Uusi hakemisto", "New Event": "Uusi tapahtuma", "New File": "Uusi tiedosto", "New Folder": "Uusi kansio", @@ -1423,6 +1531,7 @@ "Next run": "Seuraava suoritus", "No access grants. Private to you.": "Ei käyttöoikeuksia. Yksityinen sinulle.", "No activity data": "Ei aktiivisuustietoja", + "No additional headers are sent unless configured.": "", "No authentication": "Ei todennusta", "No automations found": "Automaatioita ei löytynyt", "No chats found": "Keskuteluja ei löytynyt", @@ -1435,8 +1544,10 @@ "No data": "Ei dataa", "No data found": "Dataa ei löytynyt", "No distance available": "Etäisyyttä ei saatavilla", + "No event webhooks configured.": "", "No execution logs available yet": "Suorituslokeja ei saatavilla", "No expiration can pose security risks.": "Vanhenemisen laittamatta jättäminen voi altistaa tietoturvariskeille.", + "No external knowledge sources configured.": "", "No feedback found": "Ei palautetta", "No file selected": "Tiedostoa ei ole valittu", "No files found": "Tiedostoja ei löytynyt", @@ -1448,13 +1559,13 @@ "No HTML, CSS, or JavaScript content found.": "HTML-, CSS- tai JavaScript-sisältöä ei löytynyt.", "No inference engine with management support found": "", "No kernel": "Ei kerneliä", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "Tietokantoihin ei ole käyttöoikeutta.", "No knowledge bases found.": "Tietokantoja ei löytynyt.", "No knowledge found": "Tietoa ei löytynyt", "No limit": "Ei rajoituksia", "No memories to clear": "Ei muistia tyhjennettäväksi", "No model IDs": "Ei mallitunnuksia", - "No models accessible": "", + "No models accessible": "Malleihin ei ole käyttöoikeutta.", "No models available": "Malleja ei saatavilla", "No models found": "Malleja ei löytynyt", "No models selected": "Malleja ei ole valittu", @@ -1464,6 +1575,7 @@ "No output items": "Ei tulosteita", "No pinned messages": "Ei kiinnitettyjä viestejä", "No prompts found": "Kehotteita ei löytynyt", + "No Repeat": "", "No results": "Ei tuloksia", "No results found": "Ei tuloksia", "No search query generated": "Hakukyselyä ei luotu", @@ -1475,7 +1587,7 @@ "No Terminal connection configured.": "Ei pääteyhteyttä määritettynä.", "No terminal connections configured.": "Ei pääteyhteyksiä määritettynä.", "No tool server connections configured.": "Työkalupalvelinyhteyksiä ei ole määritetty.", - "No tools accessible": "", + "No tools accessible": "Työkaluihin ei ole käyttöoikeutta.", "No tools found": "Työkaluja ei löytynyt", "No users were found.": "Käyttäjiä ei löytynyt.", "No valves": "Ei venttiileitä", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Ei vielä webhookeja", "Node Ids": "Node id:t", "None": "Ei mikään", + "Not configured": "", "Not factually correct": "Ei faktuaalisesti oikein", "Not helpful": "Ei hyödyllinen", "Not Registered": "Ei kirjautunut", @@ -1498,24 +1611,29 @@ "Notifications": "Ilmoitukset", "November": "marraskuu", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Staattinen)", "OAuth ID": "OAuth-tunnus", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "OAuth palvelimen verkko-osoite", "OAuth session disconnected": "OAuth-istunto katkaistu", "October": "lokakuu", "Off": "Ei käytössä", "Okay, Let's Go!": "Okei, mennään!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED-tumma", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API -asetukset päivitetty", "Ollama Cloud API Key": "Ollama Cloud API avain", "Ollama Version": "Ollama-versio", + "Omit": "", "On": "Käytössä", "Once": "Kerran", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Aktiivinen vain Puhetilassa.", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Aktiivinen vain, kun \"Liitä suuri teksti tiedostona\" -asetus on käytössä.", "Only active when the chat input is in focus and an LLM is generating a response.": "Aktiivinen vain, kun tekstikenttä on kohdistettuna ja LLM luo vastausta.", "Only active when the chat input is in focus.": "Aktiivinen vain, kun tekstikenttä on valittuna.", @@ -1582,6 +1700,7 @@ "Password": "Salasana", "Passwords do not match.": "Salasanat eivät täsmää", "Paste Large Text as File": "Liitä suuri teksti tiedostona", + "Path": "", "Path copied": "Polku kopioitu", "Paused": "Keskeytetty", "PDF document (.pdf)": "PDF-asiakirja (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "odottaa", "Pending": "Odottaa", + "Pending Accounts": "", "Pending User Overlay Content": "Odottavien käyttäjien sisältö", "Pending User Overlay Title": "Odottavien käyttäjien otsikko", "Permission denied when accessing media devices": "Käyttöoikeus evätty media-laitteille", "Permission denied when accessing microphone": "Käyttöoikeus evätty mikrofonille", "Permission denied when accessing microphone: {{error}}": "Käyttöoikeus evätty mikrofonille: {{error}}", "Permissions": "Käyttöoikeudet", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API-avain", "Perplexity Model": "Perplexity malli", "Perplexity Search API URL": "Perplexity Search API verkko-osoite", "Perplexity Search Context Usage": "Perplexity Search kontekstin käyttö", "Persistent": "Pysyvä", "Personalization": "Personointi", + "Picture Claim": "", "Pin": "Kiinnitä", "Pin to Sidebar": "Kiinnitä sivupalkkiin", "Pinned": "Kiinnitetty", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Täytä kaikki kentät.", "Please register the OAuth client": "Rekisteröi OAuth asiakasohjelma", "Please save the connection to persist the OAuth client information and do not change the ID": "Tallenna yhteys, jotta OAuth-asiakastiedot säilyvät, äläkä muuta tunnusta.", - "Please select a model first.": "Valitse ensin malli.", "Please select a model.": "Valitse malli.", "Please select a reason": "Valitse syy", "Please select a valid JSON file": "Valitse kelvollinen JSON-tiedosto", "Please select at least one user for Direct Message channel.": "Valitse vähintään yksi käyttäjä suoraviestikanavalle.", "Please wait until all files are uploaded.": "Odota kunnes kaikki tiedostot ovat ladattu.", "Policy ID": "Käytännön ID", + "Policy ID is required": "", "Port": "Portti", "Ports": "Portit", "Positive attitude": "Positiivinen asenne", @@ -1649,7 +1771,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "Etuliite-ID:tä käytetään välttämään ristiriidat muiden yhteyksien kanssa lisäämällä etuliite mallitunnuksiin - jätä tyhjäksi, jos haluat ottaa sen pois käytöstä", "Prevent File Creation": "Estä tiedostojen luonti", "Preview": "Esikatselu", - "Preview Access": "", + "Preview Access": "Esikatsele käyttöoikeuksia", "Previous 30 days": "Edelliset 30 päivää", "Previous 7 days": "Edelliset 7 päivää", "Previous message": "Edellinen viesti", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Kehotteiden julkinen jakaminen", "Prompts Sharing": "Kehotteiden jako", "Provider": "Palveluntarjoaja", + "Provider Name": "", + "Provider URL": "", "Public": "Julkinen", "Pull \"{{searchValue}}\" from Ollama.com": "Lataa \"{{searchValue}}\" Ollama.comista", "Pull a model from Ollama.com": "Lataa malli Ollama.comista", @@ -1687,21 +1811,29 @@ "Read": "Lue", "Read Aloud": "Lue ääneen", "Read more →": "Lue lisää →", + "Read only": "", "Read Only": "Vain luku", "Read-Only Access": "Vain lukuoikeus", "Reason": "Päättely", "Reasoning Effort": "Päättelyn määrä", "Reasoning Tags": "Päättely tagit", "Reasoning text...": "Päättely teksti...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Viimeeksi käytetty", "Reconnected": "Yhdistetty", "Record": "Nauhoita", "Record voice": "Nauhoita ääntä", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Ohjataan sinut OpenWebUI-yhteisöön", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Vähentää hölynpölyn tuottamisen todennäköisyyttä. Korkeampi arvo (esim. 100) antaa monipuolisempia vastauksia, kun taas matalampi arvo (esim. 10) on varovaisempi.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Viittaa itseen \"Käyttäjänä\" (esim. \"Käyttäjä opiskelee espanjaa\")", "Reference Chats": "Liitä keskustelu", "Refresh": "Päivitä", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Kieltäytyi, vaikka ei olisi pitänyt", "Regenerate": "Regeneroi", "Regenerate Menu": "Regenerointi ikkuna", @@ -1727,27 +1859,34 @@ "Remove from favorites": "Poista suosikeista", "Remove image": "Poista kuva", "Remove Model": "Poista malli", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "Poistetaan {{count}} vanhentunutta tiedostoa..._one", + "Removing {{count}} stale files..._other": "Poistetaan {{count}} vanhentuneita tiedostoja..._other", "Rename": "Nimeä uudelleen", "Renamed to {{name}}": "Nimetty uudelleen {{name}}", "Render Markdown in Assistant Messages": "Renderöi Markdown avustajan viesteissä", "Render Markdown in Previews": "Renderöi Markdown esikatseluissa", "Render Markdown in User Messages": "Renderöi Markdown käyttäjän viesteissä", "Reorder Models": "Uudelleenjärjestä malleja", + "Repeat": "", "Repeats": "Toistot", "Reply": "Vastaa", "Reply in Thread": "Vastaa ketjussa", "Reply to thread...": "Vastaa ketjussa...", "Replying to {{NAME}}": "Vastaa {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "vaaditaan", - "Reranking Batch Size": "", + "Reranking Batch Size": "Uudelleenpisteytyksen eräkoko", "Reranking Engine": "Uudelleenpisteytymismallin moottori", "Reranking Model": "Uudelleenpisteytymismalli", + "Research Knowledge": "", "Reset": "Palauta", "Reset All Models": "Palauta kaikki mallit", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Palauta kuva", - "Reset knowledge base?": "", + "Reset knowledge base?": "Nollataanko tietokanta?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Palauta latauspolku", "Reset Vector Storage/Knowledge": "Tyhjennä vektoritallennukset/tietämys", "Reset view": "Palauta näkymä", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 lähde noudettu", "Rich Text Input for Chat": "Rikasteksti-kenttä chattiin", "Role": "Rooli", + "Roles Claim": "", "RTL": "RTL", "Run": "Suorita", "Run All": "Suorita kaikki", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Keskustelulokien tallentaminen suoraan selaimen tallennustilaan ei ole enää tuettu. Lataa ja poista keskustelulokit napsauttamalla alla olevaa painiketta. Älä huoli, voit helposti tuoda keskustelulokit takaisin backendiin", "Schedule": "Aikataulu", "Scheduled time must be in the future": "Aikataulutetun ajan on oltava tulevaisuudessa", + "Scopes": "", "Scroll On Branch Change": "Vieritä haaran vaihtoon", "Scroll to Top": "Vieritä ylös", "Search": "Haku", "Search a model": "Hae mallia", + "Search actions": "", "Search all emojis": "Hae emojeista", "Search and manage user memories": "Hae ja hallinnoi käyttäjien muistoja", "Search and view user chat history": "Hae ja tarkastele käyttäjän keskusteluhistoriaa", @@ -1798,6 +1940,7 @@ "Search Chats": "Hae keskusteluja", "Search Collection": "Hae kokoelmaa", "Search Files": "Hae tiedostoja", + "Search filters": "", "Search Filters": "Hakusuodattimet", "search for archived chats": "Hae arkistoiduista keskusteluista", "search for folders": "Hae kansioista", @@ -1812,13 +1955,16 @@ "Search Models": "Hae malleja", "Search Notes": "Hae muistiinpanoista", "Search options": "Hakuvaihtoehdot", + "Search or add pattern": "", "Search Prompts": "Hae kehotteita", "Search Result Count": "Hakutulosten määrä", + "Search skills": "", "Search Skills": "Etsi taitoja", - "Search skills...": "", "Search the internet": "Hae verkosta", "Search the web and fetch URLs": "Hae verkosta ja hae URL-osoitteita", + "Search tools": "", "Search Tools": "Hae työkaluja", + "Search users or groups": "", "Search, view, and manage user notes": "Hae, tarkastele ja hallinnoi käyttäjämuistiinpanoja", "SearchApi API Key": "SearchApi API -avain", "SearchApi Engine": "SearchApi-moottori", @@ -1834,7 +1980,6 @@ "Seed": "Siemenluku", "Select": "Valitse", "Select {{modelName}} model": "Valitse {{modelName}} malli", - "Select a base model": "Valitse perusmalli", "Select a base model (e.g. llama3, gpt-4o)": "Valitse perusmalli (esim. llama3, gtp-4o)", "Select a conversation to preview": "Valitse keskustelun esikatselu", "Select a engine": "Valitse moottori", @@ -1872,18 +2017,25 @@ "semantic": "Semaattinen", "Send": "Lähetä", "Send a Message": "Lähetä viesti", + "Send events for": "", "Send message": "Lähetä viesti", "Send now": "Lähetä nyt", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Lähettää `stream_options: { include_usage: true }` pyynnössä.\nTuetut tarjoajat palauttavat tokenkäyttötiedot vastauksessa, kun se on asetettu.", "September": "syyskuu", "SerpApi API Key": "SerpApi API -avain", "SerpApi Engine": "SerpApi moottori", "Serper API Key": "Serper API -avain", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API -avain", "Serpstack API Key": "Serpstack API -avain", "Server connection failed": "Palvelinyhteys epäonnistui", "Server connection verified": "Palvelinyhteys vahvistettu", + "Service Account": "", "Session": "Istunto", + "Session expired. Please sign in again.": "", "Set as default": "Aseta oletukseksi", "Set as Production": "Aseta tuotantokäyttöön", "Set embedding model": "Aseta upotelmamalli", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Jakolinkki kopioitu leikepöydälle.", "Share to Open WebUI Community": "Jaa OpenWebUI-yhteisöön", "Share your background and interests": "Jaa taustasi ja kiinnostuksen kohteesi", + "Shared": "", "Shared Chats": "Jaetut keskustelut", "Shared with you": "Jaettu kanssasi", "Sharing Permissions": "Jako oikeudet", "Show": "Näytä", - "Show \"What's New\" modal on login": "Näytä \"Mitä uutta\" -modaali kirjautumisen yhteydessä", + "Show \"What's New\" Modal on Login": "Näytä \"Mitä uutta\" -modaali kirjautumisen yhteydessä", "Show Admin Details in Account Pending Overlay": "Näytä ylläpitäjän tiedot odottavan tilin päällä", "Show All": "Näytä kaikki", "Show all ({{COUNT}} characters)": "Näytä kaikki ({{COUNT}} merkkiä)", "Show Files": "Näytä tiedostot", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Näytä muotoilupalkki", "Show image preview": "Näytä kuvan esikatselu", "Show Model": "Näytä malli", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Lähde", + "Specific users or groups": "", "Speech Playback Speed": "Puhetoiston nopeus", "Speech recognition error: {{error}}": "Puheentunnistusvirhe: {{error}}", "Speech-to-Text": "Puheentunnistus", @@ -1999,6 +2154,7 @@ "STT Settings": "Puheentunnistuksen asetukset", "Stylized PDF Export": "Muotoiltun PDF-vienti", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "Lähetä kysymys", "Submit suggestion": "Lähetä ehdotus", "Subtitle": "Alaotsikko", @@ -2013,18 +2169,20 @@ "Switch to JSON editor": "Vaihda JSON-editoriin", "Switch to visual editor": "Vaihda visuaaliseen editoriin", "Sync": "Synkronoi", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Synkronoi paikallinen hakemisto tämän tietokannan kanssa. Vain uudet ja muokatut tiedostot ladataan. Hakemistorakenne peilataan.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Synkronointi valmis: {{added}} lisättyä, {{modified}} muokattua, {{deleted}} poistettua, {{unmodified}} muuttumatonta", "Sync Complete!": "Synkronointi valmis!", - "Sync directory": "Synkronoitu hakemisto", + "Sync directory": "Sykronoi hakemisto", "Sync Failed": "Synkronointi epäonnistui", "Sync Usage Stats": "Synkronoinnin käyttötilastot", "Syncing stats...": "Synkronoidaan tilastoja...", "Syncing...": "Synkronoidaan...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synkronoi vain keskustelut, joihin on tehty päivityksiä viimeisen synkronoinnin aikaleiman jälkeen. Poista käytöstä synkronoidaksesi kaikki keskustelut uudelleen.", "System": "Järjestelmä", + "System events only": "", "System Instructions": "Järjestelmäohjeet", "System Prompt": "Järjestelmäkehote", + "Table": "", "Tag": "Tagi", "Tags": "Tagit", "Tags Generation": "Tagien luonti", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Väliaikainen keskustelu oletuksena", "Terminal": "Pääte", "Terminal servers saved": "Päätepalvelimet tallennettu", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Tekstin jakaja", "Text-to-Speech": "Puhesynteesi", "Text-to-Speech Engine": "Puhesynteesimoottori", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Syöteäänen kieli. Syöttökielen antaminen ISO-639-1-muodossa (esim. en) parantaa tarkkuutta ja viivettä. Jätä tyhjäksi, jos haluat kielen automaattisen tunnistuksen.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP-määrite, joka yhdistää käyttäjien kirjautumiseen käyttämään sähköpostiin.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP-määrite, joka vastaa käyttäjien kirjautumiskäyttäjänimeä.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Tulosluettelo on tällä hetkellä beta-vaiheessa, ja voimme säätää pisteytyksen laskentaa hienostaessamme algoritmia.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Enimmäistiedostokoko megatavuissa. Jos tiedoston koko ylittää tämän rajan, tiedostoa ei ladata.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Suurin sallittu tiedostojen määrä käytettäväksi kerralla chatissa. Jos tiedostojen määrä ylittää tämän rajan, niitä ei ladata.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Tekstin tulostusmuoto. Voi olla 'json', 'markdown' tai 'html'. Oletusarvo on 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Tämä kansio on tyhjä", "This is a default user permission and will remain enabled.": "Tämä on oletusarvoinen käyttäjäoikeus ja pysyy käytössä.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Tämä on kokeellinen ominaisuus, se ei välttämättä toimi odotetulla tavalla ja se voi muuttua milloin tahansa.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Tämä malli ei ole julkisesti saatavilla. Valitse toinen malli.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Tämä asetus määrittää kuinka kauan malli pysyy ladattuna muistissa pyynnön jälkeen (oletusarvo: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Tämä asetus määrittää, kuinka monta tokenia säilytetään kontekstia päivitettäessä. Jos arvoksi on asetettu esimerkiksi 2, keskustelukontekstin kaksi viimeistä tokenia säilytetään. Kontekstin säilyttäminen voi auttaa ylläpitämään keskustelun jatkuvuutta, mutta se voi heikentää kykyä vastata uusiin aiheisiin.", @@ -2094,7 +2258,7 @@ "This will delete all models including custom models": "Tämä poistaa kaikki mallit mukaan lukien mukautetut mallit", "This will delete all models including custom models and cannot be undone.": "Tämä poistaa kaikki mallit, mukaan lukien mukautetut mallit, eikä sitä voi peruuttaa.", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Tämä poistaa pysyvästi kalenterin \"{{name}}\" ja kaikki sen tapahtumat. Tätä toimintoa ei voi peruuttaa.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Tämä poistaa kaikki tiedostot ja hakemistot tästä tietokannasta. Tätä toimintoa ei voi peruuttaa.", "Thorough explanation": "Perusteellinen selitys", "Thought": "Ajatus", "Thought for {{DURATION}}": "Ajatteli {{DURATION}}", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Jos haluat lisätietoja käytettävissä olevista päätepisteistä, tutustu dokumentaatioomme.", "To select skills here, add them to the \"Skills\" workspace first.": "Jos haluat valita taitoja tässä, lisää ne ensin \"Taidot\"-työtilaan.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Valitaksesi työkalusettejä tässä, lisää ne ensin \"Työkalut\"-työtilaan.", - "Toast notifications for new updates": "Ilmoituspopuppien näyttäminen uusista päivityksistä", + "Toast Notifications for New Updates": "Ilmoituspopuppien näyttäminen uusista päivityksistä", "Today": "Tänään", "Today at": "Tänään", "Today at {{LOCALIZED_TIME}}": "Tänään {{LOCALIZED_TIME}}", @@ -2130,12 +2294,14 @@ "Toggle 1 source": "Näytä/piilota 1 lähde", "Toggle details": "Näytä/piilota yksityiskohdat", "Toggle Dictation": "Sanelu päälle/pois", - "Toggle Mute": "", + "Toggle Mute": "Mykistys päälle/pois", "Toggle Sidebar": "Näytä/piilota sivupalkki", "Toggle status history": "Näytä/piilota tilahistoria", "Toggle whether current connection is active.": "Vaihda, onko nykyinen yhteys aktiivinen", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Tokenmäärät ovat arvioita eivätkä välttämättä vastaa todellista API-käyttöä", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokenit", "Tokens": "Tokenit", "Too verbose": "Liian puhelias", @@ -2184,20 +2350,25 @@ "Unpin": "Irrota kiinnitys", "Unpin from Sidebar": "Irrota sivupalkista", "Unravel secrets": "Avaa salaisuuksia", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Lopeta keskustelun jakaminen", "Unsupported file type.": "Ei tuettu tiedostotyyppi", "Untagged": "Ei tageja", "Untitled": "Nimetön", "Update": "Päivitä", "Update and Copy Link": "Päivitä ja kopioi linkki", + "Update Email": "", "Update for the latest features and improvements.": "Päivitä uusimpiin ominaisuuksiin ja parannuksiin.", + "Update Name": "", "Update password": "Päivitä salasana", + "Update Picture": "", "Update your status": "Päivitä tilasi", "Updated": "Päivitetty", "Updated at": "Päivitetty", "Updated At": "Päivitetty", "Upgrade to a licensed plan for enhanced capabilities, including custom theming and branding, and dedicated support.": "Päivitä lisenssi saadaksesi parempia ominaisuuksia, mukaan lukien mukautetun teeman ja brändäyksen sekä yksilöllistä tukea.", - "Upload": "Lataa", + "Upload": "Lähetä", "Upload a GGUF model": "Lataa GGUF-malli", "Upload Audio": "Lataa äänitiedosto", "Upload directory": "Lataa hakemisto", @@ -2209,7 +2380,7 @@ "Upload Progress": "Latauksen edistyminen", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Latauksen edistyminen: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Ladatut tiedostot tai kuvat", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploading {{current}}/{{total}}: {{file}}": "Ladataan {{current}}/{{total}}: {{file}}", "Uploading...": "Ladataan...", "URL": "URL", "URL is required": "URL vaaditaan", @@ -2218,22 +2389,28 @@ "Use": "Käytä", "Use '#' in the prompt input to load and include your knowledge.": "Käytä '#' -merkkiä kehotekenttään ladataksesi ja sisällyttääksesi tietämystäsi.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Käytä /v1/chat/completions-päätteitä/v1/audio/transcriptions-pääteen sijaan mahdollisesti paremman tarkkuuden saavuttamiseksi.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Käytä Chat Completions API:a", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Käytä ryhmiä käyttäjien järjestämiseen ja käyttöoikeuksien määrittämiseen.", "Use LLM": "Käytä LLM:ää", "Use no proxy to fetch page contents.": "Älä käytä välityspalvelinta sivun tietoja haettaessa.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Käytä http_proxy- ja https_proxy-ympäristömuuttujien määrittämää välityspalvelinta sivun sisällön hakemiseen.", + "Use Web Search?": "", "user": "käyttäjä", "User": "Käyttäjä", + "User Access": "", "User Activity": "Käyttäjätoiminta", "User Groups": "Käyttäjäryhmät", "User location successfully retrieved.": "Käyttäjän sijainti haettu onnistuneesti.", "User menu": "Käyttäjävalikko", - "User Preview": "", + "User Preview": "Käyttäjän esikatselu", "User ratings (thumbs up/down)": "Käyttäjien arviot (peukku ylös/alas)", "User Status": "Käyttäjän tila", "User Webhooks": "Käyttäjän Webhook:it", "Username": "Käyttäjätunnus", + "Username Claim": "", "users": "käyttäjät", "Users": "Käyttäjät", "Uses DefaultAzureCredential to authenticate": "Käyttää DefaultAzureCredential todentamiseen", @@ -2247,6 +2424,7 @@ "Valves updated": "Venttiilit päivitetty", "Valves updated successfully": "Venttiilit päivitetty onnistuneesti", "variable": "muuttuja", + "Vector Field": "", "Verify Connection": "Tarkista yhteys", "Verify SSL Certificate": "Tarkista SSL-varmenne", "Version": "Versio", @@ -2260,7 +2438,7 @@ "Visible": "Näkyvillä", "Visible to all users": "Näkyy kaikille käyttäjille", "Vision": "Visio", - "Visual": "", + "Visual": "Visuaalinen", "Voice": "Ääni", "Voice Input": "Äänitulolaitteen käyttö", "Voice mode": "Puhetila", @@ -2276,11 +2454,14 @@ "Web API": "Web-API", "Web Loader Engine": "Verkkolataaja moottori", "Web Search": "Verkkohaku", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Hakukoneet", "Web Search in Chat": "Verkkohaku keskustelussa", "Web Search Query Generation": "Verkkohakukyselyn luonti", + "Webhook deleted": "", "Webhook Name": "Webhook nimi", - "Webhook URL": "Webhook verkko-osoite", + "Webhook saved": "", "Webhooks": "Webhookit", "Webpage URLs": "Verkkosivujen verkko-osoitteet", "WebUI Settings": "WebUI-asetukset", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex Web Search API -avain", "Yandex Web Search config": "Yandex Web Search asetukset", "Yandex Web Search URL": "Yandex Web Search verkko-osoite", + "Yearly": "", "Yesterday": "Eilen", "Yesterday at {{LOCALIZED_TIME}}": "Eilen {{LOCALIZED_TIME}}", "You": "Sinä", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Selaimesi ei tue video-tagia.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Koko panoksesi menee suoraan lisäosan kehittäjälle; Open WebUI ei pidätä prosenttiosuutta. Valittu rahoitusalusta voi kuitenkin periä omia maksujaan.", "Your message text or inputs": "Viestisi teksti tai syöteet", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Käyttötilastosi on synkronoitu onnistuneesti.", "YouTube": "YouTube", "Youtube Language": "Youtube kieli", diff --git a/src/lib/i18n/locales/fil-PH/translation.json b/src/lib/i18n/locales/fil-PH/translation.json index 0e7d6bb423..cf4161c8dd 100644 --- a/src/lib/i18n/locales/fil-PH/translation.json +++ b/src/lib/i18n/locales/fil-PH/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -26,12 +30,16 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -39,8 +47,10 @@ "{{user}}'s Chats": "", "{{webUIName}} Backend Required": "", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -58,6 +68,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Account", @@ -73,6 +84,7 @@ "Activity": "Aktibidad", "Add": "Idagdag", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "", "Add a tag": "", "Add a tag...": "", @@ -85,8 +97,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -101,6 +115,7 @@ "Add to favorites": "", "Add User": "", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -113,7 +128,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "", + "Admin Roles": "", "Admin Settings": "", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "", @@ -124,16 +141,21 @@ "All": "Lahat", "All chats have been unarchived.": "", "All day": "Buong araw", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Lahat ng oras", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -153,9 +175,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Mayroon nang account?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -174,6 +198,7 @@ "API Base URL": "", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "", + "API Key / Token": "", "API Key created.": "", "API Key Endpoint Restrictions": "", "API keys": "", @@ -203,13 +228,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "Tanong", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -224,14 +254,20 @@ "Audio": "", "August": "Agosto", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "", - "Auto-playback response": "", + "Auto-Create Groups": "", + "Auto-Playback Response": "", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "", @@ -249,6 +285,7 @@ "Available Skills": "", "Available Tools": "", "available users": "", + "Available variables": "", "available!": "", "Away": "", "Awful": "", @@ -259,16 +296,17 @@ "Bad Response": "", "Banners": "", "Base Model (From)": "", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "Naka-bold", @@ -325,7 +363,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "", + "Chat Direction": "", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -397,6 +435,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "", + "Collection Field": "", "Collections": "", "Color": "Kulay", "ComfyUI": "", @@ -406,12 +445,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "", "Comment": "Komento", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -433,6 +474,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -445,8 +487,16 @@ "Contact Admin for WebUI Access": "", "Content": "Nilalaman", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "", "Continue with {{provider}}": "", "Continue with Email": "", @@ -494,6 +544,7 @@ "Create new secret key": "", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "", @@ -511,6 +562,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "Araw-araw", "Daily Messages": "", "Danger Zone": "", @@ -533,7 +585,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "", "Default model updated": "", "Default permissions": "", @@ -543,6 +594,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "", + "Default webhook": "", "Defaults": "", "Delete": "Burahin", "Delete {{name}}": "", @@ -603,6 +655,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Naka-disable", "Disconnect OAuth": "", "Discover a function": "", @@ -617,10 +671,10 @@ "Discover, download, and explore model presets": "", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "", + "Display the Username Instead of You in the Chat": "", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -631,6 +685,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokumento", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -686,12 +741,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -700,6 +757,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -708,6 +766,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "Mga Emoji", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -715,22 +774,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Pinagana", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -747,6 +811,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "", "Enter Chunk Size": "", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -784,8 +850,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -805,6 +874,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -814,6 +884,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -834,6 +905,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "", @@ -874,11 +947,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -906,12 +983,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -929,6 +1012,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -936,6 +1020,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -945,6 +1030,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -953,9 +1039,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -988,6 +1076,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Salain", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1010,6 +1100,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1040,6 +1131,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1072,7 +1164,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1084,6 +1179,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1114,6 +1210,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1139,6 +1237,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "", @@ -1196,7 +1295,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1209,6 +1307,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1225,7 +1325,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "Matuto pa", "Learn More": "Matuto Pa", @@ -1247,6 +1346,7 @@ "Legacy": "", "lexical": "", "License": "Lisensya", + "Lifecycle JSON": "", "Lift List": "", "Light": "Maliwanag", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1270,6 +1370,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "", "Make password visible in the user interface": "", @@ -1286,6 +1387,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Marso", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1313,6 +1415,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "", "Message": "Mensahe", @@ -1323,9 +1426,12 @@ "messages": "", "Messages": "Mga Mensahe", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1378,6 +1484,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "Buwan", "Monthly": "Buwanin", "More": "Higit Pa", @@ -1395,6 +1502,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Hindi Kailanman", "New": "Bago", "New Automation": "", @@ -1424,6 +1532,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1436,8 +1545,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1465,6 +1576,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "", "No results found": "Walang nahanap na resulta", "No search query generated": "", @@ -1484,6 +1596,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Wala", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1499,20 +1612,25 @@ "Notifications": "Mga Abiso", "November": "Nobyembre", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktubre", "Off": "Naka-off", "Okay, Let's Go!": "", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "", + "Omit": "", "On": "Naka-on", "Once": "", "OneDrive": "", @@ -1583,6 +1701,7 @@ "Password": "", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "Naka-pause", "PDF document (.pdf)": "", @@ -1591,18 +1710,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "", "Pending": "Nakabinbin", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "", "Permissions": "Mga Pahintulot", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalisasyon", + "Picture Claim": "", "Pin": "I-pin", "Pin to Sidebar": "", "Pinned": "Naka-pin", @@ -1635,13 +1757,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1671,6 +1793,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Pampubliko", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", @@ -1688,21 +1812,29 @@ "Read": "Basahin", "Read Aloud": "Basahin nang Malakas", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Kamakailan Ginamit", "Reconnected": "", "Record": "I-record", "Record voice": "", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "I-refresh", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1736,19 +1868,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "Sumagot", "Reply in Thread": "Sumagot sa Thread", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "I-reset", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1769,6 +1908,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Tungkulin", + "Roles Claim": "", "RTL": "", "Run": "Patakbuhin", "Run All": "", @@ -1787,10 +1927,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "", "Schedule": "Iskedyul", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Maghanap", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1800,6 +1942,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1814,13 +1957,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1836,7 +1982,6 @@ "Seed": "", "Select": "Pumili", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1874,18 +2019,25 @@ "semantic": "", "Send": "Ipadala", "Send a Message": "Magpadala ng Mensahe", + "Send events for": "", "Send message": "Magpadala ng mensahe", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Setyembre", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "", "Set as Production": "", "Set embedding model": "", @@ -1913,15 +2065,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "Ibinahagi sa iyo", "Sharing Permissions": "", "Show": "Ipakita", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "Ipakita ang Lahat", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1965,6 +2119,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "", "Speech-to-Text": "", @@ -2002,6 +2157,7 @@ "STT Settings": "", "Stylized PDF Export": "", "Su_day_of_week": "Linggo", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2026,8 +2182,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "", "System Prompt": "", + "Table": "", "Tag": "", "Tags": "Mga Tag", "Tags Generation": "", @@ -2048,6 +2206,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "", @@ -2063,7 +2227,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2085,6 +2248,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2125,7 +2289,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Ngayon", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2139,6 +2303,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2187,14 +2353,19 @@ "Unpin": "I-unpin", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "I-update", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "I-update ang Password", + "Update Picture": "", "Update your status": "", "Updated": "Na-update", "Updated at": "", @@ -2221,13 +2392,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "", "User": "Gumagamit", + "User Access": "", "User Activity": "Aktibidad ng Gumagamit", "User Groups": "Mga Grupo ng Gumagamit", "User location successfully retrieved.": "", @@ -2237,6 +2413,7 @@ "User Status": "Katayuan ng Gumagamit", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Mga Gumagamit", "Uses DefaultAzureCredential to authenticate": "", @@ -2250,6 +2427,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Bersyon", @@ -2279,11 +2457,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "Paghahanap sa Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "", @@ -2326,6 +2507,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Kahapon", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Ikaw", @@ -2355,6 +2537,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/fr-CA/translation.json b/src/lib/i18n/locales/fr-CA/translation.json index d380d380c1..ecff2af148 100644 --- a/src/lib/i18n/locales/fr-CA/translation.json +++ b/src/lib/i18n/locales/fr-CA/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "Nombres de lignes cachées {{COUNT}}", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Conversations de {{user}}", "{{webUIName}} Backend Required": "Backend {{webUIName}} requis", "*Prompt node ID(s) are required for image generation": "*Les ID de noeud du prompt sont nécessaires pour la génération d'images", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "Contrôle d'accès", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Accessible à tous les utilisateurs", "Account": "Compte", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Ajouter", "Add a model ID": "Ajouter un identifiant de modèle", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Ajoutez une brève description de ce que fait ce modèle.", "Add a tag": "Ajouter un tag", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Ajouter des fichiers", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Ajouter un utilisateur", "Add User Group": "Ajouter un groupe d'utilisateurs", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Administrateur", "Admin Contact Email": "", "Admin Panel": "Panneau d'administration", + "Admin Roles": "", "Admin Settings": "Réglages d'administration", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Les administrateurs ont accès à tous les outils en permanence ; les utilisateurs doivent se voir attribuer des outils pour chaque modèle dans l'espace de travail.", "Advanced": "", "Advanced Parameters": "Réglages avancés", @@ -126,16 +146,21 @@ "All": "Tout", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Tous les modèles ont été supprimés avec succès", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Autoriser les appels", "Allow Chat Controls": "Autoriser les contrôles de la conversation", "Allow Chat Delete": "Autoriser la suppression de la conversation", "Allow Chat Edit": "Autoriser la modification de la conversation", "Allow Chat Export": "Autoriser l'exportation de la conversation", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "Autoriser le partage de la conversation", "Allow Chat System Prompt": "Autoriser le prompt système de la conversation", @@ -155,9 +180,11 @@ "Allow User Location": "Autoriser l'emplacement de l'utilisateur", "Allow Voice Interruption in Call": "Autoriser l'interruption vocale pendant un appel", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Points de terminaison autorisés", "Allowed File Extensions": "Extensions de fichier autorisées", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Autoriser les extensions de fichier pour le téléversement. Séparez plusieurs extensions par des virgules. Laissez vide pour tous les types de fichiers.", + "Allowed Roles": "", "Already have an account?": "Avez-vous déjà un compte ?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternative à top_p, et vise à assurer un équilibre entre qualité et variété. Le paramètre p représente la probabilité minimale pour qu'un token soit considéré, par rapport à la probabilité du token le plus probable. Par exemple, avec p=0.05 et le token le plus probable ayant une probabilité de 0.9, les logits d'une valeur inférieure à 0.045 sont filtrés.", "Always": "Toujours", @@ -176,6 +203,7 @@ "API Base URL": "URL de base de l'API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Clé d'API", + "API Key / Token": "", "API Key created.": "Clé d'API générée.", "API Key Endpoint Restrictions": "Restrictions des points de terminaison de la clé API", "API keys": "Clés d'API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations archivées?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modèles d'arène", "Artifacts": "Artéfacts", "Asc": "", "Ask": "Demander", "Ask a question": "Posez votre question", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistant", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Août", "Auth": "Auth", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Authentifier", "Authentication": "Authentification", "Auto": "Automatique", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copie automatique de la réponse vers le presse-papiers", - "Auto-playback response": "Lire automatiquement la réponse", + "Auto-Create Groups": "", + "Auto-Playback Response": "Lire automatiquement la réponse", "Autocomplete Generation": "Génération des suggestions", "Autocomplete Generation Input Max Length": "Longueur maximale pour la génération des suggestions", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Chaîne d'authentification de l'API", "AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Outils disponibles", "available users": "utilisateurs disponibles", + "Available variables": "", "available!": "disponible !", "Away": "Absent", "Awful": "Horrible", @@ -261,16 +301,17 @@ "Bad Response": "Mauvaise réponse", "Banners": "Bannières", "Base Model (From)": "Modèle de base (à partir de)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "La mise en cache de la liste des modèles de base accélère l'accès en ne récupérant les modèles de base qu'au démarrage ou lors de la sauvegarde des réglages - plus rapide, mais peut ne pas afficher les modifications récentes des modèles de base.", "Bearer": "", "before": "avant", "Being lazy": "Être fainéant", - "Beta": "Bêta", "Bing": "", "Bing Search V7 Endpoint": "Point de terminaison Bing Search V7", "Bing Search V7 Subscription Key": "Clé d'abonnement Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Clé API Bocha Search", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Direction de la conversation", + "Chat Direction": "Direction de la conversation", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Réduire", "Collection": "Collection", + "Collection Field": "", "Collections": "", "Color": "Couleur", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "Flux de travaux de ComfyUI", "ComfyUI Workflow Nodes": "Noeud du flux de travaux de ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Commande", "Comment": "Commentaire", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Complétions", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Connectez-vous à vos points d'extension API compatibles OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Connectez-vous à vos serveurs d'outils externes.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Échec de la connexion", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contacter l'administrateur pour obtenir l'accès à WebUI", "Content": "Contenu", "Content Extraction Engine": "Moteur d'extraction de contenu", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Continuer la réponse", "Continue with {{provider}}": "Continuer avec {{provider}}", "Continue with Email": "Continuer avec le courriel", @@ -497,6 +550,7 @@ "Create new secret key": "Créer une nouvelle clé secrète", "Create note": "", "Create Note": "Créer une note", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Créer votre première note en cliquant sur le boutton ci-dessous", "Created at": "Créé le", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "Nom du réglage personnalisé", "Custom Parameter Value": "Valeur du réglage personnalisé", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Zone de danger", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Le mode par défaut fonctionne avec une plus large gamme de modèles en appelant les outils une fois avant l'exécution. Le mode natif exploite les capacités d'appel d'outils intégrées du modèle, mais nécessite que le modèle prenne en charge cette fonctionnalité.", "Default Model": "Modèle standard", "Default model updated": "Modèle par défaut mis à jour", "Default permissions": "Autorisations par défaut", @@ -546,6 +600,7 @@ "Default to ALL": "Par défaut à TOUS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "La recherche segmentée par défaut permet d'extraire un contenu ciblé et pertinent, ce qui est recommandé dans la plupart des cas.", "Default User Role": "Rôle utilisateur par défaut", + "Default webhook": "", "Defaults": "", "Delete": "Supprimer", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "Désactiver l'interpréteur de code", "Disable Image Extraction": "Empecher l'extraction d'image", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Désactive l'extraction d'images du PDF. Si l'option Utiliser le LLM est activée, les images seront automatiquement légendées. La valeur par défaut est False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Désactivé", "Disconnect OAuth": "", "Discover a function": "Trouvez une fonction", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préréglages de modèles", "Discussion channel where access is based on groups and permissions": "", "Display": "Afficher", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Afficher les emojis pendant l'appel", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Afficher le nom d'utilisateur à la place de \"Vous\" dans la conversation", + "Display the Username Instead of You in the Chat": "Afficher le nom d'utilisateur à la place de \"Vous\" dans la conversation", "Displays citations in the response": "Affiche les citations dans la réponse", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Plonger dans les connaissances", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "URL du serveur Docling requise.", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "Intelligence documentaire", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Modifier les autorisations par défaut", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Modifier la mémoire", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Modifier l'utilisateur", "Edit User Group": "Modifier le groupe d'utilisateurs", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "Édité", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Courriel", + "Email Claim": "", "Embark on adventures": "Embarquez pour des aventures", "Embedding": "Embedding", "Embedding Batch Size": "Taille du lot d'embedding", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Moteur de modèle d'embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "Autoriser l'execution de code", "Enable Code Interpreter": "Autoriser l'interprétation de code", "Enable Community Sharing": "Activer le partage communautaire", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Activer le verrouillage de la mémoire (mlock) pour empêcher les données du modèle d'être échangées de la RAM. Cette option verrouille l'ensemble de pages de travail du modèle en RAM, garantissant qu'elles ne seront pas échangées vers le disque. Cela peut aider à maintenir les performances en évitant les défauts de page et en assurant un accès rapide aux données.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Activer le mappage de la mémoire (mmap) pour charger les données du modèle. Cette option permet au système d'utiliser le stockage disque comme une extension de la RAM en traitant les fichiers disque comme s'ils étaient en RAM. Cela peut améliorer les performances du modèle en permettant un accès plus rapide aux données. Cependant, cela peut ne pas fonctionner correctement avec tous les systèmes et peut consommer une quantité significative d'espace disque.", "Enable Message Queue": "", "Enable Message Rating": "Activer l'évaluation des messages", "Enable Mirostat sampling for controlling perplexity.": "Activer l'échantillonnage Mirostat pour contrôler Perplexité.", "Enable New Sign Ups": "Activer les nouvelles inscriptions", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Activé", "End Tag": "", + "Endpoint": "", "Endpoint URL": "URL du point de terminaison", "Enforce Temporary Chat": "Imposer les discussions temporaires", "Enhance": "Améliore", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Vérifiez que votre fichier CSV comprenne les 4 colonnes dans cet ordre : Name, Email, Password, Role.", "Enter {{role}} message here": "Entrez le message {{role}} ici", - "Enter a detail about yourself for your LLMs to recall": "Saisissez un détail sur vous-même que vos LLMs pourront se rappeler", "Enter a title for the pending user info overlay. Leave empty for default.": "Entrez un titre pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter a watermark for the response. Leave empty for none.": "Entrez un filigrane pour la réponse. Laissez vide pour aucun.", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Entrez le chevauchement des chunks", "Enter Chunk Size": "Entrez la taille des chunks", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Entrez des paires \"token:valeur_biais\" séparées par des virgules (exemple : 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Entrez le contenu pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Entrez l'url de Jupyter", "Enter Kagi Search API Key": "Entrez la clé API Kagi Search", "Enter Key Behavior": "Entrez la clé Behavior", + "Enter language": "", "Enter language codes": "Entrez les codes de langue", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Entrez la clé APU de Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Entrez l'URL du proxy (par ex. https://use:password@host:port)", "Enter reasoning effort": "Entrez l'effort de raisonnement", + "Enter Redirect URI": "", "Enter Score": "Entrez votre score", "Enter SearchApi API Key": "Entrez la clé API SearchApi", "Enter SearchApi Engine": "Entrez le moteur de recherche SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Entrez la clé API SerPAI", "Enter SerpApi Engine": "Entrez le moteur SerApi", "Enter Serper API Key": "Entrez la clé API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Entrez la clé API Serply", "Enter Serpstack API Key": "Entrez la clé API Serpstack", "Enter server host": "Entrez l'hôte du serveur", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Entrez l'URL du serveur Tika", "Enter timeout in seconds": "Entrez le délai d'expiration en secondes", "Enter to Send": "Taper entrer pour envoyer", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Entrez la valeur Top K", "Enter Top K Reranker": "Entrez la valeur Top K pour le Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (par ex. {http://127.0.0.1:7860/})", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Évaluations", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Clé d'Exa API", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemple: TOUS", "Example: mail": "Exemple: mail", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Exporter en CSV", "Export Tools": "", "Export Users": "", "External": "Externe", + "External connection not found.": "", "External Document Loader URL required.": "URL du chargeur de document externe requis", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Model de tâche externe", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Clé API du chargeur Web externe", "External Web Loader URL": "URL du chargeur Web externe", "External Web Search API Key": "Clé API de la recherche Web externe", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Échec de la création de la clé API.", "Failed to delete calendar": "", "Failed to delete note": "Échec de la délétion de la note", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Échec de la récupération des modèles", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Échec de la sauvegarde de la configuration des modèles", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Échec de la mise à jour des réglages", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Échec du téléversement du fichier.", "Features": "Fonctionnalités", "Features Permissions": "Autorisations des fonctionnalités", @@ -991,6 +1082,8 @@ "File uploaded successfully": "Fichier téléversé avec succès", "Filename": "", "Files": "Fichiers", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtre", "Filter is now globally disabled": "Le filtre est maintenant désactivé globalement", "Filter is now globally enabled": "Le filtre est désormais activé globalement", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "Suivi", "Follow Up Generation": "Suivi de la génération", "Follow Up Generation Prompt": "Suivi de la génération du protompt", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "La fonction est désormais globalement activée", "Function Name": "Nom de la fonction", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "La fonction a été mise à jour avec succès", "Functions": "Fonctions", "Functions allow arbitrary code execution.": "Les fonctions permettent l'exécution de code arbitraire.", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Groupe créé avec succès", "Group deleted successfully": "Groupe supprimé avec succès", "Group Description": "Description du groupe", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Retour haptique", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "Autoriser les formulaires dans l'iframe sandbox", "iframe Sandbox Allow Same Origin": "Autoriser même origine dans l'iframe sandbox", @@ -1142,6 +1243,7 @@ "Import From Link": "Importer depuis le lien", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Mise à jour importante", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "Epingler dans la barre latérale", "Key": "Clé", "Key is required": "", - "Keyboard shortcuts": "Raccourcis clavier", "Keyboard Shortcuts": "", "Knowledge": "Connaissances", "Knowledge Access": "Accès aux connaissances", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Partage public des Connaissances", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Connaissance mise à jour avec succès", "Kokoro.js (Browser)": "Kokoro.js (Navigateur)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Déernière réponse", "LDAP": "LDAP", - "LDAP server updated": "Serveur LDAP mis à jour", "Leaderboard": "Classement", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "Licence", + "Lifecycle JSON": "", "Lift List": "", "Light": "Clair", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Accès à la localisation non autorisé", "Lost": "Perdu", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Réalisé par la communauté OpenWebUI", "Make password visible in the user interface": "Rendre visible les mots de passe dans l'interface", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gérer les pipelines", "Manage Tool Servers": "Gérer les serveurs d'outils", "Manage your account information.": "", + "Mapped Source": "", "March": "Mars", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "La mémoire a été effacée avec succès", "Memory deleted successfully": "Le souvenir a été supprimé avec succès", "Memory updated successfully": "Le souvenir a été mis à jour avec succès", + "Merge Accounts by Email": "", "Merge Responses": "Fusionner les réponses", "Merged Response": "Réponse fusionnée", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Les messages que vous envoyez après avoir créé votre lien ne seront pas partagés. Les utilisateurs disposant de l'URL pourront voir la conversation partagée.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personnel)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (travail/école)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Clé API Mojeek", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Plus", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nommez votre base de connaissances", "Name, prompt, and model are required": "", "Native": "Natif", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "Aucune distance disponible", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Aucun fichier sélectionné", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Aucun résultat trouvé", "No results found": "Aucun résultat trouvé", "No search query generated": "Aucune requête de recherche générée", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Aucun", + "Not configured": "", "Not factually correct": "Non factuellement correct", "Not helpful": "Pas utile", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Notifications", "November": "Novembre", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Octobre", "Off": "Désactivé", "Okay, Let's Go!": "D'accord, allons-y !", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Noir OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Réglages de l'API Ollama mis à jour", "Ollama Cloud API Key": "", "Ollama Version": "Version d'Ollama", + "Omit": "", "On": "Activé", "Once": "", "OneDrive": "OneDrive", @@ -1586,6 +1707,7 @@ "Password": "Mot de passe", "Passwords do not match.": "", "Paste Large Text as File": "Coller un texte volumineux comme fichier", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Document au format PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "en attente", "Pending": "en attente", + "Pending Accounts": "", "Pending User Overlay Content": "Contenu de l'overlay utilisateur en attente", "Pending User Overlay Title": "Titre de l'overlay utilisateur en attente", "Permission denied when accessing media devices": "Accès aux appareils multimédias refusé", "Permission denied when accessing microphone": "Accès au microphone refusé", "Permission denied when accessing microphone: {{error}}": "Accès au microphone refusé : {{error}}", "Permissions": "Permissions", + "Permissions reset to defaults": "", "Perplexity API Key": "Clé d'API de Perplexity", "Perplexity Model": "Modèle de Perplexity", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "Utilisation du contexte de recherche de Perplexity", "Persistent": "", "Personalization": "Personnalisation", + "Picture Claim": "", "Pin": "Épingler", "Pin to Sidebar": "", "Pinned": "Épinglé", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Veuillez remplir tous les champs.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Veuillez d'abord sélectionner un modèle.", "Please select a model.": "Veuillez sélectionner un modèle.", "Please select a reason": "Veuillez sélectionner une raison", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Attitude positive", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Partage public des prompts", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Public", "Pull \"{{searchValue}}\" from Ollama.com": "Récupérer « {{searchValue}} » depuis Ollama.com", "Pull a model from Ollama.com": "Télécharger un modèle depuis Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Lire", "Read Aloud": "Lire à haute voix", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "Raisonne", "Reasoning Effort": "Effort de raisonnement", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Enregistrement", "Record voice": "Enregistrer la voix", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirection vers la communauté OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Réduit la probabilité de générer du contenu incohérent. Une valeur plus élevée (ex. : 100) produira des réponses plus variées, tandis qu'une valeur plus faible (ex. : 10) sera plus conservatrice.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Refusé alors qu'il n'aurait pas dû l'être", "Regenerate": "Regénérer", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Réorganiser les modèles", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Répondre dans le fil de discussion", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Moteur de ré-ranking", "Reranking Model": "Modèle de ré-ranking", + "Research Knowledge": "", "Reset": "Réinitialiser", "Reset All Models": "Réinitialiser tous les modèles", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Réinitialiser l’image", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Réinitialiser le répertoire de téléchargement", "Reset Vector Storage/Knowledge": "Réinitialiser le stockage vectoriel/connaissances", "Reset view": "Réinitialiser la vue", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Saisie de texte enrichi pour la conversation", "Role": "Rôle", + "Roles Claim": "", "RTL": "RTL", "Run": "Exécuter", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "La sauvegarde des journaux de conversation directement dans le stockage de votre navigateur n'est plus prise en charge. Veuillez prendre un instant pour télécharger et supprimer vos journaux de conversation en cliquant sur le bouton ci-dessous. Ne vous inquiétez pas, vous pouvez facilement réimporter vos journaux de conversation dans le backend via", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Défilement lors du changement de branche", "Scroll to Top": "", "Search": "Recherche", "Search a model": "Rechercher un modèle", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Rechercher des conversations", "Search Collection": "Rechercher une collection", "Search Files": "", + "Search filters": "", "Search Filters": "Filtres de recherche", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Rechercher des modèles", "Search Notes": "", "Search options": "Options de recherche", + "Search or add pattern": "", "Search Prompts": "Rechercher des prompts", "Search Result Count": "Nombre de résultats de recherche", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Cherche sur Internet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Rechercher des outils", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Clé API SearchApi", "SearchApi Engine": "Moteur de recherche SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Sélectionnez un modèle de base", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Sélectionnez un moteur", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Envoyer", "Send a Message": "Envoyer un message", + "Send events for": "", "Send message": "Envoyer un message", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envoie `stream_options: { include_usage: true }` dans la requête.\nLes fournisseurs pris en charge renverront des informations sur l'utilisation des tokens dans la réponse lorsque cette option est activée.", "September": "Septembre", "SerpApi API Key": "Clé d'API SerpAPI", "SerpApi Engine": "Moteur SerpAPI", "Serper API Key": "Clé API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Clé API Serply", "Serpstack API Key": "Clé API Serpstack", "Server connection failed": "", "Server connection verified": "Connexion au serveur vérifiée", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Définir comme valeur par défaut", "Set as Production": "", "Set embedding model": "Définir le modèle d'embedding", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Partager avec la communauté OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Autorisation de partage", "Show": "Afficher", - "Show \"What's New\" modal on login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion", + "Show \"What's New\" Modal on Login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion", "Show Admin Details in Account Pending Overlay": "Afficher les coordonnées de l'administrateur aux comptes en attente", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "Afficher l'aperçu de l'image", "Show Model": "Afficher le model", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "Identifiant API Sougou Search (sID)", "Sougou Search API SK": "Clé secrète API Sougou Search (SK)", "Source": "Source", + "Specific users or groups": "", "Speech Playback Speed": "Vitesse de lecture de la parole", "Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}", "Speech-to-Text": "Reconnaissance vocale", @@ -2006,6 +2165,7 @@ "STT Settings": "Réglages de Speech-to-Text", "Stylized PDF Export": "Export de PDF stylisés", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Système", + "System events only": "", "System Instructions": "Instructions système", "System Prompt": "Prompt système", + "Table": "", "Tag": "", "Tags": "Étiquettes", "Tags Generation": "Génération de tags", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Text Splitter", "Text-to-Speech": "Text-to-Speech", "Text-to-Speech Engine": "Moteur de Text-to-Speech", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ISO-639-1 (par ex. en) améliorera la précision et la latence. Laisser vide pour détecter automatiquement la langue.", "The LDAP attribute that maps to the mail that users use to sign in.": "L'attribut LDAP qui correspond au courriel que les utilisateurs utilisent pour se connecter.", "The LDAP attribute that maps to the username that users use to sign in.": "L'attribut LDAP qui correspond au nom d'utilisateur que les utilisateurs utilisent pour se connecter.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Le classement est actuellement en version bêta et nous pouvons ajuster les calculs de notation à mesure que nous peaufinons l'algorithme.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "La taille maximale du fichier en Mo. Si la taille du fichier dépasse cette limite, le fichier ne sera pas téléchargé.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Le nombre maximal de fichiers pouvant être utilisés en même temps dans la conversation. Si le nombre de fichiers dépasse cette limite, les fichiers ne seront pas téléchargés.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Le format de sortie du texte. Il peut s'agir de « json », “markdown” ou « html ». La valeur par défaut est « markdown ».", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Il s'agit d'une fonctionnalité expérimentale, elle peut ne pas fonctionner comme prévu et est sujette à modification à tout moment.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Ce modèle n'est pas disponible au public. Veuillez sélectionner un autre modèle.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Cette option détermine la durée pendant laquelle le modèle restera chargé en mémoire après la demande (par défaut : 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Cette option détermine combien de Token sont conservés lors du rafraîchissement du contexte. Par exemple, avec une valeur de 2, les 2 derniers Token seront conservés. Cela aide à maintenir la continuité de la conversation, mais peut limiter la capacité à traiter de nouveaux sujets.", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Pour en savoir plus sur les points de terminaison disponibles, consultez notre documentation.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Pour sélectionner des outils ici, ajoutez-les d'abord à l'espace de travail « Outils ». ", - "Toast notifications for new updates": "Notifications toast pour les nouvelles mises à jour", + "Toast Notifications for New Updates": "Notifications toast pour les nouvelles mises à jour", "Today": "Aujourd'hui", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "Afficher/masquer si la connection courante est active", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Trop détaillé", @@ -2191,14 +2361,19 @@ "Unpin": "Désépingler", "Unpin from Sidebar": "", "Unravel secrets": "Dévoiler les secrets", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Pas de tag", "Untitled": "Sans titre", "Update": "Mise à jour", "Update and Copy Link": "Mettre à jour et copier le lien", + "Update Email": "", "Update for the latest features and improvements.": "Mettez à jour pour bénéficier des dernières fonctionnalités et améliorations.", + "Update Name": "", "Update password": "Mettre à jour le mot de passe", + "Update Picture": "", "Update your status": "", "Updated": "Mis à jour", "Updated at": "Mise à jour le", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Utilisez '#' dans la zone de saisie du prompt pour charger et inclure vos connaissances.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Utiliser le LLM", "Use no proxy to fetch page contents.": "Ne pas utiliser de proxy pour récupérer le contenu des pages.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Utiliser le proxy défini par les variables d'environnement http_proxy et https_proxy pour récupérer le contenu des pages.", + "Use Web Search?": "", "user": "utilisateur", "User": "Utilisateur", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "L'emplacement de l'utilisateur a été récupéré avec succès.", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "Webhooks utilisateur", "Username": "Nom d'utilisateur", + "Username Claim": "", "users": "", "Users": "Utilisateurs", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "Vannes mises à jour", "Valves updated successfully": "Les vannes ont été mises à jour avec succès", "variable": "variable", + "Vector Field": "", "Verify Connection": "Vérifier la connexion", "Verify SSL Certificate": "Vérifier le certificat SSL", "Version": "Version:", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "Moteur de chargement Web", "Web Search": "Recherche Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Moteur de recherche Web", "Web Search in Chat": "Recherche web depuis la conversation", "Web Search Query Generation": "Génération de requête de recherche Web", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL du webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Réglages de WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Hier", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vous", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "L'intégralité de votre contribution ira directement au développeur du plugin ; Open WebUI ne prend aucun pourcentage. Cependant, la plateforme de financement choisie peut avoir ses propres frais.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "Langue de Youtube", diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index d894c8568f..332fa63548 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "Nombres de lignes cachées {{COUNT}}", "{{COUNT}} members": "{{COUNT}} membres", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} Sources", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} mots", "{{COUNT}}d_time_ago": "{{COUNT}}j", "{{COUNT}}h_time_ago": "{{COUNT}}h", "{{COUNT}}m_time_ago": "{{COUNT}}min", "{{COUNT}}w_time_ago": "{{COUNT}}sem", "{{COUNT}}y_time_ago": "{{COUNT}}a", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} à {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Le téléchargement de {{model}} a été annulé", "{{modelName}} profile image": "Image de profil de {{modelName}}", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Conversations de {{user}}", "{{webUIName}} Backend Required": "Backend {{webUIName}} requis", "*Prompt node ID(s) are required for image generation": "*Les ID de noeud du prompt sont nécessaires pour la génération d'image", + "1 group": "", "1 hour before": "1 heure avant", "1 Source": "1 Source", + "1 user": "", "10 minutes before": "10 minutes avant", "15 minutes before": "15 minutes avant", "1m_time_ago": "1min", @@ -60,6 +73,7 @@ "Access Control": "Contrôle d'accès", "Access Grants": "Droits d'accès", "Access List": "Liste des accès", + "Access prohibited": "", "Access updated": "Accès mis à jour", "Accessible to all users": "Accessible à tous les utilisateurs", "Account": "Compte", @@ -75,6 +89,7 @@ "Activity": "Activité", "Add": "Ajouter", "Add a model ID": "Ajouter un ID de modèle", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Ajoutez une brève description de ce que fait ce modèle.", "Add a tag": "Ajouter un tag", "Add a tag...": "Ajouter un tag...", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Ajouter un prompt personnalisé", "Add description": "Ajouter une description", "Add Details": "Ajouter des détails", + "Add durable context for future chats": "", "Add Files": "Ajouter des fichiers", "Add Image": "Ajouter une image", + "Add Knowledge Connection": "", "Add location": "Ajouter un lieu", "Add Member": "Ajouter un membre", "Add Members": "Ajouter des membres", @@ -103,6 +120,7 @@ "Add to favorites": "Ajouter aux favoris", "Add User": "Ajouter un utilisateur", "Add User Group": "Ajouter un groupe d'utilisateurs", + "Add webhook": "", "Add webpage": "Ajouter une page web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Ajoutez votre URL Open Terminal et votre clé API dans Réglages → Intégrations.", "Additional Config": "Configuration supplémentaire", @@ -115,7 +133,9 @@ "Admin": "Administrateur", "Admin Contact Email": "Email de contact de l'administrateur", "Admin Panel": "Panneau d'administration", + "Admin Roles": "", "Admin Settings": "Réglages d'administration", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Les administrateurs ont accès à tous les outils en permanence ; les utilisateurs doivent se voir attribuer des outils pour chaque modèle dans l'espace de travail.", "Advanced": "Avancé", "Advanced Parameters": "Réglages avancés", @@ -126,16 +146,21 @@ "All": "Tout", "All chats have been unarchived.": "Toutes les conversations ont été désarchivées.", "All day": "Toute la journée", + "All events": "", "All models are now hidden": "Tous les modèles sont maintenant masqués", "All models are now visible": "Tous les modèles sont maintenant visibles", "All models deleted successfully": "Tous les modèles supprimés avec succès", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Toute la période", "All Users": "Tous les utilisateurs", + "All users and system events": "", "Allow Call": "Autoriser les appels", "Allow Chat Controls": "Autoriser les contrôles de la conversation", "Allow Chat Delete": "Autoriser la suppression de la conversation", "Allow Chat Edit": "Autoriser la modification de la conversation", "Allow Chat Export": "Autoriser l'exportation de la conversation", + "Allow Chat Import": "", "Allow Chat Params": "Autoriser les paramètres de discussion", "Allow Chat Share": "Autoriser le partage de la conversation", "Allow Chat System Prompt": "Autoriser le prompt système de la conversation", @@ -155,9 +180,11 @@ "Allow User Location": "Autoriser l'emplacement de l'utilisateur", "Allow Voice Interruption in Call": "Autoriser l'interruption vocale pendant un appel", "Allow Web Upload": "Autoriser le téléversement depuis le web", + "Allowed Domains": "", "Allowed Endpoints": "Points de terminaison autorisés", "Allowed File Extensions": "Extensions de fichier autorisées", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Autoriser les extensions de fichier pour le téléversement. Séparez plusieurs extensions par des virgules. Laissez vide pour tous les types de fichiers.", + "Allowed Roles": "", "Already have an account?": "Avez-vous déjà un compte ?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternative à top_p, et vise à assurer un équilibre entre qualité et variété. Le paramètre p représente la probabilité minimale pour qu'un token soit considéré, par rapport à la probabilité du token le plus probable. Par exemple, avec p=0.05 et le token le plus probable ayant une probabilité de 0.9, les logits d'une valeur inférieure à 0.045 sont filtrés.", "Always": "Toujours", @@ -176,6 +203,7 @@ "API Base URL": "URL de base de l'API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL de base de l'API pour le service Datalab Marker. Par défaut : https://www.datalab.to/api/v1/marker", "API Key": "Clé API", + "API Key / Token": "", "API Key created.": "Clé API générée.", "API Key Endpoint Restrictions": "Restrictions des points de terminaison de la clé API", "API keys": "Clés API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer ce souvenir ? Cette action est irréversible.", "Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Êtes-vous sûr de vouloir supprimer cette version ? Les versions enfants seront rattachées à la version parente.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Êtes-vous sûr de vouloir supprimer ceci ?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations ?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modèles d'arène", "Artifacts": "Artéfacts", "Asc": "Croissant", "Ask": "Demander", "Ask a question": "Posez votre question", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistant", "Async Embedding Processing": "Traitement asynchrone des embeddings", "At time of event": "Au moment de l'événement", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Août", "Auth": "Auth", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Authentifier", "Authentication": "Authentification", "Auto": "Automatique", "Auto (Random)": "Auto (Aléatoire)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copie automatique de la réponse vers le presse-papiers", - "Auto-playback response": "Lire automatiquement la réponse", + "Auto-Create Groups": "", + "Auto-Playback Response": "Lire automatiquement la réponse", "Autocomplete Generation": "Génération des suggestions", "Autocomplete Generation Input Max Length": "Longueur maximale pour la génération des suggestions", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Chaîne d'authentification de l'API", "AUTOMATIC1111 Base URL": "URL de base AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Outils disponibles", "available users": "utilisateurs disponibles", + "Available variables": "", "available!": "disponible !", "Away": "Absent", "Awful": "Horrible", @@ -261,16 +301,17 @@ "Bad Response": "Mauvaise réponse", "Banners": "Bannières", "Base Model (From)": "Modèle de base (à partir de)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "La mise en cache de la liste des modèles de base accélère l'accès en ne récupérant les modèles de base qu'au démarrage ou lors de la sauvegarde des réglages - plus rapide, mais peut ne pas afficher les modifications récentes des modèles de base.", "Bearer": "Bearer", "before": "avant", "Being lazy": "Être fainéant", - "Beta": "Bêta", "Bing": "Bing", "Bing Search V7 Endpoint": "Point de terminaison Bing Search V7", "Bing Search V7 Subscription Key": "Clé d'abonnement Bing Search V7", "Bio": "Bio", "Birth Date": "Date de naissance", + "Blocked Groups": "", "BM25 Weight": "Poids BM25", "Bocha Search API Key": "Clé API Bocha Search", "Bold": "Gras", @@ -327,7 +368,7 @@ "Chat Completions": "Chat Completions", "Chat Conversation": "Conversation par chat", "Chat deleted.": "Conversation supprimée.", - "Chat direction": "Direction de la conversation", + "Chat Direction": "Direction de la conversation", "Chat exported successfully": "Conversation exportée avec succès", "Chat History": "Historique des conversations", "Chat ID": "ID de chat", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Canal collaboratif où les membres rejoignent librement", "Collapse": "Réduire", "Collection": "Collection", + "Collection Field": "", "Collections": "Collections", "Color": "Couleur", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "Workflow ComfyUI", "ComfyUI Workflow Nodes": "Noeuds du workflow ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID de nœud séparés par des virgules (Ex : 1 ou 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "commande", "Command": "Commande", "Comment": "Commentaire", "Commit Message": "Description de la modification", "Community Reviews": "Avis de la communauté", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Complétions", "Compress Images in Channels": "Compresser les images dans les canaux", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Connectez-vous à des instances Open Terminal. Tous les utilisateurs auront accès à la navigation de fichiers et aux outils de terminal via ces serveurs.", "Connect to your own OpenAI compatible API endpoints.": "Connectez-vous à vos points d'extension API compatibles OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Connectez-vous à vos serveurs d'outils externes.", + "Connected": "", "Connected ({{type}})": "Connecté ({{type}})", "Connection failed": "Échec de la connexion", "Connection lost. Reconnecting...": "Connexion perdue. Reconnexion...", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contacter l'administrateur pour obtenir l'accès à WebUI", "Content": "Contenu", "Content Extraction Engine": "Moteur d'extraction de contenu", + "Content Field": "", "Content lengths (character counts only)": "Longueur du contenu (nombre de caractères uniquement)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Tokens de contexte", + "Continue": "", "Continue Response": "Continuer la réponse", "Continue with {{provider}}": "Continuer avec {{provider}}", "Continue with Email": "Continuer avec l'email", @@ -497,6 +550,7 @@ "Create new secret key": "Créer une nouvelle clé secrète", "Create note": "Créer une note", "Create Note": "Créer une note", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Créer des invites planifiées qui s'exécutent automatiquement de manière récurrente.", "Create your first note by clicking on the plus button below.": "Créer votre première note en cliquant sur le boutton ci-dessous", "Created at": "Créé le", @@ -514,6 +568,7 @@ "Custom Gender": "Genre personnalisé", "Custom Parameter Name": "Nom du réglage personnalisé", "Custom Parameter Value": "Valeur du réglage personnalisé", + "Custom range": "", "Daily": "Journalier", "Daily Messages": "Messages par jour", "Danger Zone": "Zone de danger", @@ -536,7 +591,6 @@ "Default Features": "Fonctionnalités par défaut", "Default Filters": "Filtres par défaut", "Default Group": "Groupe par défaut", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Le mode par défaut fonctionne avec une plus large gamme de modèles en appelant les outils une fois avant l'exécution. Le mode natif exploite les capacités d'appel d'outils intégrées du modèle, mais nécessite que le modèle prenne en charge cette fonctionnalité.", "Default Model": "Modèle standard", "Default model updated": "Modèle par défaut mis à jour", "Default permissions": "Autorisations par défaut", @@ -546,6 +600,7 @@ "Default to ALL": "Par défaut à TOUS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "La recherche segmentée par défaut permet d'extraire un contenu ciblé et pertinent, ce qui est recommandé dans la plupart des cas.", "Default User Role": "Rôle utilisateur par défaut", + "Default webhook": "", "Defaults": "Valeurs par défaut", "Delete": "Supprimer", "Delete {{name}}": "Supprimer {{name}}", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "Désactiver l'interpréteur de code", "Disable Image Extraction": "Empecher l'extraction d'image", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Désactive l'extraction d'images du PDF. Si l'option Utiliser le LLM est activée, les images seront automatiquement légendées. La valeur par défaut est False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Désactivé", "Disconnect OAuth": "Déconnecter OAuth", "Discover a function": "Trouvez une fonction", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préréglages de modèles", "Discussion channel where access is based on groups and permissions": "Canal de discussion où l'accès est basé sur les groupes et les permissions", "Display": "Afficher", - "Display chat title in tab": "Afficher le nom de la conversation dans l'onglet", + "Display Chat Title in Tab": "Afficher le nom de la conversation dans l'onglet", "Display Emoji in Call": "Afficher les emojis pendant l'appel", "Display Multi-model Responses in Tabs": "Afficher les réponses multi-modèles dans des onglets", - "Display the username instead of You in the Chat": "Afficher le nom d'utilisateur à la place de \"Vous\" dans la conversation", + "Display the Username Instead of You in the Chat": "Afficher le nom d'utilisateur à la place de \"Vous\" dans la conversation", "Displays citations in the response": "Affiche les citations dans la réponse", "Displays status updates (e.g., web search progress) in the response": "Affiche les mises à jour du statut dans la réponse (par ex : la progression de la recherche sur le Web)", "Dive into knowledge": "Plonger dans les connaissances", @@ -634,6 +691,7 @@ "Docling Parameters": "Paramètres Docling", "Docling Server URL required.": "URL du serveur Docling requise.", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Endpoint Document Intelligence requis.", "Document Intelligence Model": "Modèle Document Intelligence", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Modifier les autorisations par défaut", "Edit Folder": "Modifier le dossier", "Edit Image": "Modification d'image", + "Edit Knowledge Connection": "", "Edit Last Message": "Modifier le dernier message", "Edit Memory": "Modifier la mémoire", "Edit Prompt": "Modifier le prompt", "Edit Terminal Connection": "Modifier la connexion à un terminal", "Edit User": "Modifier l'utilisateur", "Edit User Group": "Modifier le groupe d'utilisateurs", + "Edit webhook": "", "Edit workflow.json content": "Modifier le contenu de workflow.json", "edited": "édité", "Edited": "Édité", @@ -703,6 +763,7 @@ "Eject model": "Éjecter le modèle", "ElevenLabs": "ElevenLabs", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "Embarquez pour des aventures", "Embedding": "Embedding", "Embedding Batch Size": "Taille du lot d'embedding", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Moteur de modèle d'embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "Message vide", "Enable All": "Activer tout", "Enable API Keys": "Autoriser les clés API", @@ -718,22 +780,27 @@ "Enable Code Execution": "Autoriser l'exécution de code", "Enable Code Interpreter": "Autoriser l'interprétation de code", "Enable Community Sharing": "Activer le partage communautaire", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Activer le verrouillage de la mémoire (mlock) pour empêcher les données du modèle d'être échangées de la RAM. Cette option verrouille l'ensemble de pages de travail du modèle en RAM, garantissant qu'elles ne seront pas échangées vers le disque. Cela peut aider à maintenir les performances en évitant les défauts de page et en assurant un accès rapide aux données.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Activer le mappage de la mémoire (mmap) pour charger les données du modèle. Cette option permet au système d'utiliser le stockage disque comme une extension de la RAM en traitant les fichiers disque comme s'ils étaient en RAM. Cela peut améliorer les performances du modèle en permettant un accès plus rapide aux données. Cependant, cela peut ne pas fonctionner correctement avec tous les systèmes et peut consommer une quantité significative d'espace disque.", "Enable Message Queue": "Activer la mise en file d'attente de message", "Enable Message Rating": "Activer l'évaluation des messages", "Enable Mirostat sampling for controlling perplexity.": "Activer l'échantillonnage Mirostat pour contrôler Perplexité.", "Enable New Sign Ups": "Activer les nouvelles inscriptions", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Activer, désactiver ou personnaliser les balises de raisonnement utilisées par le modèle. « Activé » utilise les balises par défaut, « Désactivé » désactive les balises de raisonnement, et « Sur mesure » permet de spécifier vos propres balises de début et de fin.", "Enabled": "Activé", "End Tag": "Tag de fin", + "Endpoint": "", "Endpoint URL": "URL du point de terminaison", "Enforce Temporary Chat": "Imposer les discussions temporaires", "Enhance": "Améliore", "Enrich Hybrid Search Text": "Enrichir le texte de recherche hybride", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Vérifiez que votre fichier CSV comprenne les 4 colonnes dans cet ordre : Name, Email, Password, Role.", "Enter {{role}} message here": "Entrez le message {{role}} ici", - "Enter a detail about yourself for your LLMs to recall": "Saisissez un détail sur vous-même que vos LLMs pourront se rappeler", "Enter a title for the pending user info overlay. Leave empty for default.": "Entrez un titre pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter a watermark for the response. Leave empty for none.": "Entrez un filigrane pour la réponse. Laissez vide pour aucun.", "Enter additional headers in JSON format": "Entrez les en-têtes supplémentaires au format JSON", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Entrez la taille minimale cible des chunks", "Enter Chunk Overlap": "Entrez le chevauchement des chunks", "Enter Chunk Size": "Entrez la taille des chunks", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Entrez des paires \"token:valeur_biais\" séparées par des virgules (exemple : 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Entrez le contenu pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter coordinates (e.g. 51.505, -0.09)": "Entrez les coordonnées (Ex : 51.505, -0.09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Entrez l'URL de Jupyter", "Enter Kagi Search API Key": "Entrez la clé API Kagi", "Enter Key Behavior": "Comportement de la touche Entrée", + "Enter language": "", "Enter language codes": "Entrez les codes de langue", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Entrez la clé API MinerU", "Enter Mistral API Base URL": "Entrez l'URL de base de l'API Mistral", "Enter Mistral API Key": "Entrez la clé API Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "Entrez le prompt ici.", "Enter proxy URL (e.g. https://user:password@host:port)": "Entrez l'URL du proxy (par ex. https://user:password@host:port)", "Enter reasoning effort": "Entrez l'effort de raisonnement", + "Enter Redirect URI": "", "Enter Score": "Entrez votre score", "Enter SearchApi API Key": "Entrez la clé API SearchApi", "Enter SearchApi Engine": "Entrez le moteur de recherche SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Entrez la clé API SerpApi", "Enter SerpApi Engine": "Entrez le moteur SerpApi", "Enter Serper API Key": "Entrez la clé API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Entrez la clé API Serply", "Enter Serpstack API Key": "Entrez la clé API Serpstack", "Enter server host": "Entrez l'hôte du serveur", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Entrez l'URL du serveur Tika", "Enter timeout in seconds": "Entrez le délai d'expiration en secondes", "Enter to Send": "Taper entrer pour envoyer", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Entrez la valeur Top K", "Enter Top K Reranker": "Entrez la valeur Top K pour le Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Entrez l'URL (par ex. {http://127.0.0.1:7860/})", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Erreur : Un modèle avec l'ID '{{modelId}}' existe déjà. Veuillez sélectionner un ID différent pour continuer.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Erreur : l'ID du modèle ne peut pas être vide. Veuillez saisir un ID valide pour continuer.", "Evaluations": "Évaluations", + "Event": "", "Event created": "Événement créé", "Event deleted": "Événement supprimé", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Titre de l'événement", "Event updated": "Événement mis à jour", + "Events": "", "Exa API Key": "Clé API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemple: TOUS", "Example: mail": "Exemple: mail", @@ -909,12 +989,18 @@ "Export Config": "Exporter la configuration", "Export Models": "Exporter les modèles", "Export Prompts": "Exporter les prompts", + "Export Skills": "", "Export to CSV": "Exporter en CSV", "Export Tools": "Exporter les outils", "Export Users": "Exporter les utilisateurs", "External": "Externe", + "External connection not found.": "", "External Document Loader URL required.": "URL du chargeur de document externe requis", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Modèle de tâche externe", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Clé API du chargeur Web externe", "External Web Loader URL": "URL du chargeur Web externe", "External Web Search API Key": "Clé API de la recherche Web externe", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Échec de la création de la clé API.", "Failed to delete calendar": "Échec de la suppression du calendrier", "Failed to delete note": "Échec de la délétion de la note", + "Failed to delete webhook": "", "Failed to disconnect": "Échec de la déconnexion", "Failed to download image": "Échec du téléchargement de l'image", "Failed to extract content from the file: {{error}}": "Échec de l'extraction du contenu du fichier : {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Échec de la récupération des modèles", "Failed to generate title": "Échec de la génération du titre", "Failed to import models": "Échec de l'importation des modèles", + "Failed to load chat": "", "Failed to load chat preview": "Échec du chargement de l'aperçu du chat", "Failed to load DOCX file. Please try downloading it instead.": "Échec du chargement du fichier DOCX. Essayez plutôt de le télécharger.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Échec du chargement du fichier Excel/CSV. Essayez plutôt de le télécharger.", @@ -948,6 +1036,7 @@ "Failed to move chat": "Échec du déplacement du chat", "Failed to process URL: {{url}}": "Échec du traitement de l'URL : {{url}}", "Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Échec de la suppression du membre", "Failed to render diagram": "Échec du rendu du diagramme", "Failed to render visualization": "Échec du rendu de la visualisation", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Échec de la sauvegarde de la configuration des modèles", "Failed to save policy: {{error}}": "Échec de la sauvegarde de la politique : {{error}}", "Failed to save terminal servers": "Échec de la sauvegarde des serveurs de terminal", + "Failed to save webhook": "", "Failed to unshare chat.": "Échec de l'annulation du partage de la conversation.", "Failed to update settings": "Échec de la mise à jour des réglages", "Failed to update status": "Échec de la mise à jour du statut", + "Failed to update webhook": "", "Failed to upload file.": "Échec du téléversement du fichier.", "Features": "Fonctionnalités", "Features Permissions": "Autorisations des fonctionnalités", @@ -991,6 +1082,8 @@ "File uploaded successfully": "Fichier téléversé avec succès", "Filename": "Nom du fichier", "Files": "Fichiers", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtre", "Filter is now globally disabled": "Le filtre est maintenant désactivé globalement", "Filter is now globally enabled": "Le filtre est désormais activé globalement", @@ -1013,6 +1106,7 @@ "Folder options": "Options du dossier", "Folder updated successfully": "Dossier mis à jour avec succès", "Folders": "Dossiers", + "Folders Sharing": "", "Follow up": "Questions de suivi", "Follow Up Generation": "Génération de questions de suivi", "Follow Up Generation Prompt": "Prompt de génération de questions de suivi", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "La fonction est désormais globalement activée", "Function Name": "Nom de la fonction", "Function Name Filter List": "Liste de filtrage des fonctions par nom", + "Function starter": "", "Function updated successfully": "Fonction mise à jour avec succès", "Functions": "Fonctions", "Functions allow arbitrary code execution.": "Les fonctions permettent l'exécution de code arbitraire.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Grille", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Canal de groupe", + "Group Claim": "", "Group created successfully": "Groupe créé avec succès", "Group deleted successfully": "Groupe supprimé avec succès", "Group Description": "Description du groupe", @@ -1087,6 +1185,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Retour haptique", + "Header variables": "", "Headers": "En-têtes HTTP", "Headers must be a valid JSON object": "Les en-têtes doivent être au format JSON valide", "Height": "Hauteur", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "L'ID ne peut pas contenir les caractères « : » ou « | »", "ID copied to clipboard": "ID copié dans le presse-papiers", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Délai d'inactivité", "iframe Sandbox Allow Forms": "Autoriser les formulaires dans l'iframe sandbox", "iframe Sandbox Allow Same Origin": "Autoriser même origine dans l'iframe sandbox", @@ -1142,6 +1243,7 @@ "Import From Link": "Importer depuis le lien", "Import Models": "Importer les modèles", "Import Prompts": "Importer les prompts", + "Import Skills": "", "Import successful": "Import réussi", "Import Tools": "Importer les outils", "Important Update": "Mise à jour importante", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "Epingler dans la barre latérale", "Key": "Clé", "Key is required": "La clé est requise", - "Keyboard shortcuts": "Raccourcis clavier", "Keyboard Shortcuts": "Raccourcis clavier", "Knowledge": "Connaissances", "Knowledge Access": "Accès aux connaissances", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Nom de la connaissance", "Knowledge Public Sharing": "Partage public des Connaissances", "Knowledge Sharing": "Partage des connaissances", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Connaissance mise à jour avec succès", "Kokoro.js (Browser)": "Kokoro.js (Navigateur)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Dernière réponse", "LDAP": "LDAP", - "LDAP server updated": "Serveur LDAP mis à jour", "Leaderboard": "Classement", "Learn more": "En savoir plus", "Learn More": "En savoir plus", @@ -1250,6 +1352,7 @@ "Legacy": "Déprécié", "lexical": "lexical", "License": "Licence", + "Lifecycle JSON": "", "Lift List": "Réduire l'indentation", "Light": "Clair", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limite les requêtes de recherche simultanées. 0 = illimité (par défaut). Définir à 1 pour une exécution séquentielle (recommandé pour les API avec des limites de débit strictes comme Brave gratuit).", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Accès à la localisation non autorisé", "Lost": "Perdu", "Low": "Faible", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Réalisé par la communauté OpenWebUI", "Make password visible in the user interface": "Rendre visible les mots de passe dans l'interface", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gérer les pipelines", "Manage Tool Servers": "Gérer les serveurs d'outils", "Manage your account information.": "Gérez les informations de votre compte.", + "Mapped Source": "", "March": "Mars", "Markdown": "Markdown", "Markdown Header Text Splitter": "Découpage par en-têtes markdown", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Souvenir effacé avec succès", "Memory deleted successfully": "Souvenir supprimé avec succès", "Memory updated successfully": "Souvenir mis à jour avec succès", + "Merge Accounts by Email": "", "Merge Responses": "Fusionner les réponses", "Merged Response": "Réponse fusionnée", "Message": "Envoyer un message", @@ -1326,9 +1432,12 @@ "messages": "messages", "Messages": "Messages", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Les messages que vous envoyez après avoir créé votre lien ne seront pas partagés. Les utilisateurs disposant de l'URL pourront voir la conversation partagée.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personnel)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (travail/école)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Clé API MinerU requise pour le mode API Cloud.", @@ -1381,6 +1490,7 @@ "Models Sharing": "Partage des modèles", "Mojeek": "Mojeek", "Mojeek Search API Key": "Clé API Mojeek", + "Monday – Friday": "", "Month": "Mois", "Monthly": "Mensuel", "More": "Plus", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nommez votre base de connaissances", "Name, prompt, and model are required": "Le nom, le prompt et le modèle sont requis", "Native": "Natif", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Jamais", "New": "Nouveaux", "New Automation": "Nouvelle automatisation", @@ -1427,6 +1538,7 @@ "Next run": "Prochaine exécution", "No access grants. Private to you.": "Aucun partage. Visible uniquement par vous.", "No activity data": "Aucune activité", + "No additional headers are sent unless configured.": "", "No authentication": "Aucune authentification", "No automations found": "Aucune automatisation trouvée", "No chats found": "Aucune discussion trouvée", @@ -1439,8 +1551,10 @@ "No data": "Aucune donnée", "No data found": "Aucune donnée trouvée", "No distance available": "Aucune distance disponible", + "No event webhooks configured.": "", "No execution logs available yet": "Aucun journal d'exécution disponible pour le moment", "No expiration can pose security risks.": "L'absence d'expiration peut présenter des risques de sécurité.", + "No external knowledge sources configured.": "", "No feedback found": "Aucun avis trouvé", "No file selected": "Aucun fichier sélectionné", "No files found": "Aucun fichier trouvé", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "Aucun message épinglé", "No prompts found": "Aucun prompt trouvé", + "No Repeat": "", "No results": "Aucun résultat trouvé", "No results found": "Aucun résultat trouvé", "No search query generated": "Aucune requête de recherche générée", @@ -1487,6 +1602,7 @@ "No webhooks yet": "Aucun webhook trouvé", "Node Ids": "ID des noeuds", "None": "Aucun", + "Not configured": "", "Not factually correct": "Non factuellement correct", "Not helpful": "Pas utile", "Not Registered": "Non enregistré", @@ -1502,20 +1618,25 @@ "Notifications": "Notifications", "November": "Novembre", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statique)", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL du serveur OAuth", "OAuth session disconnected": "Session OAuth déconnectée", "October": "Octobre", "Off": "Désactivé", "Okay, Let's Go!": "D'accord, allons-y !", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Noir OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Réglages de l'API Ollama mis à jour", "Ollama Cloud API Key": "Clé API Ollama Cloud", "Ollama Version": "Version d'Ollama", + "Omit": "", "On": "Activé", "Once": "Une fois", "OneDrive": "OneDrive", @@ -1586,6 +1707,7 @@ "Password": "Mot de passe", "Passwords do not match.": "Les mots de passe ne correspondent pas.", "Paste Large Text as File": "Coller un texte volumineux comme fichier", + "Path": "", "Path copied": "Chemin copié", "Paused": "En pause", "PDF document (.pdf)": "Document au format PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "en attente", "Pending": "en attente", + "Pending Accounts": "", "Pending User Overlay Content": "Contenu de l'overlay utilisateur en attente", "Pending User Overlay Title": "Titre de l'overlay utilisateur en attente", "Permission denied when accessing media devices": "Accès aux appareils multimédias refusé", "Permission denied when accessing microphone": "Accès au microphone refusé", "Permission denied when accessing microphone: {{error}}": "Accès au microphone refusé : {{error}}", "Permissions": "Permissions", + "Permissions reset to defaults": "", "Perplexity API Key": "Clé API Perplexity", "Perplexity Model": "Modèle de Perplexity", "Perplexity Search API URL": "URL de l'API Perplexity Search", "Perplexity Search Context Usage": "Utilisation du contexte de recherche de Perplexity", "Persistent": "Persistant", "Personalization": "Personnalisation", + "Picture Claim": "", "Pin": "Épingler", "Pin to Sidebar": "Épingler à la barre latérale", "Pinned": "Épinglé", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Veuillez remplir tous les champs.", "Please register the OAuth client": "Veuillez enregistrer le client OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Veuillez enregistrer la connexion pour conserver les informations du client OAuth et ne modifiez pas l'ID", - "Please select a model first.": "Veuillez d'abord sélectionner un modèle.", "Please select a model.": "Veuillez sélectionner un modèle.", "Please select a reason": "Veuillez sélectionner une raison", "Please select a valid JSON file": "Veuillez sélectionner un fichier JSON valide", "Please select at least one user for Direct Message channel.": "Veuillez sélectionner au moins un utilisateur pour un canal de message direct.", "Please wait until all files are uploaded.": "Veuillez patienter jusqu'à ce que tous les fichiers soient téléchargés.", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "Ports", "Positive attitude": "Attitude positive", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Partage public des prompts", "Prompts Sharing": "Partage de prompts", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Public", "Pull \"{{searchValue}}\" from Ollama.com": "Récupérer « {{searchValue}} » depuis Ollama.com", "Pull a model from Ollama.com": "Télécharger un modèle depuis Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Lire", "Read Aloud": "Lire à haute voix", "Read more →": "En savoir plus →", + "Read only": "", "Read Only": "Lecture seule", "Read-Only Access": "Accès en lecture seule", "Reason": "Raison", "Reasoning Effort": "Effort de raisonnement", "Reasoning Tags": "Balises de raisonnement", "Reasoning text...": "Texte de raisonnement...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Récemment utilisé", "Reconnected": "Reconnecté", "Record": "Enregistrement", "Record voice": "Enregistrer la voix", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirection vers la communauté OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Réduit la probabilité de générer du contenu incohérent. Une valeur plus élevée (ex. : 100) produira des réponses plus variées, tandis qu'une valeur plus faible (ex. : 10) sera plus conservatrice.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Désignez-vous comme « Utilisateur » (par ex. « L'utilisateur apprend l'espagnol »)", "Reference Chats": "Discussions de référence", "Refresh": "Actualiser", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Refusé alors qu'il n'aurait pas dû l'être", "Regenerate": "Regénérer", "Regenerate Menu": "Menu Regénérer", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "Afficher le Markdown dans les aperçus", "Render Markdown in User Messages": "Afficher le Markdown dans les messages de l'utilisateur", "Reorder Models": "Réorganiser les modèles", + "Repeat": "", "Repeats": "", "Reply": "Répondre", "Reply in Thread": "Répondre dans le fil de discussion", "Reply to thread...": "Répondre au fil de discussion...", "Replying to {{NAME}}": "En réponse à {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "requis", "Reranking Batch Size": "", "Reranking Engine": "Moteur de ré-ranking", "Reranking Model": "Modèle de ré-ranking", + "Research Knowledge": "", "Reset": "Réinitialiser", "Reset All Models": "Réinitialiser tous les modèles", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Réinitialiser l’image", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Réinitialiser le répertoire de téléchargement", "Reset Vector Storage/Knowledge": "Réinitialiser le stockage vectoriel/connaissances", "Reset view": "Réinitialiser la vue", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "Une source récupérée", "Rich Text Input for Chat": "Saisie de texte enrichi pour la conversation", "Role": "Rôle", + "Roles Claim": "", "RTL": "RTL", "Run": "Exécuter", "Run All": "Tout exécuter", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "La sauvegarde des journaux de conversation directement dans le stockage de votre navigateur n'est plus prise en charge. Veuillez prendre un instant pour télécharger et supprimer vos journaux de conversation en cliquant sur le bouton ci-dessous. Ne vous inquiétez pas, vous pouvez facilement réimporter vos journaux de conversation dans le backend via", "Schedule": "Planifier", "Scheduled time must be in the future": "L'heure prévue doit être située dans le futur", + "Scopes": "", "Scroll On Branch Change": "Défilement lors du changement de branche", "Scroll to Top": "Retour en haut", "Search": "Recherche", "Search a model": "Rechercher un modèle", + "Search actions": "", "Search all emojis": "Rechercher tous les emojis", "Search and manage user memories": "Rechercher et gérer les éléments mémorisés de l'utilisateur", "Search and view user chat history": "Rechercher et afficher l'historique des conversations de l'utilisateur", @@ -1804,6 +1950,7 @@ "Search Chats": "Rechercher des conversations", "Search Collection": "Rechercher une collection", "Search Files": "Rechercher des fichiers", + "Search filters": "", "Search Filters": "Filtres de recherche", "search for archived chats": "Rechercher les conversations archivées", "search for folders": "Rechercher tous les dossiers", @@ -1818,13 +1965,16 @@ "Search Models": "Rechercher des modèles", "Search Notes": "Rechercher des notes", "Search options": "Options de recherche", + "Search or add pattern": "", "Search Prompts": "Rechercher des prompts", "Search Result Count": "Nombre de résultats de recherche", + "Search skills": "", "Search Skills": "Rechercher des skills", - "Search skills...": "", "Search the internet": "Cherche sur Internet", "Search the web and fetch URLs": "Rechercher sur le web et récupérer le contenu de sites web à partir d'une URL", + "Search tools": "", "Search Tools": "Rechercher des outils", + "Search users or groups": "", "Search, view, and manage user notes": "Rechercher, afficher et gérer les notes de l'utilisateur", "SearchApi API Key": "Clé API SearchApi", "SearchApi Engine": "Moteur de recherche SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Seed", "Select": "Choisir", "Select {{modelName}} model": "Sélectionner le modèle {{modelName}}", - "Select a base model": "Sélectionnez un modèle de base", "Select a base model (e.g. llama3, gpt-4o)": "Chosir un modèle de base (ex : lamma3, gpt-4o)", "Select a conversation to preview": "Choisir une conversation pour la prévisualiser", "Select a engine": "Sélectionnez un moteur", @@ -1878,18 +2027,25 @@ "semantic": "sémantique", "Send": "Envoyer", "Send a Message": "Envoyer un message", + "Send events for": "", "Send message": "Envoyer un message", "Send now": "Envoyer maintenant", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envoie `stream_options: { include_usage: true }` dans la requête.\nLes fournisseurs pris en charge renverront des informations sur l'utilisation des tokens dans la réponse lorsque cette option est activée.", "September": "Septembre", "SerpApi API Key": "Clé API SerpApi", "SerpApi Engine": "Moteur SerpAPI", "Serper API Key": "Clé API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Clé API Serply", "Serpstack API Key": "Clé API Serpstack", "Server connection failed": "Connexion au serveur échouée", "Server connection verified": "Connexion au serveur vérifiée", + "Service Account": "", "Session": "Session", + "Session expired. Please sign in again.": "", "Set as default": "Définir comme valeur par défaut", "Set as Production": "Définir comme version active", "Set embedding model": "Définir le modèle d'embedding", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "Lien de partage copié dans le presse-papiers.", "Share to Open WebUI Community": "Partager avec la communauté OpenWebUI", "Share your background and interests": "Partagez votre parcours et vos intérêts", + "Shared": "", "Shared Chats": "Conversations partagées", "Shared with you": "Partagé avec vous", "Sharing Permissions": "Autorisation de partage", "Show": "Afficher", - "Show \"What's New\" modal on login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion", + "Show \"What's New\" Modal on Login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion", "Show Admin Details in Account Pending Overlay": "Afficher les coordonnées de l'administrateur aux comptes en attente", "Show All": "Afficher tout", "Show all ({{COUNT}} characters)": "Tout afficher ({{COUNT}} caractères)", "Show Files": "Afficher les fichiers", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Afficher la barre d'outils de formatage", "Show image preview": "Afficher l'aperçu de l'image", "Show Model": "Afficher le modèle", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "Identifiant API Sougou Search (sID)", "Sougou Search API SK": "Clé secrète API Sougou Search (SK)", "Source": "Source", + "Specific users or groups": "", "Speech Playback Speed": "Vitesse de lecture de la parole", "Speech recognition error: {{error}}": "Erreur de reconnaissance vocale : {{error}}", "Speech-to-Text": "Reconnaissance vocale", @@ -2006,6 +2165,7 @@ "STT Settings": "Réglages de Speech-to-Text", "Stylized PDF Export": "Export de PDF stylisés", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "Envoyer la question", "Submit suggestion": "Soumettre la suggestion", "Subtitle": "Sous-titre", @@ -2030,8 +2190,10 @@ "Syncing...": "Synchronisation en cours...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synchronise uniquement les conversations mises à jour depuis la dernière synchronisation. Désactivez pour re-synchroniser toutes les conversations.", "System": "Système", + "System events only": "", "System Instructions": "Instructions système", "System Prompt": "Prompt système", + "Table": "", "Tag": "Tag", "Tags": "Tags", "Tags Generation": "Génération de tags", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Conversation temporaire par défaut", "Terminal": "Terminal", "Terminal servers saved": "Serveurs de terminal sauvegardés", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Découpage du texte", "Text-to-Speech": "Text-to-Speech", "Text-to-Speech Engine": "Moteur de Text-to-Speech", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ISO-639-1 (par ex. en) améliorera la précision et la latence. Laisser vide pour détecter automatiquement la langue.", "The LDAP attribute that maps to the mail that users use to sign in.": "L'attribut LDAP qui correspond à l'adresse e-mail que les utilisateurs utilisent pour se connecter.", "The LDAP attribute that maps to the username that users use to sign in.": "L'attribut LDAP qui correspond au nom d'utilisateur que les utilisateurs utilisent pour se connecter.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Le classement est actuellement en version bêta et nous pouvons ajuster les calculs de notation à mesure que nous peaufinons l'algorithme.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "La taille maximale du fichier en Mo. Si la taille du fichier dépasse cette limite, le fichier ne sera pas téléchargé.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Le nombre maximal de fichiers pouvant être utilisés en même temps dans la conversation. Si le nombre de fichiers dépasse cette limite, les fichiers ne seront pas téléchargés.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Le format de sortie du texte. Il peut s'agir de « json », “markdown” ou « html ». La valeur par défaut est « markdown ».", @@ -2089,6 +2256,7 @@ "This folder is empty": "Ce dossier est vide", "This is a default user permission and will remain enabled.": "Ceci est une permission utilisateur par défaut et restera activée.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Il s'agit d'une fonctionnalité expérimentale, elle peut ne pas fonctionner comme prévu et est sujette à modification à tout moment.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Ce modèle n'est pas disponible au public. Veuillez sélectionner un autre modèle.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Cette option détermine la durée pendant laquelle le modèle restera chargé en mémoire après la demande (par défaut : 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Cette option détermine combien de Token sont conservés lors du rafraîchissement du contexte. Par exemple, avec une valeur de 2, les 2 derniers Token seront conservés. Cela aide à maintenir la continuité de la conversation, mais peut limiter la capacité à traiter de nouveaux sujets.", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Pour en savoir plus sur les points de terminaison disponibles, consultez notre documentation.", "To select skills here, add them to the \"Skills\" workspace first.": "Pour sélectionner des skills ici, ajoutez-les d'abord à l'espace de travail « Skills ».", "To select toolkits here, add them to the \"Tools\" workspace first.": "Pour sélectionner des outils ici, ajoutez-les d'abord à l'espace de travail « Outils ». ", - "Toast notifications for new updates": "Notifications toast pour les nouvelles mises à jour", + "Toast Notifications for New Updates": "Notifications toast pour les nouvelles mises à jour", "Today": "Aujourd'hui", "Today at": "Aujourd'hui à", "Today at {{LOCALIZED_TIME}}": "Aujourd'hui à {{LOCALIZED_TIME}}", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "Afficher/masquer si la connection courante est active", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Le nombre de tokens est une estimation et peut ne pas refléter l'utilisation réelle de l'API", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Trop détaillé", @@ -2191,14 +2361,19 @@ "Unpin": "Désépingler", "Unpin from Sidebar": "Désépingler de la barre latérale", "Unravel secrets": "Dévoiler les secrets", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Annuler le partage de la conversation", "Unsupported file type.": "Type de fichier non pris en charge.", "Untagged": "Pas de tag", "Untitled": "Sans titre", "Update": "Mise à jour", "Update and Copy Link": "Mettre à jour et copier le lien", + "Update Email": "", "Update for the latest features and improvements.": "Mettez à jour pour bénéficier des dernières fonctionnalités et améliorations.", + "Update Name": "", "Update password": "Mettre à jour le mot de passe", + "Update Picture": "", "Update your status": "Mettre à jour votre statut", "Updated": "Mis à jour", "Updated at": "Mise à jour le", @@ -2225,13 +2400,18 @@ "Use": "Utilisez", "Use '#' in the prompt input to load and include your knowledge.": "Utilisez '#' dans la zone de saisie du prompt pour charger et inclure vos connaissances.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Utilise le endpoint /v1/chat/completions au lieu de /v1/audio/transcriptions pour une meilleure précision potentielle.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Utiliser l'API Chat Completions", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Utilisez les groupes pour organiser vos utilisateurs et attribuer des permissions.", "Use LLM": "Utiliser le LLM", "Use no proxy to fetch page contents.": "Ne pas utiliser de proxy pour récupérer le contenu des pages.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Utiliser le proxy défini par les variables d'environnement http_proxy et https_proxy pour récupérer le contenu des pages.", + "Use Web Search?": "", "user": "utilisateur", "User": "Utilisateur", + "User Access": "", "User Activity": "Activité des utilisateurs", "User Groups": "Groupes d'utilisateurs", "User location successfully retrieved.": "Emplacement de l'utilisateur récupéré avec succès.", @@ -2241,6 +2421,7 @@ "User Status": "Statut utilisateur", "User Webhooks": "Webhooks utilisateur", "Username": "Nom d'utilisateur", + "Username Claim": "", "users": "utilisateurs", "Users": "Utilisateurs", "Uses DefaultAzureCredential to authenticate": "Utilise DefaultAzureCredential pour s'authentifier", @@ -2254,6 +2435,7 @@ "Valves updated": "Vannes mises à jour", "Valves updated successfully": "Vannes mises à jour avec succès", "variable": "variable", + "Vector Field": "", "Verify Connection": "Vérifier la connexion", "Verify SSL Certificate": "Vérifier le certificat SSL", "Version": "Version:", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "Moteur de chargement Web", "Web Search": "Recherche Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Moteur de recherche Web", "Web Search in Chat": "Recherche web depuis la conversation", "Web Search Query Generation": "Génération de requête de recherche Web", + "Webhook deleted": "", "Webhook Name": "Nom du webhook", - "Webhook URL": "URL du webhook", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URL des pages web", "WebUI Settings": "Réglages de WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "Clé API de recherche web Yandex", "Yandex Web Search config": "Configuration de recherche web Yandex", "Yandex Web Search URL": "URL de recherche web Yandex", + "Yearly": "", "Yesterday": "Hier", "Yesterday at {{LOCALIZED_TIME}}": "Hier à {{LOCALIZED_TIME}}", "You": "Vous", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "Votre navigateur ne prend pas en charge la balise « video ».", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "L'intégralité de votre contribution ira directement au développeur du plugin ; Open WebUI ne prend aucun pourcentage. Cependant, la plateforme de financement choisie peut avoir ses propres frais.", "Your message text or inputs": "Vos messages envoyés", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Vos statistiques d'utilisation ont été synchronisées avec succès.", "YouTube": "YouTube", "Youtube Language": "Langue de YouTube", diff --git a/src/lib/i18n/locales/gl-ES/translation.json b/src/lib/i18n/locales/gl-ES/translation.json index 392d9fe7e1..9c7cd51f42 100644 --- a/src/lib/i18n/locales/gl-ES/translation.json +++ b/src/lib/i18n/locales/gl-ES/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Chats do {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Servidor Requerido", "*Prompt node ID(s) are required for image generation": "Os ID do nodo son requeridos para a xeneración de imáxes", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Control de Acceso", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Accesible para todos os usuarios", "Account": "Conta", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Agregar", "Add a model ID": "Agregado ID do modelo", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Agregue unha breve descripción sobre o que fai este modelo", "Add a tag": "Agregar unha etiqueta", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Agregar Arquivos", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Agregar Usuario", "Add User Group": "Agregar usuario al grupo", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Panel de Administración", + "Admin Roles": "", "Admin Settings": "Configuración de Administrador", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Os administradores teñen acceso a todas as ferramentas en todo momento; os usuarios necesitan ferramentas asignadas por modelo no espacio de trabajo.", "Advanced": "", "Advanced Parameters": "Parámetros Avanzados", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Todos os modelos han sido borrados", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Permitir Control dos Chats", "Allow Chat Delete": "Permitir Borrar Chat", "Allow Chat Edit": "Pemritir Editar Chat", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Permitir Ubicación do Usuario", "Allow Voice Interruption in Call": "Permitir interrupción de voz en chamada", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Puntos finais permitidos", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "¿Xa tes unha conta?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Sempre", @@ -173,6 +197,7 @@ "API Base URL": "Dirección URL da API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Chave da API ", + "API Key / Token": "", "API Key created.": "Chave da API creada.", "API Key Endpoint Restrictions": "Restriccions de Endpoint de Chave de API", "API keys": "Chaves da API", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "¿Seguro que queres eliminar este mensaxe? ", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "¿Estás seguro de que quieres desArquivar todos os chats arquivados?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Area de Modelos", "Artifacts": "Artefactos", "Asc": "", "Ask": "", "Ask a question": "Fai unha pregunta", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistente", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "Agosto", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autenticar", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copiar a resposta automáticamente o portapapeis", - "Auto-playback response": "Respuesta de reproducción automática", + "Auto-Create Groups": "", + "Auto-Playback Response": "Respuesta de reproducción automática", "Autocomplete Generation": "xeneración de autocompletado", "Autocomplete Generation Input Max Length": "Longitud máxima de entrada da xeneración de autocompletado", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "AUTOMATIC1111", "AUTOMATIC1111 Api Auth String": "API de autenticación para a instancia de AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Dirección URL de AUTOMATIC1111", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "usuarios dispoñibles", + "Available variables": "", "available!": "¡dispoñible!", "Away": "Ausente", "Awful": "Horrible", @@ -258,16 +295,17 @@ "Bad Response": "Resposta incorrecta", "Banners": "Mensaxes emerxentes", "Base Model (From)": "Modelo base (desde)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "antes", "Being lazy": "Ser pregizeiro", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Punto final da busqueda de Bing versión V7", "Bing Search V7 Subscription Key": "Chave de suscripción da busqueda de Bing versión V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Dirección do Chat", + "Chat Direction": "Dirección do Chat", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Esconder", "Collection": "Colección", + "Collection Field": "", "Collections": "", "Color": "Cor", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "Fluxo de traballo de ComfyUI", "ComfyUI Workflow Nodes": "Nodos para ComfyUI Workflow", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Comando", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Respostas autoxeradas", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Conecta os teus propios Api compatibles con OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Contacta o administrador para obter acceso o WebUI", "Content": "Contido", "Content Extraction Engine": "Motor extractor de contido", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Continuar Respuesta", "Continue with {{provider}}": "Continuar co {{provider}}", "Continue with Email": "Continuar co email", @@ -493,6 +543,7 @@ "Create new secret key": "Xerar unha nova chave secreta", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Creado en", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "O modo predeterminado funciona con unha gama mais ampla de modelos chamando as ferramentas unha vez antes da execución. o modo nativo aproveita as capacidades integradas de chamada de ferramentas do modelo, pero requiere que o modelo soporte esta función de manera inherente.", "Default Model": "Modelo predeterminado", "Default model updated": "O modelo por defecto foi actualizado", "Default permissions": "Permisos predeterminados", @@ -542,6 +593,7 @@ "Default to ALL": "Predeterminado a TODOS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Rol por defecto para os usuarios", + "Default webhook": "", "Defaults": "", "Delete": "Borrar", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Desactivado", "Disconnect OAuth": "", "Discover a function": "Descubre unha función", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos", "Discussion channel where access is based on groups and permissions": "", "Display": "Mostrar", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Muestra Emoji en chamada", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Mostrar o nombre de usuario en lugar de Vostede no chat", + "Display the Username Instead of You in the Chat": "Mostrar o nombre de usuario en lugar de Vostede no chat", "Displays citations in the response": "Muestra citas en arespuesta", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Sumérgete no coñecemento", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Documento", + "Document ID Field": "", "Document Intelligence": "Inteligencia documental", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Editar permisos predeterminados", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Editar Memoria", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Editar Usuario", "Edit User Group": "Editar grupo de usuarios", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Emprende aventuras", "Embedding": "", "Embedding Batch Size": "Tamaño de Embedding", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Motor de Modelo de Embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Habilitar a execución de código", "Enable Code Interpreter": "Habilitar o interprete de código", "Enable Community Sharing": "Habilitar o uso compartido da comunidad", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Habilitar o bloqueo de memoria (mlock) para evitar que os datos do modelo se intercambien da RAM. Esta opción bloquea o conxunto de páxinas de traballo do modelo na RAM, asegurando que non se intercambiarán ao disco. Isto pode axudar a manter o rendemento evitando fallos de páxina e garantindo un acceso rápido aos datos.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Habilitar o mapeo de memoria (mmap) para cargar os datos do modelo. Esta opción permite ao sistema usar o almacenamento en disco como unha extensión da RAM tratando os arquivos de disco como se estivesen na RAM. Isto pode mellorar o rendemento do modelo permitindo un acceso máis rápido aos datos. Sen embargo, pode non funcionar correctamente con todos os sistemas e pode consumir unha cantidade significativa de espazo en disco.", "Enable Message Queue": "", "Enable Message Rating": "Habilitar a calificación de os mensaxes", "Enable Mirostat sampling for controlling perplexity.": "Habilitar o muestreo de Mirostat para controlar Perplexity.", "Enable New Sign Ups": "Habilitar novos Registros", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Activado", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "asegurese de o teu arquivo CSV inclúe 4 columnas nesta orde: Nome, Email, Contrasinal, Rol.", "Enter {{role}} message here": "Ingrese o mensaxe {{role}} aquí", - "Enter a detail about yourself for your LLMs to recall": "Ingrese un detalle sobre vostede para que as suas LLMs recorden", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Ingresar superposición de fragmentos", "Enter Chunk Size": "Ingrese o tamaño do fragmento", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Ingrese a URL de Jupyter", "Enter Kagi Search API Key": "Ingrese a chave API de Kagi Search", "Enter Key Behavior": "Ingrese o comportamento da chave", + "Enter language": "", "Enter language codes": "Ingrese códigos de idioma", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Ingrese a URL do proxy (p.ej. https://user:password@host:port)", "Enter reasoning effort": "Ingrese o esfuerzo de razonamiento", + "Enter Redirect URI": "", "Enter Score": "Ingrese a puntuación", "Enter SearchApi API Key": "Ingrese a chave API de SearchApi", "Enter SearchApi Engine": "Ingrese o motor de SearchApi", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Ingrese a chave API de SerpApi", "Enter SerpApi Engine": "Ingrese o motor de SerpApi", "Enter Serper API Key": "Ingrese a chave API de Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Ingrese a chave API de Serply", "Enter Serpstack API Key": "Ingrese a chave API de Serpstack", "Enter server host": "Ingrese o host do servidor", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Ingrese a URL do servidor Tika", "Enter timeout in seconds": "Ingrese o tempo de espera en segundos", "Enter to Send": "Ingrese para enviar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Ingrese o Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Ingrese a URL (p.ej., http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Evaluacions", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "chave API de Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemplo: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemplo: TODOS", "Example: mail": "Exemplo: correo", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Exportar a CSV", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Non pudo xerarse a chave API.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Non puderon obterse os modelos", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Non pudo Lerse o contido do portapapeles", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Non pudogardarse a configuración de os modelos", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Falla al actualizar os ajustes", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Falla al subir o Arquivo.", "Features": "Características", "Features Permissions": "Permisos de características", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Arquivo subido correctamente", "Filename": "", "Files": "Arquivos", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "O filtro ahora está desactivado globalmente", "Filter is now globally enabled": "O filtro ahora está habilitado globalmente", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Afunción está habilitada globalmente", "Function Name": "Nombre da función", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Función actualizada exitosamente", "Functions": "Funcions", "Functions allow arbitrary code execution.": "Funcions habilitan aexecución de código arbitrario.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Grupo creado correctamente", "Group deleted successfully": "Grupo eliminado correctamente", "Group Description": "Descripción do grupo", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Retroalimentación háptica", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Actualización importante", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Chave", "Key is required": "", - "Keyboard shortcuts": "Atallos de teclado", "Keyboard Shortcuts": "", "Knowledge": "coñecemento", "Knowledge Access": "Acceso al coñecemento", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "coñecemento actualizado exitosamente.", "Kokoro.js (Browser)": "Kokoro .js (Navegador)", "Kokoro.js Dtype": "Kokoro .js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Última respuesta", "LDAP": "LDAP", - "LDAP server updated": "Servidor LDAP actualizado", "Leaderboard": "Tablero de líderes", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Licencia", + "Lifecycle JSON": "", "Lift List": "", "Light": "Claro", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "Perdido", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Feito por a comunidad de OpenWebUI", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Administrar Pipelines", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Marzo", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Memoria liberada correctamente", "Memory deleted successfully": "Memoria borrada correctamente", "Memory updated successfully": "Memoria actualizada correctamente", + "Merge Accounts by Email": "", "Merge Responses": "Fusionar Respuestas", "Merged Response": "Resposta combinada", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Os mensaxes que envíe despois de xerar su enlace no compartiránse. os usuarios co enlace podrán ver o chat compartido.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "chave API de Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "mais", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Nombra a tua base de coñecementos", "Name, prompt, and model are required": "", "Native": "Nativo", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Non ten distancia disponible", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ningún arquivo fué seleccionado", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "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", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Ninguno", + "Not configured": "", "Not factually correct": "No es correcto en todos os aspectos", "Not helpful": "No útil", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Notificacions", "November": "Noviembre", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Octubre", "Off": "Desactivado", "Okay, Let's Go!": "Bien, ¡Vamos!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED oscuro", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Configuración de Ollama API actualizada", "Ollama Cloud API Key": "", "Ollama Version": "Versión de Ollama", + "Omit": "", "On": "Activado", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Contrasinal ", "Passwords do not match.": "", "Paste Large Text as File": "Pegar texto grande como arquivo", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Documento PDF (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "pendente", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Permiso denegado al acceder a os dispositivos", "Permission denied when accessing microphone": "Permiso denegado al acceder a a micrófono", "Permission denied when accessing microphone: {{error}}": "Permiso denegado al acceder al micrófono: {{error}}", "Permissions": "Permisos", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalización", + "Picture Claim": "", "Pin": "Fijar", "Pin to Sidebar": "", "Pinned": "Fijado", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Por favor llene todos os campos.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Por favor seleccione un modelo primeiro.", "Please select a model.": "Por favor seleccione un modelo.", "Please select a reason": "Por favor seleccione unha razón", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Puerto", "Ports": "", "Positive attitude": "Actitud positiva", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Extraer \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obter un modelo de Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Ler", "Read Aloud": "Ler en voz alta", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Esfuerzo de razonamiento", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Grabar voz", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redireccionándote a a comunidad OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referirse a vostede mismo como \"Usuario\" (por Exemplo, \"O usuario está aprendiendo Español\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Rechazado cuando no debería", "Regenerate": "Regenerar", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Reordenar modelos", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Responder no hilo", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Modelo de reranking", + "Research Knowledge": "", "Reset": "Reiniciar", "Reset All Models": "Reiniciar todos os modelos", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Restablecer imaxe", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Reiniciar Directorio de carga", "Reset Vector Storage/Knowledge": "Reiniciar almacenamiento de vectores/coñecemento", "Reset view": "Reiniciar vista", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Entrada de texto enriquecido para chat", "Role": "Rol", + "Roles Claim": "", "RTL": "RTL", "Run": "Executar", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Xa non se admite gardar registros de chat directamente no almacenamiento da sua navegador. Tómese un momento para descargar y eliminar sus registros de chat haciendo clic no botón a continuación. No te preocupes, puedes volver a importar fácilmente tus registros de chat al backend a través de", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Buscar", "Search a model": "Buscar un modelo", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Chats de búsqueda", "Search Collection": "Buscar Colección", "Search Files": "", + "Search filters": "", "Search Filters": "Filtros de búsqueda", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Buscar Modelos", "Search Notes": "", "Search options": "Opcions de búsqueda", + "Search or add pattern": "", "Search Prompts": "Buscar Prompts", "Search Result Count": "Recuento de resultados de búsqueda", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Buscar en internet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Búsqueda de ferramentas", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "chave API de SearchApi", "SearchApi Engine": "Motor de SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "Semilla", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Seleccionar un modelo base", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Busca un motor", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Enviar", "Send a Message": "Enviar un mensaxe", + "Send events for": "", "Send message": "Enviar mensaxe", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envia `stream_options: { include_usage: true }` en a solicitud.\nLos proveedores admitidos devolverán información de uso do token en a resposta cuando se establezca.", "September": "Septiembre", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "chave API de Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "chave API de Serply", "Serpstack API Key": "chave API de Serpstack", "Server connection failed": "", "Server connection verified": "Conexión do servidor verificada", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Establecer por defecto", "Set as Production": "", "Set embedding model": "Establecer modelo de embedding", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Compartir coa comunidads OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Mostrar", - "Show \"What's New\" modal on login": "Mostrar modal \"Qué hay de novo\" al iniciar sesión", + "Show \"What's New\" Modal on Login": "Mostrar modal \"Qué hay de novo\" al iniciar sesión", "Show Admin Details in Account Pending Overlay": "Mostrar detalles de administración na capa de espera da conta", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Fonte", + "Specific users or groups": "", "Speech Playback Speed": "Velocidad de reproducción de voz", "Speech recognition error: {{error}}": "Error de recoñecemento de voz: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "Configuracions de STT", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "Instruccions do sistema", "System Prompt": "Prompt do sistema", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "xeneración de etiquetas", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divisor de texto", "Text-to-Speech": "", "Text-to-Speech Engine": "Motor de texto a voz", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "O atributo LDAP que se asigna al correo que os usuarios utilizan para iniciar sesión.", "The LDAP attribute that maps to the username that users use to sign in.": "O atributo LDAP que se asigna al nombre de usuario que os usuarios utilizan para iniciar sesión.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "O tablero de líderes está actualmente en beta y podemos axustar os cálculos de clasificación a medida que refinamos o algoritmo.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "O tamaño máximo do arquivo en MB. Si o tamaño do arquivo supera este límite, o arquivo no se subirá.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "O número máximo de arquivos que se pueden utilizar a la vez en chat. Si este límite es superado, os arquivos no se subirán.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Esta es unha característica experimental que puede no funcionar como se esperaba y está sujeto a cambios en cualquier momento.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Para obter mais información sobre os endpoints disponibles, visite nuestra documentación.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Para seleccionar ferramentas aquí, agreguelas al área de trabajo \"Ferramentas\" primeiro.", - "Toast notifications for new updates": "Notificacions emergentes para novas actualizacions", + "Toast Notifications for New Updates": "Notificacions emergentes para novas actualizacions", "Today": "Hoxe", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Demasiado detalliado", @@ -2184,14 +2350,19 @@ "Unpin": "Desanclar", "Unpin from Sidebar": "", "Unravel secrets": "Desentrañar secretos", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Sin etiquetar", "Untitled": "", "Update": "Actualizar", "Update and Copy Link": "Actualizar y copiar enlace", + "Update Email": "", "Update for the latest features and improvements.": "Actualize para as últimas características e mejoras.", + "Update Name": "", "Update password": "Actualizar contrasinal ", + "Update Picture": "", "Update your status": "", "Updated": "Actualizado", "Updated at": "Actualizado en", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Utilice '#' no prompt para cargar y incluir su coñecemento.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "usuario", "User": "Usuario", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Localización do usuario recuperada con éxito.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "Nombre de usuario", + "Username Claim": "", "users": "", "Users": "Usuarios", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Valves actualizados", "Valves updated successfully": "Valves actualizados con éxito", "variable": "variable", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Versión", @@ -2276,11 +2454,14 @@ "Web API": "API Web", "Web Loader Engine": "", "Web Search": "Búsqueda na Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motor de búsqueda web", "Web Search in Chat": "Búsqueda web en chat", "Web Search Query Generation": "xeneración de consultas de búsqueda web", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Configuración do WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Onte", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vostede", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "A sua contribución completa irá directamente o desarrollador do plugin; Open WebUI non toma ningun porcentaxe. Sin embargo, a plataforma de financiación elegida podría ter as suas propias tarifas.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/he-IL/translation.json b/src/lib/i18n/locales/he-IL/translation.json index 8024cad7e3..94522437f6 100644 --- a/src/lib/i18n/locales/he-IL/translation.json +++ b/src/lib/i18n/locales/he-IL/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_two": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_two": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_two": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_two": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_two": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "צ'אטים של {{user}}", "{{webUIName}} Backend Required": "נדרש Backend של {{webUIName}}", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "בקרת גישה", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "חשבון", @@ -75,6 +89,7 @@ "Activity": "", "Add": "הוסף", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "הוסף תיאור קצר אודות אופן הפעולה של מודל זה", "Add a tag": "הוסף תג", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "הוסף קבצים", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "הוסף משתמש", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "מנהל", "Admin Contact Email": "", "Admin Panel": "לוח בקרה למנהל", + "Admin Roles": "", "Admin Settings": "הגדרות מנהל", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "פרמטרים מתקדמים", @@ -126,16 +146,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "כל המודלים נמחקו בהצלחה", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "אפשר עריכת צ'אט", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "אפשר שיתוף צ'אט", "Allow Chat System Prompt": "", @@ -155,9 +180,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "כבר יש לך חשבון?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "תמיד", @@ -176,6 +203,7 @@ "API Base URL": "כתובת URL בסיסית ל-API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "מפתח API", + "API Key / Token": "", "API Key created.": "מפתח API נוצר.", "API Key Endpoint Restrictions": "", "API keys": "מפתחות API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "אודיו", "August": "אוגוסט", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "אוטומטי", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "העתקה אוטומטית של תגובה ללוח", - "Auto-playback response": "תגובת השמעה אוטומטית", + "Auto-Create Groups": "", + "Auto-Playback Response": "תגובת השמעה אוטומטית", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "כתובת URL בסיסית של AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "כלים זמינים", "available users": "משתמשים זמינים", + "Available variables": "", "available!": "זמין!", "Away": "נעדר", "Awful": "", @@ -261,16 +301,17 @@ "Bad Response": "תגובה שגויה", "Banners": "באנרים", "Base Model (From)": "דגם בסיס (מ)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "לפני", "Being lazy": "להיות עצלן", - "Beta": "בטא", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "כיוון צ'אט", + "Chat Direction": "כיוון צ'אט", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "אוסף", + "Collection Field": "", "Collections": "", "Color": "צבע", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "פקודה", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "החיבור נכשל", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "", "Content": "תוכן", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "המשך תגובה", "Continue with {{provider}}": "המשך עם {{provider}}", "Continue with Email": "המשך עם מייל", @@ -497,6 +550,7 @@ "Create new secret key": "צור מפתח סודי חדש", "Create note": "", "Create Note": "יצירת פתק", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "נוצר ב", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "מודל ברירת מחדל", "Default model updated": "המודל המוגדר כברירת מחדל עודכן", "Default permissions": "", @@ -546,6 +600,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "תפקיד משתמש ברירת מחדל", + "Default webhook": "", "Defaults": "", "Delete": "מחק", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "מושבת", "Disconnect OAuth": "", "Discover a function": "", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "גלה, הורד, וחקור הגדרות מודל מוגדרות מראש", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "הצג את שם המשתמש במקום 'אתה' בצ'אט", + "Display the Username Instead of You in the Chat": "הצג את שם המשתמש במקום 'אתה' בצ'אט", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "מסמך", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ערוך משתמש", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "דוא\"ל", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -711,6 +772,7 @@ "Embedding Model Engine": "מנוע מודל הטמעה", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "הפיכת שיתוף קהילה לזמין", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "אפשר הרשמות חדשות", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "מופעל", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ודא שקובץ ה-CSV שלך כולל 4 עמודות בסדר הבא: שם, דוא\"ל, סיסמה, תפקיד.", "Enter {{role}} message here": "הזן הודעת {{role}} כאן", - "Enter a detail about yourself for your LLMs to recall": "הזן פרטים על עצמך כדי שLLMs יזכור", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "הזן חפיפת נתונים", "Enter Chunk Size": "הזן גודל נתונים", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "הזן קודי שפה", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "הזן ציון", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "הזן מפתח API של Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "הזן מפתח API של Serpstack", "Enter server host": "", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "הזן Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "הזן כתובת URL (למשל http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "יצירת מפתח API נכשלה.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "קריאת תוכן הלוח נכשלה", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -991,6 +1082,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1142,6 +1243,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "עדכון חשוב", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "קיצורי מקלדת", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "רישיון", + "Lifecycle JSON": "", "Lift List": "", "Light": "בהיר", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "נוצר על ידי קהילת OpenWebUI", "Make password visible in the user interface": "", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "ניהול צינורות", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "מרץ", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "תגובה ממוזגת", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "הודעות שתשלח לאחר יצירת הקישור לא ישותפו. משתמשים עם כתובת האתר יוכלו לצפות בצ'אט המשותף.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "עוד", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "לא נמצאו תוצאות", "No results found": "לא נמצאו תוצאות", "No search query generated": "לא נוצרה שאילתת חיפוש", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "ללא", + "Not configured": "", "Not factually correct": "לא נכון מבחינה עובדתית", "Not helpful": "", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "התראות", "November": "נובמבר", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "אוקטובר", "Off": "כבוי", "Okay, Let's Go!": "בסדר, בואו נתחיל!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED כהה", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "גרסת Ollama", + "Omit": "", "On": "פועל", "Once": "", "OneDrive": "", @@ -1586,6 +1707,7 @@ "Password": "סיסמה", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "מסמך PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "ממתין", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "ההרשאה נדחתה בעת גישה למיקרופון: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "תאור", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "גישה חיובית", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "משוך \"{{searchValue}}\" מ-Ollama.com", "Pull a model from Ollama.com": "משוך מודל מ-Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "", "Read Aloud": "קרא בקול", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "הקלט קול", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "מפנה אותך לקהילת OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_two": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "נדחה כאשר לא היה צריך", "Regenerate": "הפק מחדש", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "מודל דירוג מחדש", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "איפוס תמונה", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "תפקיד", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "שמירת יומני צ'אט ישירות באחסון הדפדפן שלך אינה נתמכת יותר. אנא הקדש רגע להוריד ולמחוק את יומני הצ'אט שלך על ידי לחיצה על הכפתור למטה. אל דאגה, באפשרותך לייבא מחדש בקלות את יומני הצ'אט שלך לשרת האחורי דרך", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "חפש", "Search a model": "חפש מודל", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "חיפוש צ'אטים", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "חיפוש מודלים", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "חפש פקודות", "Search Result Count": "ספירת תוצאות חיפוש", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1840,7 +1990,6 @@ "Seed": "זרע", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "בחירת מודל בסיס", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "שלח", "Send a Message": "שלח הודעה", + "Send events for": "", "Send message": "שלח הודעה", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "ספטמבר", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "מפתח Serper API", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "מפתח API של Serpstack", "Server connection failed": "", "Server connection verified": "החיבור לשרת אומת", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "הגדר כברירת מחדל", "Set as Production": "", "Set embedding model": "", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "שתף לקהילת OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "הצג", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "מקור", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "שגיאת תחקור שמע: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "הגדרות חקירה של TTS", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "מערכת", + "System events only": "", "System Instructions": "", "System Prompt": "תגובת מערכת", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "מנוע טקסט לדיבור", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "היום", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2191,14 +2361,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "עדכן ושכפל קישור", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "עדכן סיסמה", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "משתמש", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "משתמשים", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "משתנה", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "גרסה", @@ -2283,11 +2465,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "חיפוש באינטרנט", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "מנוע חיפוש באינטרנט", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL Webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "הגדרות WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "אתמול", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "אתה", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/hi-IN/translation.json b/src/lib/i18n/locales/hi-IN/translation.json index dbdd03b8bb..06a8e5545f 100644 --- a/src/lib/i18n/locales/hi-IN/translation.json +++ b/src/lib/i18n/locales/hi-IN/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} की चैट", "{{webUIName}} Backend Required": "{{webUIName}} बैकएंड आवश्यक", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "खाता", @@ -72,6 +83,7 @@ "Activity": "", "Add": "जोड़ें", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "इस मॉडल के बारे में एक संक्षिप्त विवरण जोड़ें", "Add a tag": "एक टैग जोड़े", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "फाइलें जोड़ें", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "उपयोगकर्ता जोड़ें", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "व्यवस्थापक पैनल", + "Admin Roles": "", "Admin Settings": "व्यवस्थापक सेटिंग्स", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "उन्नत पैरामीटर", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "क्या आपके पास पहले से एक खाता मौजूद है?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "एपीआई बेस यूआरएल", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "एपीआई कुंजी", + "API Key / Token": "", "API Key created.": "एपीआई कुंजी बनाई गई", "API Key Endpoint Restrictions": "", "API keys": "एपीआई कुंजियाँ", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "ऑडियो", "August": "अगस्त", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "क्लिपबोर्ड पर प्रतिक्रिया ऑटोकॉपी", - "Auto-playback response": "ऑटो-प्लेबैक प्रतिक्रिया", + "Auto-Create Groups": "", + "Auto-Playback Response": "ऑटो-प्लेबैक प्रतिक्रिया", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 बेस यूआरएल", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "उपलब्ध उपयोगकर्ता", + "Available variables": "", "available!": "उपलब्ध!", "Away": "अनुपस्थित", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "ख़राब प्रतिक्रिया", "Banners": "बैनर", "Base Model (From)": "बेस मॉडल (से)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "पहले", "Being lazy": "आलसी होना", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "चैट दिशा", + "Chat Direction": "चैट दिशा", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "संग्रह", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "कमांड", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "सामग्री", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "प्रतिक्रिया जारी रखें", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "नई गुप्त कुंजी बनाएं", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "किस समय बनाया गया", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "डिफ़ॉल्ट मॉडल", "Default model updated": "डिफ़ॉल्ट मॉडल अपडेट किया गया", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "डिफ़ॉल्ट उपयोगकर्ता भूमिका", + "Default webhook": "", "Defaults": "", "Delete": "डिलीट", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "अक्षम", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "मॉडल प्रीसेट खोजें, डाउनलोड करें और एक्सप्लोर करें", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "चैट में 'आप' के स्थान पर उपयोगकर्ता नाम प्रदर्शित करें", + "Display the Username Instead of You in the Chat": "चैट में 'आप' के स्थान पर उपयोगकर्ता नाम प्रदर्शित करें", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "दस्तावेज़", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "यूजर को संपादित करो", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "ईमेल", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "एंबेडिंग मॉडल इंजन", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "समुदाय साझाकरण सक्षम करें", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "नए साइन अप सक्रिय करें", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "सक्षम", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "सुनिश्चित करें कि आपकी CSV फ़ाइल में इस क्रम में 4 कॉलम शामिल हैं: नाम, ईमेल, पासवर्ड, भूमिका।", "Enter {{role}} message here": "यहां {{role}} संदेश दर्ज करें", - "Enter a detail about yourself for your LLMs to recall": "अपने एलएलएम को याद करने के लिए अपने बारे में एक विवरण दर्ज करें", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "चंक ओवरलैप दर्ज करें", "Enter Chunk Size": "खंड आकार दर्ज करें", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "भाषा कोड दर्ज करें", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "स्कोर दर्ज करें", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Serper API कुंजी दर्ज करें", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "सर्पस्टैक एपीआई कुंजी दर्ज करें", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "शीर्ष K दर्ज करें", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "यूआरएल दर्ज करें (उदा. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "एपीआई कुंजी बनाने में विफल.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "क्लिपबोर्ड सामग्री पढ़ने में विफल", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "महत्वपूर्ण अपडेट", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "कीबोर्ड शॉर्टकट", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "हल्का", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "OpenWebUI समुदाय द्वारा निर्मित", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "पाइपलाइनों का प्रबंधन करें", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "मार्च", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "मिली-जुली प्रतिक्रिया", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "अपना लिंक बनाने के बाद आपके द्वारा भेजे गए संदेश साझा नहीं किए जाएंगे। यूआरएल वाले यूजर्स शेयर की गई चैट देख पाएंगे।", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "और..", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "कोई परिणाम नहीं मिला", "No results found": "कोई परिणाम नहीं मिला", "No search query generated": "कोई खोज क्वेरी जनरेट नहीं हुई", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "कोई नहीं", + "Not configured": "", "Not factually correct": "तथ्यात्मक रूप से सही नहीं है", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "सूचनाएं", "November": "नवंबर", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "अक्टूबर", "Off": "बंद", "Okay, Let's Go!": "ठीक है, चलिए चलते हैं!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED डार्क", "Ollama": "Ollama", "Ollama API": "ओलामा एपीआई", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama Version", + "Omit": "", "On": "चालू", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "पासवर्ड", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF दस्तावेज़ (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "लंबित", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "माइक्रोफ़ोन तक पहुँचने पर अनुमति अस्वीकृत: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "पेरसनलाइज़मेंट", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "सकारात्मक रवैया", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" को Ollama.com से खींचें", "Pull a model from Ollama.com": "Ollama.com से एक मॉडल खींचें", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "जोर से पढ़ें", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "आवाज रिकॉर्ड करना", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "आपको OpenWebUI समुदाय पर पुनर्निर्देशित किया जा रहा है", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "जब ऐसा नहीं होना चाहिए था तो मना कर दिया", "Regenerate": "पुनः जेनरेट", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "रीरैकिंग मोड", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "छवि रीसेट करें", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "भूमिका", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "चैट लॉग को सीधे आपके ब्राउज़र के स्टोरेज में सहेजना अब समर्थित नहीं है। कृपया नीचे दिए गए बटन पर क्लिक करके डाउनलोड करने और अपने चैट लॉग को हटाने के लिए कुछ समय दें। चिंता न करें, आप आसानी से अपने चैट लॉग को बैकएंड पर पुनः आयात कर सकते हैं", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "खोजें", "Search a model": "एक मॉडल खोजें", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "चैट खोजें", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "मॉडल खोजें", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "प्रॉम्प्ट खोजें", "Search Result Count": "खोज परिणामों की संख्या", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "सीड्\u200c", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "एक आधार मॉडल का चयन करें", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "भेज", "Send a Message": "एक संदेश भेजो", + "Send events for": "", "Send message": "मेसेज भेजें", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "सितंबर", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API कुंजी", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "सर्पस्टैक एपीआई कुंजी", "Server connection failed": "", "Server connection verified": "सर्वर कनेक्शन सत्यापित", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "डिफाल्ट के रूप में सेट", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "OpenWebUI समुदाय में साझा करें", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "दिखाओ", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "स्रोत", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "वाक् पहचान त्रुटि: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT सेटिंग्स ", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "सिस्टम", + "System events only": "", "System Instructions": "", "System Prompt": "सिस्टम प्रॉम्प्ट", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "टेक्स्ट-टू-स्पीच इंजन", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "आज", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "अपडेट करें और लिंक कॉपी करें", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "पासवर्ड अपडेट करें", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "उपयोगकर्ता", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "उपयोगकर्ताओं", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "वेरिएबल", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "संस्करण", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "वेब खोज", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "वेब खोज इंजन", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "वेबहुक URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI सेटिंग्स", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "कल", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "आप", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/hr-HR/translation.json b/src/lib/i18n/locales/hr-HR/translation.json index 339209f5fd..8268bf43aa 100644 --- a/src/lib/i18n/locales/hr-HR/translation.json +++ b/src/lib/i18n/locales/hr-HR/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_few": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Razgovori korisnika {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Backend je potreban", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Račun", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Dodaj", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Dodajte kratak opis funkcija ovog modela", "Add a tag": "Dodaj oznaku", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Dodaj datoteke", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Dodaj korisnika", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Admin ploča", + "Admin Roles": "", "Admin Settings": "Admin postavke", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "Napredni parametri", @@ -126,16 +146,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -155,9 +180,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Već imate račun?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -176,6 +203,7 @@ "API Base URL": "Osnovni URL API-ja", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API ključ", + "API Key / Token": "", "API Key created.": "API ključ je stvoren.", "API Key Endpoint Restrictions": "", "API keys": "API ključevi", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Kolovoz", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatsko kopiranje odgovora u međuspremnik", - "Auto-playback response": "Automatska reprodukcija odgovora", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatska reprodukcija odgovora", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 osnovni URL", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "", "available users": "dostupni korisnici", + "Available variables": "", "available!": "dostupno!", "Away": "Odsutan", "Awful": "", @@ -261,16 +301,17 @@ "Bad Response": "Loš odgovor", "Banners": "Baneri", "Base Model (From)": "Osnovni model (Od)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "prije", "Being lazy": "Biti lijen", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Razgovor - smijer", + "Chat Direction": "Razgovor - smijer", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Kolekcija", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Naredba", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Kontaktirajte admina za WebUI pristup", "Content": "Sadržaj", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Nastavi odgovor", "Continue with {{provider}}": "", "Continue with Email": "", @@ -497,6 +550,7 @@ "Create new secret key": "Stvori novi tajni ključ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Stvoreno", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Zadani model", "Default model updated": "Zadani model ažuriran", "Default permissions": "", @@ -546,6 +600,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Zadana korisnička uloga", + "Default webhook": "", "Defaults": "", "Delete": "Izbriši", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Onemogućeno", "Disconnect OAuth": "", "Discover a function": "", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru", + "Display the Username Instead of You in the Chat": "Prikaži korisničko ime umjesto Vas u razgovoru", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Uredi korisnika", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "Embedding - Veličina batch-a", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Embedding model pogon", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Omogući zajedničko korištenje zajednice", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Omogući nove prijave", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Omogućeno", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Provjerite da vaša CSV datoteka uključuje 4 stupca u ovom redoslijedu: Name, Email, Password, Role.", "Enter {{role}} message here": "Unesite {{role}} poruku ovdje", - "Enter a detail about yourself for your LLMs to recall": "Unesite pojedinosti o sebi da bi učitali memoriju u LLM", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Unesite preklapanje dijelova", "Enter Chunk Size": "Unesite veličinu dijela", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Unesite kodove jezika", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Unesite ocjenu", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Unesite Serper API ključ", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Unesite Serply API ključ", "Enter Serpstack API Key": "Unesite Serpstack API ključ", "Enter server host": "", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Unesite Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Unesite URL (npr. http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Neuspješno stvaranje API ključa.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Neuspješno čitanje sadržaja međuspremnika", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Greška kod ažuriranja postavki", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -991,6 +1082,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1142,6 +1243,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Važno ažuriranje", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Tipkovnički prečaci", "Keyboard Shortcuts": "", "Knowledge": "Znanje", "Knowledge Access": "", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Svijetlo", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Izradio OpenWebUI Community", "Make password visible in the user interface": "", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Upravljanje cjevovodima", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Ožujak", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Spojeni odgovor", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Poruke koje pošaljete nakon stvaranja veze neće se dijeliti. Korisnici s URL-om moći će vidjeti zajednički chat.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Više", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Nema rezultata", "No results found": "Nema rezultata", "No search query generated": "Nije generiran upit za pretraživanje", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Ništa", + "Not configured": "", "Not factually correct": "Nije činjenično točno", "Not helpful": "", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Obavijesti", "November": "Studeni", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Listopad", "Off": "Isključeno", "Okay, Let's Go!": "U redu, idemo!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Tamno", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama verzija", + "Omit": "", "On": "Uključeno", "Once": "", "OneDrive": "", @@ -1586,6 +1707,7 @@ "Password": "Lozinka", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokument (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "u tijeku", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Dopuštenje je odbijeno prilikom pristupa medijskim uređajima", "Permission denied when accessing microphone": "Dopuštenje je odbijeno prilikom pristupa mikrofonu", "Permission denied when accessing microphone: {{error}}": "Pristup mikrofonu odbijen: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Prilagodba", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Pozitivan stav", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Povucite \"{{searchValue}}\" s Ollama.com", "Pull a model from Ollama.com": "Povucite model s Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "", "Read Aloud": "Čitaj naglas", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Snimanje glasa", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Preusmjeravanje na OpenWebUI zajednicu", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Nazivajte se \"Korisnik\" (npr. \"Korisnik uči španjolski\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Odbijen kada nije trebao biti", "Regenerate": "Regeneriraj", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Model za ponovno rangiranje", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetiraj sliku", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Poništi upload direktorij", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Uloga", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Spremanje zapisnika razgovora izravno u pohranu vašeg preglednika više nije podržano. Molimo vas da odvojite trenutak za preuzimanje i brisanje zapisnika razgovora klikom na gumb ispod. Ne brinite, možete lako ponovno uvesti zapisnike razgovora u backend putem", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Pretraga", "Search a model": "Pretraži model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Pretraži razgovore", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Pretražite modele", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Pretraga prompta", "Search Result Count": "Broj rezultata pretraživanja", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Alati za pretraživanje", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1840,7 +1990,6 @@ "Seed": "Sjeme", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Odabir osnovnog modela", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Odaberite pogon", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Pošalji", "Send a Message": "Pošaljite poruku", + "Send events for": "", "Send message": "Pošalji poruku", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Rujan", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API ključ", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API ključ", "Serpstack API Key": "Serpstack API API ključ", "Server connection failed": "", "Server connection verified": "Veza s poslužiteljem potvrđena", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Postavi kao zadano", "Set as Production": "", "Set embedding model": "", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Podijeli u OpenWebUI zajednici", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Pokaži", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Izvor", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Pogreška prepoznavanja govora: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "STT postavke", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sustav", + "System events only": "", "System Instructions": "", "System Prompt": "Sistemski prompt", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Stroj za pretvorbu teksta u govor", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ovo je eksperimentalna značajka, možda neće funkcionirati prema očekivanjima i podložna je promjenama u bilo kojem trenutku.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Danas", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2191,14 +2361,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "Ažuriraj i kopiraj vezu", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "Ažuriraj lozinku", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "korisnik", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Korisnici", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "varijabla", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Verzija", @@ -2283,11 +2465,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "Internet pretraga", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Web tražilica", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL webkuke", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI postavke", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Jučer", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vi", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/hu-HU/translation.json b/src/lib/i18n/locales/hu-HU/translation.json index 250a047c61..4bb548330e 100644 --- a/src/lib/i18n/locales/hu-HU/translation.json +++ b/src/lib/i18n/locales/hu-HU/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} rejtett sor", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} beszélgetései", "{{webUIName}} Backend Required": "{{webUIName}} Backend szükséges", "*Prompt node ID(s) are required for image generation": "*Prompt node ID(k) szükségesek a képgeneráláshoz", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Hozzáférés-vezérlés", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Minden felhasználó számára elérhető", "Account": "Fiók", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Hozzáadás", "Add a model ID": "Modell azonosító hozzáadása", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Adj hozzá egy rövid leírást arról, hogy mit csinál ez a modell", "Add a tag": "Címke hozzáadása", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Fájlok hozzáadása", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Felhasználó hozzáadása", "Add User Group": "Felhasználói csoport hozzáadása", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Admin Panel", + "Admin Roles": "", "Admin Settings": "Admin beállítások", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Az adminok mindig hozzáférnek minden eszközhöz; a felhasználóknak modellenként kell eszközöket hozzárendelni a munkaterületen.", "Advanced": "", "Advanced Parameters": "Haladó paraméterek", @@ -123,16 +140,21 @@ "All": "Mind", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Minden modell sikeresen törölve", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Csevegésvezérlők engedélyezése", "Allow Chat Delete": "Csevegés törlésének engedélyezése", "Allow Chat Edit": "Csevegés szerkesztésének engedélyezése", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Felhasználói helyzet engedélyezése", "Allow Voice Interruption in Call": "Hang megszakítás engedélyezése hívás közben", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Engedélyezett végpontok", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Már van fiókod?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatíva a top_p helyett, célja a minőség és változatosság egyensúlyának biztosítása. A p paraméter a token figyelembevételének minimális valószínűségét jelzi a legvalószínűbb token valószínűségéhez képest. Például, ha p=0,05 és a legvalószínűbb token valószínűsége 0,9, a 0,045-nél kisebb értékű logitok kiszűrésre kerülnek.", "Always": "Mindig", @@ -173,6 +197,7 @@ "API Base URL": "API alap URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API kulcs", + "API Key / Token": "", "API Key created.": "API kulcs létrehozva.", "API Key Endpoint Restrictions": "API kulcs végpont korlátozások", "API keys": "API kulcsok", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Biztosan törölni szeretnéd ezt az üzenetet?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Biztosan vissza szeretnéd állítani az összes archivált csevegést?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena modellek", "Artifacts": "Műtermékek", "Asc": "", "Ask": "Kérdezz", "Ask a question": "Kérdezz valamit", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asszisztens", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Hang", "August": "Augusztus", "Auth": "Hitelesítés", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Hitelesítés", "Authentication": "Hitelesítés", "Auto": "Automatikus", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Válasz automatikus másolása a vágólapra", - "Auto-playback response": "Automatikus válasz lejátszás", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatikus válasz lejátszás", "Autocomplete Generation": "Automatikus kiegészítés generálása", "Autocomplete Generation Input Max Length": "Automatikus kiegészítés bemenet maximális hossza", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api hitelesítési karakterlánc", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 alap URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Elérhető eszközök", "available users": "elérhető felhasználók", + "Available variables": "", "available!": "elérhető!", "Away": "Távol", "Awful": "Szörnyű", @@ -258,16 +295,17 @@ "Bad Response": "Rossz válasz", "Banners": "Bannerek", "Base Model (From)": "Alap modell (Forrás)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "előtt", "Being lazy": "Lustaság", - "Beta": "Béta", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 végpont", "Bing Search V7 Subscription Key": "Bing Search V7 előfizetési kulcs", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Bocha Search API kulcs", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Beszélgetés iránya", + "Chat Direction": "Beszélgetés iránya", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Összecsukás", "Collection": "Gyűjtemény", + "Collection Field": "", "Collections": "", "Color": "Szín", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI munkafolyamat", "ComfyUI Workflow Nodes": "ComfyUI munkafolyamat csomópontok", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Parancs", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Kiegészítések", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Csatlakozz saját OpenAI kompatibilis API végpontjaidhoz.", "Connect to your own OpenAPI compatible external tool servers.": "Csatlakozz saját OpenAPI kompatibilis külső eszköszervereidhez.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Kapcsolat sikertelen", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Lépj kapcsolatba az adminnal a WebUI hozzáférésért", "Content": "Tartalom", "Content Extraction Engine": "Tartalom kinyerési motor", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Válasz folytatása", "Continue with {{provider}}": "Folytatás {{provider}} szolgáltatóval", "Continue with Email": "Folytatás emaillel", @@ -493,6 +543,7 @@ "Create new secret key": "Új titkos kulcs létrehozása", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Létrehozva", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Veszélyzóna", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Az alapértelmezett mód szélesebb modellválasztékkal működik az eszközök egyszeri meghívásával a végrehajtás előtt. A natív mód a modell beépített eszközhívási képességeit használja ki, de ehhez a modellnek eredendően támogatnia kell ezt a funkciót.", "Default Model": "Alapértelmezett modell", "Default model updated": "Alapértelmezett modell frissítve", "Default permissions": "Alapértelmezett engedélyek", @@ -542,6 +593,7 @@ "Default to ALL": "Alapértelmezés szerint MIND", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Alapértelmezés szerint szegmentált visszakeresés a fókuszált és releváns tartalom kinyeréséhez, ez a legtöbb esetben ajánlott.", "Default User Role": "Alapértelmezett felhasználói szerep", + "Default webhook": "", "Defaults": "", "Delete": "Törlés", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Letiltva", "Disconnect OAuth": "", "Discover a function": "Funkció felfedezése", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Fedezz fel, tölts le és fedezz fel modell beállításokat", "Discussion channel where access is based on groups and permissions": "", "Display": "Megjelenítés", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Emoji megjelenítése hívásban", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Felhasználónév megjelenítése a 'Te' helyett a beszélgetésben", + "Display the Username Instead of You in the Chat": "Felhasználónév megjelenítése a 'Te' helyett a beszélgetésben", "Displays citations in the response": "Idézetek megjelenítése a válaszban", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Merülj el a tudásban", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Docling szerver URL szükséges.", "Document": "Dokumentum", + "Document ID Field": "", "Document Intelligence": "Dokumentum intelligencia", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Alapértelmezett engedélyek szerkesztése", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Memória szerkesztése", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Felhasználó szerkesztése", "Edit User Group": "Felhasználói csoport szerkesztése", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Vágj bele kalandokba", "Embedding": "Beágyazás", "Embedding Batch Size": "Beágyazási köteg méret", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Beágyazási modell motor", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Kód végrehajtás engedélyezése", "Enable Code Interpreter": "Kód értelmező engedélyezése", "Enable Community Sharing": "Közösségi megosztás engedélyezése", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Engedélyezd a memória zárolást (mlock), hogy a modell adatai ne kerüljenek ki a RAM-ból. Ez az opció a modell munkakészletének oldalait a RAM-ban rögzíti, így nem kerülnek a lemezre. Ez segíthet a teljesítmény fenntartásában az oldalhibák elkerülésével és a gyors adathozzáférés biztosításával.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Engedélyezd a memória leképezést (mmap) a modell adatainak betöltéséhez. Ez az opció lehetővé teszi a rendszer számára, hogy a lemeztárolót a RAM kiterjesztéseként használja, a lemezfájlokat RAM-ban lévőként kezelve. Ez javíthatja a modell teljesítményét a gyorsabb adathozzáférés révén. Azonban nem minden rendszerrel működik megfelelően és jelentős lemezterületet foglalhat.", "Enable Message Queue": "", "Enable Message Rating": "Üzenet értékelés engedélyezése", "Enable Mirostat sampling for controlling perplexity.": "Engedélyezd a Mirostat mintavételezést a perplexitás szabályozásához.", "Enable New Sign Ups": "Új regisztrációk engedélyezése", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Engedélyezve", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "Ideiglenes csevegés kikényszerítése", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Győződj meg róla, hogy a CSV fájl tartalmazza ezt a 4 oszlopot ebben a sorrendben: Név, Email, Jelszó, Szerep.", "Enter {{role}} message here": "Írd ide a {{role}} üzenetet", - "Enter a detail about yourself for your LLMs to recall": "Adj meg egy részletet magadról, amit az LLM-ek megjegyezhetnek", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Add meg a darab átfedést", "Enter Chunk Size": "Add meg a darab méretet", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Add meg vesszővel elválasztott \"token:bias_érték\" párokat (példa: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Add meg a Jupyter URL-t", "Enter Kagi Search API Key": "Add meg a Kagi Search API kulcsot", "Enter Key Behavior": "Add meg a kulcs viselkedését", + "Enter language": "", "Enter language codes": "Add meg a nyelvi kódokat", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Add meg a Mistral API kulcsot", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Add meg a proxy URL-t (pl. https://user:password@host:port)", "Enter reasoning effort": "Add meg az érvelési erőfeszítést", + "Enter Redirect URI": "", "Enter Score": "Add meg a pontszámot", "Enter SearchApi API Key": "Add meg a SearchApi API kulcsot", "Enter SearchApi Engine": "Add meg a SearchApi motort", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Add meg a SerpApi API kulcsot", "Enter SerpApi Engine": "Add meg a SerpApi motort", "Enter Serper API Key": "Add meg a Serper API kulcsot", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Add meg a Serply API kulcsot", "Enter Serpstack API Key": "Add meg a Serpstack API kulcsot", "Enter server host": "Add meg a szerver hosztot", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Add meg a Tika szerver URL-t", "Enter timeout in seconds": "Add meg az időtúllépést másodpercekben", "Enter to Send": "Enter a küldéshez", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Add meg a Top K értéket", "Enter Top K Reranker": "Add meg a Top K újrarangsorolót", "Enter URL (e.g. http://127.0.0.1:7860/)": "Add meg az URL-t (pl. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Értékelések", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API kulcs", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Példa: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Példa: MIND", "Example: mail": "Példa: email", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Exportálás CSV-be", "Export Tools": "", "Export Users": "", "External": "Külső", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Nem sikerült létrehozni az API kulcsot.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Nem sikerült lekérni a modelleket", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nem sikerült olvasni a vágólap tartalmát", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Nem sikerült menteni a modellek konfigurációját", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Nem sikerült frissíteni a beállításokat", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Nem sikerült feltölteni a fájlt.", "Features": "Funkciók", "Features Permissions": "Funkciók engedélyei", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Fájl sikeresen feltöltve", "Filename": "", "Files": "Fájlok", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "A szűrő globálisan letiltva", "Filter is now globally enabled": "A szűrő globálisan engedélyezve", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "A funkció globálisan engedélyezve", "Function Name": "Funkció neve", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funkció sikeresen frissítve", "Functions": "Funkciók", "Functions allow arbitrary code execution.": "A funkciók tetszőleges kód végrehajtását teszik lehetővé.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Csoport sikeresen létrehozva", "Group deleted successfully": "Csoport sikeresen törölve", "Group Description": "Csoport leírása", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Tapintási visszajelzés", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "Azonosító", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Fontos frissítés", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Kulcs", "Key is required": "", - "Keyboard shortcuts": "Billentyűparancsok", "Keyboard Shortcuts": "", "Knowledge": "Tudásbázis", "Knowledge Access": "Tudásbázis hozzáférés", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Tudásbázis nyilvános megosztása", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Tudásbázis sikeresen frissítve", "Kokoro.js (Browser)": "Kokoro.js (Böngésző)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Utolsó válasz", "LDAP": "LDAP", - "LDAP server updated": "LDAP szerver frissítve", "Leaderboard": "Ranglista", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Licenc", + "Lifecycle JSON": "", "Lift List": "", "Light": "Világos", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Helyhozzáférés nem engedélyezett", "Lost": "Elveszett", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Az OpenWebUI közösség által készítve", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Folyamatok kezelése", "Manage Tool Servers": "Eszközszerverek kezelése", "Manage your account information.": "", + "Mapped Source": "", "March": "Március", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Memória sikeresen törölve", "Memory deleted successfully": "Memória sikeresen törölve", "Memory updated successfully": "Memória sikeresen frissítve", + "Merge Accounts by Email": "", "Merge Responses": "Válaszok egyesítése", "Merged Response": "Összevont válasz", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "A link létrehozása után küldött üzenetei nem lesznek megosztva. A URL-lel rendelkező felhasználók megtekinthetik a megosztott beszélgetést.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search API kulcs", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Több", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Nevezd el a tudásbázisodat", "Name, prompt, and model are required": "", "Native": "Natív", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Nincs elérhető távolság", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nincs kiválasztva fájl", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Nincs találat", "No results found": "Nincs találat", "No search query generated": "Nem generálódott keresési lekérdezés", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Nincs", + "Not configured": "", "Not factually correct": "Tényszerűen nem helyes", "Not helpful": "Nem segítőkész", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Értesítések", "November": "November", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth azonosító", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Október", "Off": "Ki", "Okay, Let's Go!": "Rendben, kezdjük!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED sötét", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API beállítások frissítve", "Ollama Cloud API Key": "", "Ollama Version": "Ollama verzió", + "Omit": "", "On": "Be", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Jelszó", "Passwords do not match.": "", "Paste Large Text as File": "Nagy szöveg beillesztése fájlként", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokumentum (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "függőben", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Hozzáférés megtagadva a médiaeszközökhöz", "Permission denied when accessing microphone": "Hozzáférés megtagadva a mikrofonhoz", "Permission denied when accessing microphone: {{error}}": "Hozzáférés megtagadva a mikrofonhoz: {{error}}", "Permissions": "Engedélyek", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API kulcs", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Személyre szabás", + "Picture Claim": "", "Pin": "Rögzítés", "Pin to Sidebar": "", "Pinned": "Rögzítve", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Kérjük, töltse ki az összes mezőt.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Kérjük, először válasszon egy modellt.", "Please select a model.": "Kérjük, válasszon egy modellt.", "Please select a reason": "Kérjük, válasszon egy okot", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Pozitív hozzáállás", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Promptok nyilvános megosztása", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Nyilvános", "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" letöltése az Ollama.com-ról", "Pull a model from Ollama.com": "Modell letöltése az Ollama.com-ról", @@ -1687,21 +1811,29 @@ "Read": "Olvasás", "Read Aloud": "Felolvasás", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Érvelési erőfeszítés", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Hang rögzítése", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Átirányítás az OpenWebUI közösséghez", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Csökkenti a ostobaság generálásának valószínűségét. Magasabb érték (pl. 100) változatosabb válaszokat ad, míg alacsonyabb érték (pl. 10) konzervatívabb lesz.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Hivatkozzon magára \"Felhasználó\"-ként (pl. \"A Felhasználó spanyolul tanul\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Elutasítva, amikor nem kellett volna", "Regenerate": "Újragenerálás", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Modellek átrendezése", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Válasz szálban", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Újrarangsoroló modell", + "Research Knowledge": "", "Reset": "Visszaállítás", "Reset All Models": "Minden modell visszaállítása", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Kép visszaállítása", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Feltöltési könyvtár visszaállítása", "Reset Vector Storage/Knowledge": "Vektor tárhely/tudásbázis visszaállítása", "Reset view": "Nézet visszaállítása", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Formázott szövegbevitel a chathez", "Role": "Szerep", + "Roles Claim": "", "RTL": "RTL", "Run": "Futtatás", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "A csevegési naplók közvetlen mentése a böngésző tárolójába már nem támogatott. Kérjük, szánjon egy percet a csevegési naplók letöltésére és törlésére az alábbi gomb megnyomásával. Ne aggódjon, könnyen újra importálhatja a csevegési naplókat a backend-be", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Keresés", "Search a model": "Modell keresése", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Beszélgetések keresése", "Search Collection": "Gyűjtemény keresése", "Search Files": "", + "Search filters": "", "Search Filters": "Keresési szűrők", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Modellek keresése", "Search Notes": "", "Search options": "Keresési opciók", + "Search or add pattern": "", "Search Prompts": "Promptok keresése", "Search Result Count": "Keresési találatok száma", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Keresés az interneten", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Eszközök keresése", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API kulcs", "SearchApi Engine": "SearchApi motor", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Válasszon egy alapmodellt", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Válasszon egy motort", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Küldés", "Send a Message": "Üzenet küldése", + "Send events for": "", "Send message": "Üzenet küldése", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "A kérésben elküldi a `stream_options: { include_usage: true }` opciót.\nA támogatott szolgáltatók token használati információt küldenek vissza a válaszban, ha be van állítva.", "September": "Szeptember", "SerpApi API Key": "SerpApi API kulcs", "SerpApi Engine": "SerpApi motor", "Serper API Key": "Serper API kulcs", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API kulcs", "Serpstack API Key": "Serpstack API kulcs", "Server connection failed": "", "Server connection verified": "Szerverkapcsolat ellenőrizve", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Beállítás alapértelmezettként", "Set as Production": "", "Set embedding model": "Beágyazási modell beállítása", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Megosztás az OpenWebUI közösséggel", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Megosztási engedélyek", "Show": "Mutat", - "Show \"What's New\" modal on login": "\"Mi újság\" modal megjelenítése bejelentkezéskor", + "Show \"What's New\" Modal on Login": "\"Mi újság\" modal megjelenítése bejelentkezéskor", "Show Admin Details in Account Pending Overlay": "Admin részletek megjelenítése a függő fiók átfedésben", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Modell megjelenítése", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Forrás", + "Specific users or groups": "", "Speech Playback Speed": "Beszéd lejátszási sebesség", "Speech recognition error: {{error}}": "Beszédfelismerési hiba: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT beállítások", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Rendszer", + "System events only": "", "System Instructions": "Rendszer utasítások", "System Prompt": "Rendszer prompt", + "Table": "", "Tag": "", "Tags": "Címkék", "Tags Generation": "Címke generálás", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Szöveg felosztó", "Text-to-Speech": "", "Text-to-Speech Engine": "Szöveg-beszéd motor", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "Az LDAP attribútum, amely a felhasználók bejelentkezéshez használt emailjéhez kapcsolódik.", "The LDAP attribute that maps to the username that users use to sign in.": "Az LDAP attribútum, amely a felhasználók bejelentkezéshez használt felhasználónevéhez kapcsolódik.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "A ranglista jelenleg béta verzióban van, és az algoritmus finomítása során módosíthatjuk az értékelési számításokat.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "A maximális fájlméret MB-ban. Ha a fájlméret meghaladja ezt a limitet, a fájl nem lesz feltöltve.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "A csevegésben egyszerre használható fájlok maximális száma. Ha a fájlok száma meghaladja ezt a limitet, a fájlok nem lesznek feltöltve.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ez egy kísérleti funkció, lehet, hogy nem a várt módon működik és bármikor változhat.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Ez az opció szabályozza, hány token marad meg a kontextus frissítésekor. Például, ha 2-re van állítva, a beszélgetés kontextusának utolsó 2 tokenje megmarad. A kontextus megőrzése segíthet a beszélgetés folytonosságának fenntartásában, de csökkentheti az új témákra való reagálás képességét.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Az elérhető végpontokról további információért látogassa meg dokumentációnkat.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Az eszközkészletek kiválasztásához először adja hozzá őket a \"Tools\" munkaterülethez.", - "Toast notifications for new updates": "Felugró értesítések az új frissítésekről", + "Toast Notifications for New Updates": "Felugró értesítések az új frissítésekről", "Today": "Ma", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Túl bőbeszédű", @@ -2184,14 +2350,19 @@ "Unpin": "Rögzítés feloldása", "Unpin from Sidebar": "", "Unravel secrets": "Titkok megfejtése", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Címkézetlen", "Untitled": "", "Update": "Frissítés", "Update and Copy Link": "Frissítés és link másolása", + "Update Email": "", "Update for the latest features and improvements.": "Frissítsen a legújabb funkciókért és fejlesztésekért.", + "Update Name": "", "Update password": "Jelszó frissítése", + "Update Picture": "", "Update your status": "", "Updated": "Frissítve", "Updated at": "Frissítve ekkor", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Használja a '#' karaktert a prompt bevitelénél a tudásbázis betöltéséhez és felhasználásához.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "felhasználó", "User": "Felhasználó", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Felhasználó helye sikeresen lekérve.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Felhasználói webhookok", "Username": "Felhasználónév", + "Username Claim": "", "users": "", "Users": "Felhasználók", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Szelepek frissítve", "Valves updated successfully": "Szelepek sikeresen frissítve", "variable": "változó", + "Vector Field": "", "Verify Connection": "Kapcsolat ellenőrzése", "Verify SSL Certificate": "", "Version": "Verzió", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "Webes keresés", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Webes keresőmotor", "Web Search in Chat": "Webes keresés a csevegésben", "Web Search Query Generation": "Webes keresési lekérdezés generálása", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI beállítások", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Tegnap", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Ön", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "A teljes hozzájárulása közvetlenül a bővítmény fejlesztőjéhez kerül; az Open WebUI nem vesz le százalékot. Azonban a választott támogatási platformnak lehetnek saját díjai.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "YouTube nyelv", diff --git a/src/lib/i18n/locales/id-ID/translation.json b/src/lib/i18n/locales/id-ID/translation.json index 1d71921cdd..2332a3b4f4 100644 --- a/src/lib/i18n/locales/id-ID/translation.json +++ b/src/lib/i18n/locales/id-ID/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "", "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "Obrolan {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Diperlukan Backend", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -54,6 +61,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Akun", @@ -69,6 +77,7 @@ "Activity": "", "Add": "Tambah", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Tambahkan deskripsi singkat tentang apa yang dilakukan model ini", "Add a tag": "Menambahkan tag", "Add a tag...": "", @@ -81,8 +90,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Menambahkan File", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -97,6 +108,7 @@ "Add to favorites": "", "Add User": "Tambah Pengguna", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -109,7 +121,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Panel Admin", + "Admin Roles": "", "Admin Settings": "Pengaturan Admin", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Admin memiliki akses ke semua alat setiap saat; pengguna memerlukan alat yang ditetapkan per model di ruang kerja.", "Advanced": "", "Advanced Parameters": "Parameter Lanjutan", @@ -120,16 +134,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -149,9 +168,11 @@ "Allow User Location": "Izinkan Lokasi Pengguna", "Allow Voice Interruption in Call": "Izinkan Gangguan Suara dalam Panggilan", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Sudah memiliki akun?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -170,6 +191,7 @@ "API Base URL": "URL Dasar API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Kunci API", + "API Key / Token": "", "API Key created.": "Kunci API dibuat.", "API Key Endpoint Restrictions": "", "API keys": "Kunci API", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -220,14 +247,20 @@ "Audio": "Audio", "August": "Agustus", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Tanggapan Salin Otomatis ke Papan Klip", - "Auto-playback response": "Respons pemutaran otomatis", + "Auto-Create Groups": "", + "Auto-Playback Response": "Respons pemutaran otomatis", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "URL Dasar AUTOMATIC1111", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "", "available users": "pengguna yang tersedia", + "Available variables": "", "available!": "tersedia!", "Away": "Tidak di tempat", "Awful": "", @@ -255,16 +289,17 @@ "Bad Response": "Respons Buruk", "Banners": "Spanduk", "Base Model (From)": "Model Dasar (Dari)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "sebelum", "Being lazy": "Menjadi malas", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -321,7 +356,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Arah obrolan", + "Chat Direction": "Arah obrolan", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Koleksi", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Perintah", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "Hubungi Admin untuk Akses WebUI", "Content": "Konten", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Lanjutkan Tanggapan", "Continue with {{provider}}": "Lanjutkan dengan {{provider}}", "Continue with Email": "", @@ -489,6 +536,7 @@ "Create new secret key": "Buat kunci rahasia baru", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Dibuat di", @@ -506,6 +554,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -528,7 +577,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Model Default", "Default model updated": "Model default diperbarui", "Default permissions": "", @@ -538,6 +586,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Peran Pengguna Default", + "Default webhook": "", "Defaults": "", "Delete": "Menghapus", "Delete {{name}}": "", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Dinonaktifkan", "Disconnect OAuth": "", "Discover a function": "Menemukan sebuah fungsi", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "Menemukan, mengunduh, dan menjelajahi preset model", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Menampilkan Emoji dalam Panggilan", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Menampilkan nama pengguna, bukan Anda di Obrolan", + "Display the Username Instead of You in the Chat": "Menampilkan nama pengguna, bukan Anda di Obrolan", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -626,6 +677,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokumen", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -681,12 +733,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Edit Memori", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Edit Pengguna", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -695,6 +749,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "Menyematkan Ukuran Batch", @@ -703,6 +758,7 @@ "Embedding Model Engine": "Mesin Model Penyematan", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -710,22 +766,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Aktifkan Berbagi Komunitas", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Aktifkan Pendaftaran Baru", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Diaktifkan", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Pastikan file CSV Anda menyertakan 4 kolom dengan urutan sebagai berikut: Nama, Email, Kata Sandi, Peran.", "Enter {{role}} message here": "Masukkan pesan {{role}} di sini", - "Enter a detail about yourself for your LLMs to recall": "Masukkan detail tentang diri Anda untuk diingat oleh LLM Anda", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Masukkan Tumpang Tindih Chunk", "Enter Chunk Size": "Masukkan Ukuran Potongan", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Masukkan kode bahasa", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -800,6 +866,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Masukkan Skor", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Masukkan Kunci API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Masukkan Kunci API Serply", "Enter Serpstack API Key": "Masukkan Kunci API Serpstack", "Enter server host": "", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Masukkan Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Masukkan URL (mis. http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -901,12 +975,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "Gagal membuat API Key.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -931,6 +1012,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -940,6 +1022,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Gagal membaca konten papan klip", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Gagal memperbarui pengaturan", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -983,6 +1068,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filter sekarang dinonaktifkan secara global", "Filter is now globally enabled": "Filter sekarang diaktifkan secara global", @@ -1005,6 +1092,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Fungsi berhasil diperbarui", "Functions": "Fungsi", "Functions allow arbitrary code execution.": "", @@ -1067,7 +1156,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1079,6 +1171,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1109,6 +1202,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1134,6 +1229,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Pembaruan penting", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Pintasan keyboard", "Keyboard Shortcuts": "", "Knowledge": "Pengetahuan", "Knowledge Access": "", @@ -1204,6 +1299,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1220,7 +1317,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1242,6 +1338,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Cahaya", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1265,6 +1362,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Dibuat oleh Komunitas OpenWebUI", "Make password visible in the user interface": "", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "Mengelola Saluran Pipa", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Maret", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "Memori berhasil dihapus", "Memory deleted successfully": "Memori berhasil dihapus", "Memory updated successfully": "Memori berhasil diperbarui", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Tanggapan yang Digabungkan", "Message": "", @@ -1318,9 +1418,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Pesan yang Anda kirim setelah membuat tautan tidak akan dibagikan. Pengguna yang memiliki URL tersebut akan dapat melihat obrolan yang dibagikan.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1373,6 +1476,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Lainnya", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1419,6 +1524,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1431,8 +1537,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Tidak ada file yang dipilih", "No files found": "", @@ -1460,6 +1568,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Tidak ada hasil yang ditemukan", "No results found": "Tidak ada hasil yang ditemukan", "No search query generated": "Tidak ada permintaan pencarian yang dibuat", @@ -1479,6 +1588,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Tidak ada", + "Not configured": "", "Not factually correct": "Tidak benar secara faktual", "Not helpful": "", "Not Registered": "", @@ -1494,20 +1604,25 @@ "Notifications": "Pemberitahuan", "November": "November", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktober", "Off": "Mati", "Okay, Let's Go!": "Oke, Ayo Kita Pergi!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Gelap", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Versi Ollama", + "Omit": "", "On": "Aktif", "Once": "", "OneDrive": "", @@ -1578,6 +1693,7 @@ "Password": "Kata sandi", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Dokumen PDF (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "tertunda", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Izin ditolak saat mengakses perangkat media", "Permission denied when accessing microphone": "Izin ditolak saat mengakses mikrofon", "Permission denied when accessing microphone: {{error}}": "Izin ditolak saat mengakses mikrofon: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalisasi", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Sikap positif", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Tarik \"{{searchValue}}\" dari Ollama.com", "Pull a model from Ollama.com": "Tarik model dari Ollama.com", @@ -1683,21 +1804,28 @@ "Read": "", "Read Aloud": "Baca dengan Keras", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Rekam suara", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Mengarahkan Anda ke Komunitas OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Merujuk diri Anda sebagai \"Pengguna\" (misalnya, \"Pengguna sedang belajar bahasa Spanyol\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Menolak ketika seharusnya tidak", "Regenerate": "Regenerasi", "Regenerate Menu": "", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Model Pemeringkatan Ulang", + "Research Knowledge": "", "Reset": "Atur Ulang", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Atur Ulang Gambar", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Setel Ulang Direktori Unggahan", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Peran", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Menyimpan log obrolan secara langsung ke penyimpanan browser Anda tidak lagi didukung. Mohon luangkan waktu sejenak untuk mengunduh dan menghapus log obrolan Anda dengan mengeklik tombol di bawah ini. Jangan khawatir, Anda dapat dengan mudah mengimpor kembali log obrolan Anda ke backend melalui", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Cari", "Search a model": "Mencari model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1792,6 +1930,7 @@ "Search Chats": "Cari Obrolan", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1806,13 +1945,16 @@ "Search Models": "Cari Model", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Perintah Pencarian", "Search Result Count": "Jumlah Hasil Pencarian", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Alat Pencarian", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1828,7 +1970,6 @@ "Seed": "Benih", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Pilih model dasar", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Pilih mesin", @@ -1866,18 +2007,25 @@ "semantic": "", "Send": "Kirim", "Send a Message": "Kirim Pesan", + "Send events for": "", "Send message": "Kirim pesan", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "September", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Kunci API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Kunci API Serply", "Serpstack API Key": "Kunci API Serpstack", "Server connection failed": "", "Server connection verified": "Koneksi server diverifikasi", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Ditetapkan sebagai default", "Set as Production": "", "Set embedding model": "", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Bagikan ke Komunitas OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Tampilkan", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "Tampilkan Detail Admin di Hamparan Akun Tertunda", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Sumber", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Kesalahan pengenalan suara: {{error}}", "Speech-to-Text": "", @@ -1992,6 +2143,7 @@ "STT Settings": "Pengaturan STT", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2016,8 +2168,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistem", + "System events only": "", "System Instructions": "", "System Prompt": "Permintaan Sistem", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Mesin Teks-ke-Suara", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2075,6 +2234,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ini adalah fitur eksperimental, mungkin tidak berfungsi seperti yang diharapkan dan dapat berubah sewaktu-waktu.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Untuk memilih perangkat di sini, tambahkan ke ruang kerja \"Alat\" terlebih dahulu.", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Hari ini", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2177,14 +2339,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "Memperbarui", "Update and Copy Link": "Perbarui dan Salin Tautan", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "Perbarui kata sandi", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "Diperbarui di", @@ -2211,13 +2378,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "pengguna", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Lokasi pengguna berhasil diambil.", @@ -2227,6 +2399,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Pengguna", "Uses DefaultAzureCredential to authenticate": "", @@ -2240,6 +2413,7 @@ "Valves updated": "Katup diperbarui", "Valves updated successfully": "Katup berhasil diperbarui", "variable": "variabel", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Versi", @@ -2269,11 +2443,14 @@ "Web API": "API Web", "Web Loader Engine": "", "Web Search": "Pencarian Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Mesin Pencari Web", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL pengait web", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Pengaturan WebUI", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Kemarin", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Anda", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/ie-GA/translation.json b/src/lib/i18n/locales/ie-GA/translation.json index 3137af410f..14499f41fb 100644 --- a/src/lib/i18n/locales/ie-GA/translation.json +++ b/src/lib/i18n/locales/ie-GA/translation.json @@ -9,28 +9,36 @@ "[Today at] h:mm A": "[Inniu ag] h:mm A", "[Yesterday at] h:mm A": "[Inné ag] h:mm A", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Skills": "", + "{{COUNT}} Available Skills": "{{COUNT}} Scileanna atá ar Fáil", "{{COUNT}} Available Tools": "{{COUNT}} Uirlisí ar Fáil", "{{COUNT}} characters": "{{COUNT}} carachtair", "{{COUNT}} extracted lines": "{{COUNT}} línte eastósctha", "{{COUNT}} files": "{{COUNT}} comhad", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "Roghnaíodh {{count}} comhad. Ní uaslódálfar ach comhaid nua agus modhnaithe. Bainfear comhaid scriosta. Déanfar struchtúr an fhillteáin a scáthánú. Lean ar aghaidh?_one", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "Roghnaíodh {{count}} comhad. Ní uaslódálfar ach comhaid nua agus modhnaithe. Bainfear comhaid scriosta. Déanfar struchtúr an fhillteáin a scáthánú. Lean ar aghaidh?_other", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} línte folaithe", "{{COUNT}} members": "{{COUNT}} ball", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}} de {{total}} inrochtana_aon", + "{{count}} of {{total}} accessible_other": "{{count}} de {{total}} inrochtana_eile", "{{COUNT}} Replies": "{{COUNT}} Freagra", "{{COUNT}} Rows": "{{COUNT}} Sraitheanna", "{{count}} selected_one": "{{count}} mir roghnaithe", "{{count}} selected_other": "{{count}} míreanna roghnaithe", "{{COUNT}} Sources": "{{COUNT}} Foinsí", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} focail", "{{COUNT}}d_time_ago": "l", "{{COUNT}}h_time_ago": "u", "{{COUNT}}m_time_ago": "n", "{{COUNT}}w_time_ago": "s", "{{COUNT}}y_time_ago": "b", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} ag {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Tá íoslódáil {{model}} curtha ar ceal", "{{modelName}} profile image": "{{modelName}} íomhá próifíle ", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Comhráite {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Ceoldeireadh Riachtanach", "*Prompt node ID(s) are required for image generation": "* Tá ID(anna) nód treorach ag teastáil chun íomhá a ghiniúint", + "1 group": "", "1 hour before": "1 uair an chloig roimhe", "1 Source": "1 Foinse", + "1 user": "", "10 minutes before": "10 nóiméad roimhe", "15 minutes before": "15 nóiméad roimhe", "1m_time_ago": "1 nóiméad ó shin", @@ -57,6 +67,7 @@ "Access Control": "Rialaithe Rochtana", "Access Grants": "Deontais Rochtana", "Access List": "Liosta Rochtana", + "Access prohibited": "", "Access updated": "Rochtain nuashonraithe", "Accessible to all users": "Inrochtana do gach úsáideoir", "Account": "Cuntas", @@ -72,6 +83,7 @@ "Activity": "Gníomhaíocht", "Add": "Cuir", "Add a model ID": "Cuir aitheantas samhail leis", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Cuir cur síos gairid leis faoi na rudaí a dhéanann an tsamhail seo", "Add a tag": "Cuir clib leis", "Add a tag...": "Cuir clib leis...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Cuir Treoir Shaincheaptha leis", "Add description": "Cuir cur síos leis", "Add Details": "Cuir Sonraí leis", + "Add durable context for future chats": "", "Add Files": "Cuir Comhaid", "Add Image": "Cuir Íomhá leis", + "Add Knowledge Connection": "", "Add location": "Cuir suíomh leis", "Add Member": "Cuir Ball leis", "Add Members": "Cuir Baill leis", @@ -100,6 +114,7 @@ "Add to favorites": "Cuir le Ceanáin", "Add User": "Cuir Úsáideoir leis", "Add User Group": "Cuir Grúpa Úsáideoirí leis", + "Add webhook": "", "Add webpage": "Cuir leathanach gréasáin leis", "Add your Open Terminal URL and API key in Settings → Integrations.": "Cuir d’URL Teirminéal Oscailte agus d’eochair API leis i Socruithe → Comhtháthúcháin.", "Additional Config": "Cumraíocht Bhreise", @@ -112,7 +127,9 @@ "Admin": "Riarachán", "Admin Contact Email": "Ríomhphost Teagmhála Riarthóra", "Admin Panel": "Painéal Riaracháin", + "Admin Roles": "", "Admin Settings": "Socruithe Riaracháin", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Bíonn rochtain ag riarthóirí ar na huirlisí go léir i gcónaí; teastaíonn ó úsáideoirí uirlisí a shanntar de réir samhail sa spás oibre.", "Advanced": "Ardleibhéil", "Advanced Parameters": "Paraiméadair Casta", @@ -123,16 +140,21 @@ "All": "Gach", "All chats have been unarchived.": "Tá na comhráite uile díchartlannaithe.", "All day": "An lá ar fad", + "All events": "", "All models are now hidden": "Tá na samhlacha uile i bhfolach anois", "All models are now visible": "Tá na samhlacha uile le feiceáil anois", "All models deleted successfully": "Scriosadh na samhlacha go léir go rathúil", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Gach am", "All Users": "Gach Úsáideoir", + "All users and system events": "", "Allow Call": "Ceadaigh Glao", "Allow Chat Controls": "Ceadaigh Rialuithe Comhrá", "Allow Chat Delete": "Ceadaigh Comhrá a Scriosadh", "Allow Chat Edit": "Ceadaigh Eagarthóireacht Comhrá", "Allow Chat Export": "Ceadaigh Easpórtáil Comhrá", + "Allow Chat Import": "", "Allow Chat Params": "Ceadaigh Paraiméadair Comhrá", "Allow Chat Share": "Ceadaigh Comhroinnt Comhrá", "Allow Chat System Prompt": "Ceadaigh Treoir Chórais Comhrá", @@ -152,9 +174,11 @@ "Allow User Location": "Ceadaigh Suíomh Úsáideora", "Allow Voice Interruption in Call": "Ceadaigh Briseadh Guth i nGlao", "Allow Web Upload": "Ceadaigh Uaslódáil Gréasáin", + "Allowed Domains": "", "Allowed Endpoints": "Críochphointí Ceadaithe", "Allowed File Extensions": "Síneadh Comhaid Ceadaithe", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Síneadh comhaid ceadaithe le haghaidh uaslódála. Deighil il-síneadh le camóga. Fág folamh do gach cineál comhaid.", + "Allowed Roles": "", "Already have an account?": "Tá cuntas agat cheana féin?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Rogha eile seachas an top_p, agus tá sé mar aidhm aige cothromaíocht cáilíochta agus éagsúlachta a chinntiú. Léiríonn an paraiméadar p an dóchúlacht íosta go mbreithneofar comhartha, i gcoibhneas le dóchúlacht an chomhartha is dóichí. Mar shampla, le p=0.05 agus dóchúlacht 0.9 ag an comhartha is dóichí, déantar logits le luach níos lú ná 0.045 a scagadh amach.", "Always": "I gcónaí", @@ -173,6 +197,7 @@ "API Base URL": "URL Bonn API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL Bunúsach API do sheirbhís Marcóra Datalab. Réamhshocraithe go: https://www.datalab.to/api/v1/marker", "API Key": "Eochair API", + "API Key / Token": "", "API Key created.": "Cruthaíodh Eochair API.", "API Key Endpoint Restrictions": "Príomhshrianta Críochphointe API", "API keys": "Eochracha API", @@ -198,17 +223,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "An bhfuil tú cinnte gur mian leat na comhráite go léir a scriosadh? Ní féidir an gníomh seo a chealú.", "Are you sure you want to delete this channel?": "An bhfuil tú cinnte gur mhaith leat an cainéal seo a scriosadh?", "Are you sure you want to delete this connection? This action cannot be undone.": "An bhfuil tú cinnte gur mian leat an nasc seo a scriosadh? Ní féidir an gníomh seo a chealú.", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "An bhfuil tú cinnte gur mian leat an t-eolaire seo a scriosadh?", "Are you sure you want to delete this memory? This action cannot be undone.": "An bhfuil tú cinnte gur mian leat an chuimhne seo a scriosadh? Ní féidir an gníomh seo a chealú.", "Are you sure you want to delete this message?": "An bhfuil tú cinnte gur mhaith leat an teachtaireacht seo a scriosadh?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "An bhfuil tú cinnte gur mian leat an leagan seo a scriosadh? Déanfar leaganacha linbh a athnascadh le tuismitheoir an leagain seo.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "An bhfuil tú cinnte gur mian leat é seo a scriosadh?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "An bhfuil tú cinnte gur mhaith leat gach comhrá cartlainne a dhíchartlannú?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Samhlacha Réimse", "Artifacts": "Déantáin", "Asc": "Ardú", "Ask": "Fiafraigh", "Ask a question": "Cuir ceist", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Cúntóir", "Async Embedding Processing": "Próiseáil Leabaithe Asyncrónach", "At time of event": "Tráth na hócáide", @@ -223,14 +253,20 @@ "Audio": "Fuaim", "August": "Lúnasa", "Auth": "Údarú", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Fíordheimhnigh", "Authentication": "Fíordheimhniú", "Auto": "Uath", "Auto (Random)": "Uathoibríoch (Randamach)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Freagra AutoCopy go Gearrthaisce", - "Auto-playback response": "Freagra uathsheinm", + "Auto-Create Groups": "", + "Auto-Playback Response": "Freagra uathsheinm", "Autocomplete Generation": "Giniúint Uathchríochnaithe", "Autocomplete Generation Input Max Length": "Ionchur Giniúint Uathchríochnaithe Uasfhad", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Uathoibríoch1111", "AUTOMATIC1111 Api Auth String": "UATHOIBRÍOCH1111 Api Auth Teaghrán", "AUTOMATIC1111 Base URL": "UATHOIBRÍOCH1111 Bun URL", @@ -245,9 +281,10 @@ "Automations": "Uathoibrithe", "Available list": "Liosta atá ar fáil", "Available models": "Samhlacha atá ar fáil", - "Available Skills": "", + "Available Skills": "Scileanna atá ar Fáil", "Available Tools": "Uirlisí ar Fáil", "available users": "úsáideoirí ar fáil", + "Available variables": "", "available!": "ar fáil!", "Away": "As láthair", "Awful": "Uafásach", @@ -258,16 +295,17 @@ "Bad Response": "Droch-fhreagra", "Banners": "Meirgí", "Base Model (From)": "Samhail Bunúsach (Ó)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Luasaíonn Taisce an Liosta Bunsamhail de rochtain trí bhunmhúnlaí a fháil ach amháin ag am tosaithe nó ar shocruithe a shábháil-níos tapúla, ach b'fhéidir nach dtaispeánfar athruithe bonnsamhail le déanaí.", "Bearer": "Iompróir", "before": "roimh", "Being lazy": "A bheith leisciúil", - "Beta": "Béite", "Bing": "Bing", "Bing Search V7 Endpoint": "Cuardach Bing V7 Críochphointe", "Bing Search V7 Subscription Key": "Eochair Síntiúis Bing Cuardach V7", "Bio": "Beathaisnéis", "Birth Date": "Dáta Breithe", + "Blocked Groups": "", "BM25 Weight": "Meáchan BM25", "Bocha Search API Key": "Eochair API Cuardach Bocha", "Bold": "Trom", @@ -324,7 +362,7 @@ "Chat Completions": "Críochnuithe Comhrá", "Chat Conversation": "Caint agus comhrá", "Chat deleted.": "Scriosadh an comhrá.", - "Chat direction": "Treo comhrá", + "Chat Direction": "Treo comhrá", "Chat exported successfully": "Easpórtáil an chomhrá go rathúil", "Chat History": "Stair Chomhrá", "Chat ID": "Aitheantas Comhrá", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Cainéal comhoibrithe ina mbíonn daoine páirteach mar bhaill", "Collapse": "Laghdaigh", "Collection": "Bailiúchán", + "Collection Field": "", "Collections": "Bailiúcháin", "Color": "Dath", "ComfyUI": "ComfyUI", @@ -405,17 +444,19 @@ "ComfyUI Workflow": "Sreabhadh Oibre ComfyUI", "ComfyUI Workflow Nodes": "Nóid Sreabhadh Oibre ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "Aitheantóirí Nóid scartha le camóga (m.sh. 1 nó 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Liosta síntí comhad scartha le camóga a láimhseálfaidh MinerU (m.sh. pdf, docx, pptx, xlsx)", "command": "ordú", "Command": "Ordú", "Comment": "Trácht", "Commit Message": "Teachtaireacht Tiomnaithe", "Community Reviews": "Léirmheasanna Pobail", - "Comparing with knowledge base...": "", + "Compacting context": "", + "Comparing with knowledge base...": "Ag comparáid le bunachar eolais...", "Completions": "Críochnaithe", "Compress Images in Channels": "Comhbhrúigh Íomhánna i gCainéil", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Suimeanna seiceála á ríomh ({{count}} comhad)_aon", + "Computing checksums ({{count}} files)_other": "Suimeanna seiceála á ríomh ({{count}} comhad)_eile", "Concurrent Requests": "Iarrataí Comhthéime", "Config": "Cumraíocht", "Config imported successfully": "Cumraíocht allmhairithe go rathúil", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Ceangail le cásanna Open Terminal. Beidh rochtain ag gach úsáideoir ar bhrabhsáil comhad agus uirlisí críochfoirt trí na freastalaithe seo.", "Connect to your own OpenAI compatible API endpoints.": "Ceangail le do chríochphointí API atá comhoiriúnach le OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Ceangail le do fhreastalaithe uirlisí seachtracha atá comhoiriúnach le OpenAPI.", + "Connected": "", "Connected ({{type}})": "Ceangailte ({{type}})", "Connection failed": "Theip ar an gceangal", "Connection lost. Reconnecting...": "Ceangal caillte. Ag athcheangal...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Déan teagmháil le Riarachán le haghaidh Rochtana WebUI", "Content": "Ábhar", "Content Extraction Engine": "Inneall Eastóscadh Ábhar", + "Content Field": "", "Content lengths (character counts only)": "Fad an ábhair (líon na gcarachtar amháin)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Comharthaí Comhthéacs", + "Continue": "", "Continue Response": "Leanúint ar aghaidh", "Continue with {{provider}}": "Lean ar aghaidh le {{provider}}", "Continue with Email": "Lean ar aghaidh le Ríomhphost", @@ -493,6 +543,7 @@ "Create new secret key": "Cruthaigh eochair rúnda nua", "Create note": "Cruthaigh nóta", "Create Note": "Cruthaigh Nóta", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Cruthaigh leideanna sceidealaithe a ritheann go huathoibríoch ar bhonn athfhillteach.", "Create your first note by clicking on the plus button below.": "Cruthaigh do chéad nóta trí chliceáil ar an gcnaipe móide thíos.", "Created at": "Cruthaithe ag", @@ -510,6 +561,7 @@ "Custom Gender": "Inscne Saincheaptha", "Custom Parameter Name": "Ainm Paraiméadair Saincheaptha", "Custom Parameter Value": "Luach Paraiméadair Saincheaptha", + "Custom range": "", "Daily": "Laethúil", "Daily Messages": "Teachtaireachtaí Laethúla", "Danger Zone": "Crios Contúirte", @@ -532,7 +584,6 @@ "Default Features": "Gnéithe Réamhshocraithe", "Default Filters": "Scagairí Réamhshocraithe", "Default Group": "Grúpa Réamhshocraithe", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Oibríonn an mód réamhshocraithe le raon níos leithne samhlacha trí uirlisí a ghlaoch uair amháin roimh an bhforghníomhú. Úsáideann an modh dúchasach cumais ionsuite glaoite uirlisí an samhail, ach éilíonn sé go dtacóidh an tsamhail leis an ngné seo go bunúsach.", "Default Model": "Samhail Réamhshocrú", "Default model updated": "Nuashonraithe samhail réamhshocraithe", "Default permissions": "Ceadanna réamhshocraithe", @@ -542,20 +593,21 @@ "Default to ALL": "Réamhshocrú do GACH", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Réamhshocrú maidir le haisghabháil deighilte d'eastóscadh ábhar dírithe agus ábhartha, moltar é seo i bhformhór na gcásanna.", "Default User Role": "Ról Úsáideora Réamhshocraithe", + "Default webhook": "", "Defaults": "Réamhshocruithe", "Delete": "Scrios", "Delete {{name}}": "Scrios {{name}}", "Delete a model": "Scrios samhail", "Delete All": "Scrios Gach Rud", "Delete All Chats": "Scrios Gach Comhrá", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Scrios gach ábhar atá sa chomhadlann seo", "Delete all contents inside this folder": "Scrios an t-ábhar go léir atá sa fhillteán seo", "Delete automation?": "Scrios an t-uathoibriú?", "Delete calendar": "Scrios féilire", "Delete Calendar": "Scrios Féilire", "Delete Chat": "Scrios Comhrá", "Delete chat?": "Scrios comhrá?", - "Delete directory?": "", + "Delete directory?": "Scrios an t-eolaire?", "Delete Event": "Scrios Imeacht", "Delete File": "Scrios Comhad", "Delete folder?": "Scrios fillteán?", @@ -592,16 +644,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Ligeann Connections Direct d'úsáideoirí ceangal lena gcríochphointí API féin atá comhoiriúnach le OpenAI.", "Direct Message": "Teachtaireacht Dhíreach", "Direct Tool Servers": "Freastalaithe Uirlisí Díreacha", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Eolaire cruthaithe.", + "Directory deleted.": "Eolaire scriosta.", + "Directory moved.": "Eolaire bogtha.", + "Directory name": "Ainm an eolaire", + "Directory renamed.": "Athainmníodh an eolaire.", "Directory selection was cancelled": "Cealaíodh roghnú an eolaire", "Disable All": "Díchumasaigh Gach Rud", "Disable Code Interpreter": "Díchumasaigh Léirmhínitheoir Cód", "Disable Image Extraction": "Díchumasaigh Eastóscadh Íomhá", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Díchumasaigh eastóscadh íomhánna ón PDF. Má tá Úsáid LLM cumasaithe, cuirfear fotheidil leis na híomhánna go huathoibríoch. Is é Bréag an réamhshocrú.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Díchumasaithe", "Disconnect OAuth": "Dícheangail OAuth", "Discover a function": "Faigh amach feidhm", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Faigh amach, íoslódáil agus réamhshocruithe samhail a iniúchadh", "Discussion channel where access is based on groups and permissions": "Cainéal plé ina bhfuil rochtain bunaithe ar ghrúpaí agus ceadanna", "Display": "Taispeáin", - "Display chat title in tab": "Taispeáin teideal an chomhrá sa chluaisín", + "Display Chat Title in Tab": "Taispeáin teideal an chomhrá sa chluaisín", "Display Emoji in Call": "Taispeáin Emoji i nGlao", "Display Multi-model Responses in Tabs": "Taispeáin Freagraí Ilsamhlacha i gCluaisíní", - "Display the username instead of You in the Chat": "Taispeáin an t-ainm úsáideora in ionad Tú sa Comhrá", + "Display the Username Instead of You in the Chat": "Taispeáin an t-ainm úsáideora in ionad Tú sa Comhrá", "Displays citations in the response": "Taispeánann sé luanna sa fhreagra", "Displays status updates (e.g., web search progress) in the response": "Taispeánann sé nuashonruithe stádais (m.sh., dul chun cinn cuardaigh gréasáin) sa fhreagra", "Dive into knowledge": "Léim isteach eolas", @@ -630,6 +684,7 @@ "Docling Parameters": "Paraiméadair Docling", "Docling Server URL required.": "URL Freastalaí Doling ag teastáil.", "Document": "Doiciméad", + "Document ID Field": "", "Document Intelligence": "Faisnéise Doiciméad", "Document Intelligence endpoint required.": "Críochphointe Faisnéise Doiciméad ag teastáil.", "Document Intelligence Model": "Múnla Faisnéise Doiciméad", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Cuir Ceadanna Réamhshocraithe in Eagar", "Edit Folder": "Cuir Fillteán in Eagar", "Edit Image": "Cuir Íomhá in Eagar", + "Edit Knowledge Connection": "", "Edit Last Message": "Cuir an Teachtaireacht Dheiridh in Eagar", "Edit Memory": "Cuir Cuimhne in Eagar", "Edit Prompt": "Cuir an Treoir in Eagar", "Edit Terminal Connection": "Cuir Nasc Críochfoirt in Eagar", "Edit User": "Cuir Úsáideoir in eagar", "Edit User Group": "Cuir Grúpa Úsáideoirí in Eagar", + "Edit webhook": "", "Edit workflow.json content": "Cuir ábhar workflow.json in eagar", "edited": "curtha in eagar", "Edited": "Curtha in eagar", @@ -699,14 +756,16 @@ "Eject model": "Samhail Díbirt", "ElevenLabs": "Eleven Labs", "Email": "Ríomhphost", + "Email Claim": "", "Embark on adventures": "Dul ar eachtraí", "Embedding": "Leabú", "Embedding Batch Size": "Méid Baisc Leabaith", "Embedding Concurrent Requests": "Iarratais Chomhuaineacha a Leabú", "Embedding Model": "Samhail Leabháilte", "Embedding Model Engine": "Inneall Samhail Leabaithe", - "Emoji": "", - "Emojis": "Emoji", + "Emoji": "Emoji", + "Emojis": "Emojis", + "Empty": "", "Empty message": "Teachtaireacht folamh", "Enable All": "Cumasaigh Gach Rud", "Enable API Keys": "Cumasaigh Eochracha API", @@ -714,22 +773,27 @@ "Enable Code Execution": "Cumasaigh Forghníomhú Cód", "Enable Code Interpreter": "Cumasaigh Ateangaire Cóid", "Enable Community Sharing": "Cumasaigh Comhroinnt Pobail", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Cumasaigh Glasáil Cuimhne (mlock) chun cosc a chur ar shonraí samhail a bheith á malartú amach as RAM. Glasálann an rogha seo tacar oibre leathanach an tsamhail isteach sa RAM, rud a chinntíonn nach ndéanfar iad a mhalartú amach chuig diosca. Is féidir leis seo cabhrú le feidhmíocht a choinneáil trí lochtanna leathanaigh a sheachaint agus rochtain thapa ar shonraí a chinntiú.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Cumasaigh Mapáil Cuimhne (mmap) chun sonraí samhla a lódáil. Ligeann an rogha seo don chóras stóráil diosca a úsáid mar leathnú ar RAM trí chomhaid diosca a chóireáil amhail is dá mba i RAM iad. Is féidir leis seo feidhmíocht na samhla a fheabhsú trí rochtain níos tapúla ar shonraí a cheadú. Mar sin féin, d'fhéadfadh sé nach n-oibreoidh sé i gceart le gach córas agus féadfaidh sé méid suntasach spáis diosca a ithe.", "Enable Message Queue": "Cumasaigh an Scuaine Teachtaireachtaí", "Enable Message Rating": "Cumasaigh Rátáil Teachtai", "Enable Mirostat sampling for controlling perplexity.": "Cumasaigh sampláil Mirostat chun seachrán a rialú.", "Enable New Sign Ups": "Cumasaigh Clárúcháin Nua", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Cumasaigh, díchumasaigh nó saincheap na clibeanna réasúnaíochta a úsáideann an tsamhail. Úsáideann \"Cumasaithe\" clibeanna réamhshocraithe, múchann \"Díchumasaithe\" clibeanna réasúnaíochta, agus ligeann \"Saincheaptha\" duit do chlibeanna tosaigh agus deiridh féin a shonrú.", "Enabled": "Cumasaithe", "End Tag": "Clib Deiridh", + "Endpoint": "", "Endpoint URL": "URL críochphointe", "Enforce Temporary Chat": "Cuir Comhrá Sealadach i bhfeidhm", "Enhance": "Feabhsaigh", "Enrich Hybrid Search Text": "Saibhrigh Téacs Cuardaigh Hibrideach", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Déan cinnte go bhfuil 4 cholún san ord seo i do chomhad CSV: Ainm, Ríomhphost, Pasfhocal, Ról.", "Enter {{role}} message here": "Cuir isteach teachtaireacht {{role}} anseo", - "Enter a detail about yourself for your LLMs to recall": "Cuir isteach mionsonraí fút féin chun do LLManna a mheabhrú", "Enter a title for the pending user info overlay. Leave empty for default.": "Cuir isteach teideal don fhorleagan faisnéise úsáideora atá ar feitheamh. Fág folamh don réamhshocrú.", "Enter a watermark for the response. Leave empty for none.": "Cuir isteach comhartha uisce don fhreagra. Fág folamh mura bhfuil aon cheann ann.", "Enter additional headers in JSON format": "Cuir ceanntásca breise isteach i bhformáid JSON", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Iontráil Spriocmhéid Íosta an Bhrúid", "Enter Chunk Overlap": "Cuir isteach Chunk Forluí", "Enter Chunk Size": "Cuir isteach Méid an Smután", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Cuir isteach péirí camóg-scartha \"comhartha:luach laofachta\" (mar shampla: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Cuir isteach ábhar don fhorleagan faisnéise úsáideora atá ar feitheamh. Fág folamh don réamhshocrú.", "Enter coordinates (e.g. 51.505, -0.09)": "Cuir isteach comhordanáidí (m.sh. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Cuir isteach URL Jupyter", "Enter Kagi Search API Key": "Cuir isteach Eochair Kagi Cuardach API", "Enter Key Behavior": "Iontráil Iompar Eochair", + "Enter language": "", "Enter language codes": "Cuir isteach cóid teanga", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Cuir isteach Eochair API Linkup", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Cuir isteach Eochair API MinerU", "Enter Mistral API Base URL": "Cuir isteach URL Bunúsach API Mistral", "Enter Mistral API Key": "Cuir isteach Eochair API Mistral", @@ -804,6 +873,7 @@ "Enter prompt here.": "Cuir isteach an treoir anseo.", "Enter proxy URL (e.g. https://user:password@host:port)": "Cuir isteach URL seachfhreastalaí (m.sh. https://user:password@host:port)", "Enter reasoning effort": "Cuir isteach iarracht réasúnaíochta", + "Enter Redirect URI": "", "Enter Score": "Iontráil Scór", "Enter SearchApi API Key": "Cuir isteach Eochair API SearchAPI", "Enter SearchApi Engine": "Cuir isteach Inneall SearchAPI", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Cuir isteach Eochair API SerpApi", "Enter SerpApi Engine": "Cuir isteach Inneall SerpApi", "Enter Serper API Key": "Cuir isteach Eochair API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Cuir isteach Eochair API Serply", "Enter Serpstack API Key": "Cuir isteach Eochair API Serpstack", "Enter server host": "Cuir isteach óstach freastalaí", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Cuir isteach URL freastalaí Tika", "Enter timeout in seconds": "Cuir isteach an t-am istigh i soicindí", "Enter to Send": "Iontráil chun Seol", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Cuir isteach Barr K", "Enter Top K Reranker": "Cuir isteach Barr K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Iontráil URL (m.sh. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Earráid: Tá samhail leis an ID '{{modelId}}' ann cheana féin. Roghnaigh ID difriúil le dul ar aghaidh.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Earráid: Ní féidir ID an tSamhail a fhágáil folamh. Cuir isteach ID bailí le dul ar aghaidh.", "Evaluations": "Meastóireachtaí", + "Event": "", "Event created": "Imeacht cruthaithe", "Event deleted": "Imeacht scriosta", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Teideal na hócáide", "Event updated": "Nuashonraithe ag an imeacht", + "Events": "", "Exa API Key": "Eochair Exa API", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Sampla: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Sampla: GACH", "Example: mail": "Sampla: ríomhphost", @@ -905,12 +982,18 @@ "Export Config": "Easpórtáil Cumraíocht", "Export Models": "Easpórtáil Samhlacha", "Export Prompts": "Easpórtáil Treoracha", + "Export Skills": "", "Export to CSV": "Easpórtáil go CSV", "Export Tools": "Easpórtáil Uirlisí", "Export Users": "Easpórtáil Úsáideoirí", "External": "Seachtrach", + "External connection not found.": "", "External Document Loader URL required.": "URL Luchtaitheora Doiciméad Seachtrach ag teastáil.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Samhail Tasc Seachtracha", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Eochair API Luchtaire Gréasáin Sheachtrach", "External Web Loader URL": "URL Luchtóra Gréasáin Sheachtraigh", "External Web Search API Key": "Eochair API Cuardaigh Gréasáin Sheachtrach", @@ -921,13 +1004,14 @@ "Failed to archive chat.": "Theip ar an gcomhrá a chartlannú.", "Failed to attach file": "Theip ar an gcomhad a cheangal", "Failed to clear status": "Theip ar an stádas a ghlanadh", - "Failed to compare files.": "", + "Failed to compare files.": "Theip ar chomhaid a chur i gcomparáid.", "Failed to connect to {{URL}} OpenAPI tool server": "Theip ar nascadh le {{URL}} freastalaí uirlisí OpenAPI", "Failed to connect to {{URL}} terminal server": "Theip ar cheangal le freastalaí críochfoirt {{URL}}", "Failed to copy link": "Theip ar an nasc a chóipeáil", "Failed to create API Key.": "Theip ar an eochair API a chruthú.", "Failed to delete calendar": "Theip ar an bhféilire a scriosadh", "Failed to delete note": "Theip ar an nóta a scriosadh", + "Failed to delete webhook": "", "Failed to disconnect": "Theip ar dhícheangal", "Failed to download image": "Theip ar an íomhá a íoslódáil", "Failed to extract content from the file: {{error}}": "Theip ar an ábhar a bhaint as an gcomhad: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Theip ar shamhlacha a fháil", "Failed to generate title": "Theip ar an teideal a ghiniúint", "Failed to import models": "Theip ar samhail a iompórtáil", + "Failed to load chat": "", "Failed to load chat preview": "Theip ar réamhamharc comhrá a lódáil", "Failed to load DOCX file. Please try downloading it instead.": "Theip ar an gcomhad DOCX a luchtú. Déan iarracht é a íoslódáil ina ionad.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Theip ar an gcomhad Excel/CSV a lódáil. Déan iarracht é a íoslódáil ina ionad.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Theip ar an gcomhrá a bhogadh", "Failed to process URL: {{url}}": "Theip ar phróiseáil an URL: {{url}}", "Failed to read clipboard contents": "Theip ar ábhar gearrthaisce a lé", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Theip ar an mball a bhaint", "Failed to render diagram": "Theip ar an léaráid a rindreáil", "Failed to render visualization": "Theip ar an léirshamhlú a rindreáil", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Theip ar chumraíocht na samhlacha a shábháil", "Failed to save policy: {{error}}": "Theip ar an mbeartas a shábháil: {{error}}", "Failed to save terminal servers": "Theip ar fhreastalaithe críochfoirt a shábháil", + "Failed to save webhook": "", "Failed to unshare chat.": "Theip ar an gcomhrá a dhíroinnt.", "Failed to update settings": "Theip ar shocruithe a nuashonrú", "Failed to update status": "Theip ar an stádas a nuashonrú", + "Failed to update webhook": "", "Failed to upload file.": "Theip ar uaslódáil an chomhaid.", "Features": "Gnéithe", "Features Permissions": "Ceadanna Gnéithe", @@ -975,18 +1063,20 @@ "File content updated successfully.": "D'éirigh le hábhar an chomhaid a nuashonrú.", "File Context": "Comhthéacs Comhaid", "File deleted successfully.": "Scriosadh an comhad go rathúil.", - "File Extensions": "", + "File Extensions": "Síneadh Comhaid", "File Mode": "Mód Comhad", - "File moved.": "", + "File moved.": "Bogadh an comhad.", "File name": "Ainm comhaid", "File not found.": "Níor aimsíodh an comhad.", "File removed successfully.": "D'éirigh le baint an chomhaid.", - "File renamed.": "", + "File renamed.": "Athainmníodh an comhad.", "File size should not exceed {{maxSize}} MB.": "Níor chóir go mbeadh méid an chomhaid níos mó ná {{maxSize}} MB.", "File Upload": "Uaslódáil Comhaid", "File uploaded successfully": "D'éirigh le huaslódáil an chomhaid", "Filename": "Ainm comhaid", "Files": "Comhaid", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Scagaire", "Filter is now globally disabled": "Tá an scagaire faoi mhíchumas go domhanda", "Filter is now globally enabled": "Tá an scagaire cumasaithe go domhanda anois", @@ -1009,6 +1099,7 @@ "Folder options": "Roghanna fillteáin", "Folder updated successfully": "Nuashonraíodh an fillteán go rathúil", "Folders": "Fillteáin", + "Folders Sharing": "", "Follow up": "Leanúint suas", "Follow Up Generation": "Giniúint Leantach", "Follow Up Generation Prompt": "Treoir Giniúna Leantach", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Tá feidhm cumasaithe go domhanda anois", "Function Name": "Ainm Feidhme", "Function Name Filter List": "Liosta Scagaire Ainm Feidhme", + "Function starter": "", "Function updated successfully": "Feidhm nuashonraithe", "Functions": "Feidhmeanna", "Functions allow arbitrary code execution.": "Ceadaíonn feidhmeanna forghníomhú cód treallach.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Eangach", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Cainéal Grúpa", + "Group Claim": "", "Group created successfully": "Grúpa cruthaithe go rathúil", "Group deleted successfully": "D'éirigh le scriosadh an ghrúpa", "Group Description": "Cur síos ar an nGrúpa", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Aiseolas Haptic", + "Header variables": "", "Headers": "Ceanntásca", "Headers must be a valid JSON object": "Ní mór ceanntásca a bheith ina réad JSON bailí", "Height": "Airde", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "Ní féidir carachtair \":\" nó \"|\" a bheith san ID", "ID copied to clipboard": "Aitheantas cóipeáilte chuig an ghearrthaisce", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Am Teorann Díomhaoin", "iframe Sandbox Allow Forms": "iframe Bosca Gainimh Foirmeacha Ceadaithe", "iframe Sandbox Allow Same Origin": "ceadaigh Bosca Gainimh iframe an Bunús Céanna", @@ -1138,6 +1236,7 @@ "Import From Link": "Iompórtáil Ó Nasc", "Import Models": "Iompórtáil Samhlacha", "Import Prompts": "Iompórtáil Treoracha", + "Import Skills": "", "Import successful": "D'éirigh leis an allmhairiú", "Import Tools": "Uirlisí Iompórtála", "Important Update": "Nuashonrú tábhachtach", @@ -1195,12 +1294,11 @@ "Keep in Sidebar": "Coinnigh sa Bharra Taobh", "Key": "Eochair", "Key is required": "Tá eochair ag teastáil", - "Keyboard shortcuts": "Aicearraí méarchlár", "Keyboard Shortcuts": "Aicearraí Méarchláir", "Knowledge": "Eolas", "Knowledge Access": "Rochtain Eolais", "Knowledge Base": "Bunachar Eolais", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "Tá an bunachar eolais athshocraithe", "Knowledge created successfully.": "Eolas cruthaithe go rathúil.", "Knowledge deleted successfully.": "D'éirigh leis an eolas a scriosadh.", "Knowledge Description": "Cur Síos Eolais", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Ainm an Eolais", "Knowledge Public Sharing": "Roinnt Faisnéise Poiblí", "Knowledge Sharing": "Comhroinnt Eolais", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "D'éirigh leis an eolas a nuashonrú", "Kokoro.js (Browser)": "Kokoro.js (Brabhsálaí)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Rith dheireanach", "Last reply": "Freagra deiridh", "LDAP": "LDAP", - "LDAP server updated": "Nuashonraíodh freastalaí LDAP", "Leaderboard": "An Clár Ceannairí", "Learn more": "Foghlaim níos mó", "Learn More": "Foghlaim Tuilleadh", @@ -1246,11 +1345,12 @@ "Legacy": "Oidhreacht", "lexical": "leicseach", "License": "Ceadúnas", + "Lifecycle JSON": "", "Lift List": "Liosta Ardaitheoirí", "Light": "Solas", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Teorainn a chur le fiosrúcháin chuardaigh chomhuaineacha. 0 = gan teorainn (réamhshocraithe). Socraigh go 1 le haghaidh forghníomhú seicheamhach (molta do APIanna le teorainneacha ráta dochta cosúil le sraith saor in aisce Brave).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Cuireann sé teorainn le líon na n-iarratas leabaithe comhuaineach. Socraigh go 0 le haghaidh neamhtheoranta.", - "Linkup API Key": "", + "Linkup API Key": "Eochair API Linkup", "List": "Liosta", "List calendars, search, create, update, and delete calendar events": "Liostaigh féilirí, cuardaigh, cruthaigh, nuashonraigh agus scrios imeachtaí féilire", "Listening...": "Éisteacht...", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Ní cheadaítear rochtain suímh", "Lost": "Cailleadh", "Low": "Íseal", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Déanta ag OpenWebUI Community", "Make password visible in the user interface": "Déan an focal faire le feiceáil sa chomhéadan úsáideora", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Bainistigh píblín", "Manage Tool Servers": "Bainistigh Freastalaithe Uirlisí", "Manage your account information.": "Bainistigh faisnéis do chuntais.", + "Mapped Source": "", "March": "Márta", "Markdown": "Marcáil síos", "Markdown Header Text Splitter": "Scoilteoir Téacs Ceanntásc Markdown", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Cuimhne glanta go rathúil", "Memory deleted successfully": "Cuimhne scriosta go rathúil", "Memory updated successfully": "Cuimhne nuashonraithe", + "Merge Accounts by Email": "", "Merge Responses": "Cumaisc Freagraí", "Merged Response": "Freagra Cumaiscthe", "Message": "Teachtaireacht", @@ -1322,9 +1425,12 @@ "messages": "teachtaireachtaí", "Messages": "Teachtaireachtaí", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Ní roinnfear teachtaireachtaí a sheolann tú tar éis do nasc a chruthú. Beidh úsáideoirí leis an URL in ann féachaint ar an gcomhrá roinnte.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (pearsanta)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (obair/scoil)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "nóim", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Eochair API MinerU ag teastáil le haghaidh mód Cloud API.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Roinnt Samhlacha", "Mojeek": "Mojeek", "Mojeek Search API Key": "Eochair API Cuardach Mojeek", + "Monday – Friday": "", "Month": "Mí", "Monthly": "Míosúil", "More": "Tuilleadh", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Cuir ainm ar do bhunachar eolais", "Name, prompt, and model are required": "Tá ainm, treoir agus samhail riachtanach", "Native": "Dúchasach", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Choíche", "New": "Nua", "New Automation": "Uathoibriú Nua", @@ -1401,8 +1509,8 @@ "New calendar": "Féilire nua", "New Calendar": "Féilire Nua", "New Chat": "Comhrá Nua", - "New directory": "", - "New Directory": "", + "New directory": "Eolaire nua", + "New Directory": "Eolaire Nua", "New Event": "Imeacht Nua", "New File": "Comhad Nua", "New Folder": "Fillteán Nua", @@ -1423,6 +1531,7 @@ "Next run": "An chéad rith eile", "No access grants. Private to you.": "Gan aon deontais rochtana. Príobháideach duitse.", "No activity data": "Gan aon sonraí gníomhaíochta", + "No additional headers are sent unless configured.": "", "No authentication": "Gan fíordheimhniú", "No automations found": "Níor aimsíodh aon uathoibrithe", "No chats found": "Ní bhfuarthas aon chomhráite", @@ -1435,8 +1544,10 @@ "No data": "Gan aon sonraí", "No data found": "Níor aimsíodh aon sonraí", "No distance available": "Níl achar ar fáil", + "No event webhooks configured.": "", "No execution logs available yet": "Níl aon logaí forghníomhaithe ar fáil go fóill", "No expiration can pose security risks.": "Ní féidir le haon dáta éaga rioscaí slándála a chruthú.", + "No external knowledge sources configured.": "", "No feedback found": "Níor aimsíodh aon aiseolas", "No file selected": "Níl aon chomhad roghnaithe", "No files found": "Níor aimsíodh aon chomhaid", @@ -1448,13 +1559,13 @@ "No HTML, CSS, or JavaScript content found.": "Níor aimsíodh aon ábhar HTML, CSS nó JavaScript.", "No inference engine with management support found": "Níor aimsíodh aon inneall tátail le tacaíocht bhainistíochta", "No kernel": "Gan aon eithne", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "Níl aon bhunachair eolais inrochtana", "No knowledge bases found.": "Níor aimsíodh aon bhunachair eolais.", "No knowledge found": "Níor aimsíodh aon eolas", "No limit": "Gan teorainn", "No memories to clear": "Gan cuimhní cinn a ghlanadh", "No model IDs": "Gan aon aitheantóirí samhail", - "No models accessible": "", + "No models accessible": "Níl aon samhlacha inrochtana", "No models available": "Níl aon samhlacha ar fáil", "No models found": "Níor aimsíodh samhlacha", "No models selected": "Uimh samhlacha roghnaithe", @@ -1464,6 +1575,7 @@ "No output items": "Gan aon mhíreanna aschuir", "No pinned messages": "Gan aon teachtaireachtaí bioráilte", "No prompts found": "Níor aimsíodh aon treoracha", + "No Repeat": "", "No results": "Níl aon torthaí le fáil", "No results found": "Níl aon torthaí le fáil", "No search query generated": "Ní ghintear aon cheist cuardaigh", @@ -1475,7 +1587,7 @@ "No Terminal connection configured.": "Gan nasc teirminéal cumraithe.", "No terminal connections configured.": "Gan aon naisc teirminéal cumraithe.", "No tool server connections configured.": "Níl aon naisc freastalaí uirlisí cumraithe.", - "No tools accessible": "", + "No tools accessible": "Gan aon uirlisí inrochtana", "No tools found": "Níor aimsíodh aon uirlisí", "No users were found.": "Níor aimsíodh aon úsáideoirí.", "No valves": "Gan comhlaí", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Gan aon crúcaí gréasáin fós", "Node Ids": "Aitheantas Nóid", "None": "Dada", + "Not configured": "", "Not factually correct": "Níl sé ceart go fírineach", "Not helpful": "Gan a bheith cabhrach", "Not Registered": "Gan Clárú", @@ -1498,24 +1611,29 @@ "Notifications": "Fógraí", "November": "Samhain", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statach)", "OAuth ID": "Aitheantas OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL Freastalaí OAuth", "OAuth session disconnected": "Seisiún OAuth dícheangailte", "October": "Deireadh Fómhair", "Off": "As", "Okay, Let's Go!": "Ceart go leor, Déanaimis Téigh!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Dorcha", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Nuashonraíodh socruithe Olama API", "Ollama Cloud API Key": "Eochair API Ollama Cloud", "Ollama Version": "Leagan Ollama", + "Omit": "", "On": "Ar", "Once": "Uair amháin", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Gníomhach le linn Mód Gutha amháin.", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Gníomhach amháin nuair a bhíonn an socrú \"Greamaigh Téacs Mór mar Chomhad\" casta air.", "Only active when the chat input is in focus and an LLM is generating a response.": "Gníomhach ach amháin nuair a bhíonn an t-ionchur comhrá i bhfócas agus nuair a bhíonn LLM ag giniúint freagra.", "Only active when the chat input is in focus.": "Gníomhach ach amháin nuair a bhíonn an t-ionchur comhrá i bhfócas.", @@ -1582,26 +1700,30 @@ "Password": "Pasfhocal", "Passwords do not match.": "Ní hionann na pasfhocail.", "Paste Large Text as File": "Greamaigh Téacs Mór mar Chomhad", + "Path": "", "Path copied": "Cosán cóipeáilte", "Paused": "Sosaithe", "PDF document (.pdf)": "Doiciméad PDF (.pdf)", "PDF Extract Images (OCR)": "Íomhánna Sliocht PDF (OCR)", "PDF Loader Mode": "Mód Luchtaithe PDF", - "pdf, docx, pptx, xlsx": "", + "pdf, docx, pptx, xlsx": "pdf, docx, pptx, xlsx", "pending": "ar feitheamh", "Pending": "Ar feitheamh", + "Pending Accounts": "", "Pending User Overlay Content": "Ábhar Forleagan Úsáideora atá ar Feitheamh", "Pending User Overlay Title": "Teideal Forleagan Úsáideora atá ar Feitheamh", "Permission denied when accessing media devices": "Cead diúltaithe nuair a bhíonn rochtain agat", "Permission denied when accessing microphone": "Cead diúltaithe agus tú ag rochtain ar", "Permission denied when accessing microphone: {{error}}": "Cead diúltaithe agus tú ag teacht ar mhicreafón: {{error}}", "Permissions": "Ceadanna", + "Permissions reset to defaults": "", "Perplexity API Key": "Eochair API Perplexity", "Perplexity Model": "Samhail Perplexity", "Perplexity Search API URL": "URL API Cuardaigh Measctha", "Perplexity Search Context Usage": "Úsáid Chomhthéacs Cuardaigh Mearbhall", "Persistent": "Dianseasmhach", "Personalization": "Pearsantú", + "Picture Claim": "", "Pin": "Bioráin", "Pin to Sidebar": "Bioráin chuig an mBarra Taoibh", "Pinned": "Bioránaithe", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Líon isteach gach réimse le do thoil.", "Please register the OAuth client": "Cláraigh an cliant OAuth le do thoil", "Please save the connection to persist the OAuth client information and do not change the ID": "Sábháil an nasc le go gcoimeádfar faisnéis an chliaint OAuth agus ná hathraigh an ID.", - "Please select a model first.": "Roghnaigh samhail ar dtús le do thoil.", "Please select a model.": "Roghnaigh samhail le do thoil.", "Please select a reason": "Roghnaigh cúis le do thoil", "Please select a valid JSON file": "Roghnaigh comhad JSON bailí le do thoil", "Please select at least one user for Direct Message channel.": "Roghnaigh úsáideoir amháin ar a laghad don chainéal Teachtaireachtaí Díreacha.", "Please wait until all files are uploaded.": "Fan go dtí go mbeidh na comhaid go léir uaslódáilte.", "Policy ID": "Aitheantas Polasaí", + "Policy ID is required": "", "Port": "Port", "Ports": "Poirt", "Positive attitude": "Dearcadh dearfach", @@ -1649,7 +1771,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "Úsáidtear Aitheantas Réimír chun coinbhleachtaí le naisc eile a sheachaint trí réimír a chur le haitheantas na samhla - fág folamh le díchumasú", "Prevent File Creation": "Cosc a chur ar Chruthú Comhad", "Preview": "Réamhamharc", - "Preview Access": "", + "Preview Access": "Rochtain Réamhamhairc", "Previous 30 days": "30 lá roimhe seo", "Previous 7 days": "7 lá roimhe seo", "Previous message": "Teachtaireacht roimhe seo", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Comhroinnt Phoiblí Treoracha", "Prompts Sharing": "Comhroinnt Treoracha", "Provider": "Soláthraí", + "Provider Name": "", + "Provider URL": "", "Public": "Poiblí", "Pull \"{{searchValue}}\" from Ollama.com": "Tarraing \"{{searchValue}}\" ó Ollama.com", "Pull a model from Ollama.com": "Tarraing samhail ó Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Léigh", "Read Aloud": "Léigh Ard", "Read more →": "Léigh tuilleadh →", + "Read only": "", "Read Only": "Léigh Amháin", "Read-Only Access": "Rochtain Léite Amháin", "Reason": "Cúis", "Reasoning Effort": "Iarracht Réasúnúcháin", "Reasoning Tags": "Clibeanna Réasúnaíochta", "Reasoning text...": "Téacs réasúnaíochta...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Úsáidte le Déanaí", "Reconnected": "Athcheangailte", "Record": "Taifead", "Record voice": "Taifead guth", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Tú a atreorú chuig OpenWebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Laghdaíonn sé an dóchúlacht go giniúint nonsense. Tabharfaidh luach níos airde (m.sh. 100) freagraí níos éagsúla, agus beidh luach níos ísle (m.sh. 10) níos coimeádaí.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Tagairt duit féin mar \"Úsáideoir\" (m.sh., \"Tá an úsáideoir ag foghlaim Spáinnis\")", "Reference Chats": "Comhráite Tagartha", "Refresh": "Athnuachan", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Diúltaíodh nuair nár chóir dó", "Regenerate": "Athghiniúint", "Regenerate Menu": "Athghin an Roghchlár", @@ -1727,27 +1859,34 @@ "Remove from favorites": "Bain de Ceanáin", "Remove image": "Bain íomhá", "Remove Model": "Bain an tSamhail", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "Ag baint {{count}} comhad seanchaite..._aon", + "Removing {{count}} stale files..._other": "Ag baint {{count}} comhad seanchaite..._eile", "Rename": "Athainmnigh", "Renamed to {{name}}": "Athainmnithe go {{name}}", "Render Markdown in Assistant Messages": "Rindreáil Markdown i dTeachtaireachtaí Cúntóra", "Render Markdown in Previews": "Rindreáil Markdown i Réamhamhairc", "Render Markdown in User Messages": "Rindreáil Markdown i dTeachtaireachtaí Úsáideora", "Reorder Models": "Athordú na Samhlacha", + "Repeat": "", "Repeats": "Athdhéantar", "Reply": "Freagra", "Reply in Thread": "Freagra i Snáithe", "Reply to thread...": "Freagra ar an snáithe...", "Replying to {{NAME}}": "Ag freagairt do {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "riachtanach", "Reranking Batch Size": "Méid an Bhaisc Athrangaithe", "Reranking Engine": "Inneall Athrangaithe", "Reranking Model": "Samhail Athrangaithe", + "Research Knowledge": "", "Reset": "Athshocraigh", "Reset All Models": "Athshocraigh Gach Samhail", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Athshocraigh Íomhá", - "Reset knowledge base?": "", + "Reset knowledge base?": "Athshocraigh an bonn eolais?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Athshocraigh Eolaire Uas", "Reset Vector Storage/Knowledge": "Athshocraigh Stóráil/Eolas Veicteoir", "Reset view": "Athshocraigh amharc", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "Aisghafa 1 fhoinse", "Rich Text Input for Chat": "Ionchur Saibhir Téacs don Chomhrá", "Role": "Ról", + "Roles Claim": "", "RTL": "RTL", "Run": "Rith", "Run All": "Rith Gach Rud", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ní thacaítear le logaí comhrá a shábháil go díreach chuig stóráil do bhrabhsálaí Tóg nóiméad chun do logaí comhrá a íoslódáil agus a scriosadh trí chliceáil an cnaipe thíos. Ná bíodh imní ort, is féidir leat do logaí comhrá a athiompórtáil go héasca chuig an gcúltaca trí", "Schedule": "Sceideal", "Scheduled time must be in the future": "Ní mór don am sceidealaithe a bheith sa todhchaí", + "Scopes": "", "Scroll On Branch Change": "Scrollaigh ar Athrú Brainse", "Scroll to Top": "Scrollaigh go Barr", "Search": "Cuardaigh", "Search a model": "Cuardaigh samhail", + "Search actions": "", "Search all emojis": "Cuardaigh gach emoji", "Search and manage user memories": "Cuardaigh agus bainistigh cuimhní úsáideora", "Search and view user chat history": "Cuardaigh agus féach ar stair comhrá úsáideora", @@ -1798,6 +1940,7 @@ "Search Chats": "Cuardaigh Comhráite", "Search Collection": "Bailiúchán Cuardaigh", "Search Files": "Cuardaigh Comhaid", + "Search filters": "", "Search Filters": "Scagairí Cuardaigh", "search for archived chats": "cuardach le haghaidh comhráite gcartlann", "search for folders": "cuardach le haghaidh fillteáin", @@ -1812,13 +1955,16 @@ "Search Models": "Cuardaigh Samhlacha", "Search Notes": "Cuardaigh Nótaí", "Search options": "Roghanna cuardaigh", + "Search or add pattern": "", "Search Prompts": "Treoracha Cuardaigh", "Search Result Count": "Líon Torthaí Cuardaigh", + "Search skills": "", "Search Skills": "Scileanna Cuardaigh", - "Search skills...": "", "Search the internet": "Cuardaigh an tIdirlíon", "Search the web and fetch URLs": "Cuardaigh an gréasán agus faigh URLanna", + "Search tools": "", "Search Tools": "Uirlisí Cuardaigh", + "Search users or groups": "", "Search, view, and manage user notes": "Cuardaigh, féach ar agus bainistigh nótaí úsáideora", "SearchApi API Key": "Eochair API SearchAPI", "SearchApi Engine": "Inneall SearchAPI", @@ -1834,7 +1980,6 @@ "Seed": "Síol", "Select": "Roghnaigh", "Select {{modelName}} model": "Roghnaigh samhail {{modelName}}", - "Select a base model": "Roghnaigh samhail bhunúsach", "Select a base model (e.g. llama3, gpt-4o)": "Roghnaigh bunsamhail (m.sh. lama3, gpt-4o)", "Select a conversation to preview": "Roghnaigh comhrá le réamhamharc a fháil air", "Select a engine": "Roghnaigh inneall", @@ -1872,18 +2017,25 @@ "semantic": "séimeantach", "Send": "Seol", "Send a Message": "Seol Teachtaireacht", + "Send events for": "", "Send message": "Seol teachtaireacht", "Send now": "Seol anois", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Seolann `stream_options: { include_usage: true }` san iarratas.\nTabharfaidh soláthraithe a fhaigheann tacaíocht faisnéis úsáide chomharthaí ar ais sa fhreagra nuair a bheidh sé socraithe.", "September": "Meán Fómhair", "SerpApi API Key": "Eochair API SerpApi", "SerpApi Engine": "Inneall SerpApi", "Serper API Key": "Serper API Eochair", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Eochair API Serply", "Serpstack API Key": "Eochair API Serpstack", "Server connection failed": "Theip ar cheangal leis an bhfreastalaí", "Server connection verified": "Ceangal freastalaí fíoraithe", + "Service Account": "", "Session": "Seisiún", + "Session expired. Please sign in again.": "", "Set as default": "Socraigh mar réamhshocraithe", "Set as Production": "Socraigh mar Tháirgeadh", "Set embedding model": "Socraigh samhail leabaithe", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Cóipeáladh an nasc comhroinnte chuig an ghearrthaisce.", "Share to Open WebUI Community": "Comhroinn le Pobal OpenWebUI", "Share your background and interests": "Roinn do chúlra agus do leasanna", + "Shared": "", "Shared Chats": "Comhráite Comhroinnte", "Shared with you": "Roinnte leat", "Sharing Permissions": "Ceadanna a Roinnt", "Show": "Taispeáin", - "Show \"What's New\" modal on login": "Taispeáin módúil \"Cad atá Nua\" ar logáil isteach", + "Show \"What's New\" Modal on Login": "Taispeáin módúil \"Cad atá Nua\" ar logáil isteach", "Show Admin Details in Account Pending Overlay": "Taispeáin Sonraí Riaracháin sa Chuntas ar Feitheamh Forleagan", "Show All": "Taispeáin Gach Rud", "Show all ({{COUNT}} characters)": "Taispeáin gach ceann ({{COUNT}} carachtar)", "Show Files": "Taispeáin Comhaid", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Taispeáin Barra Uirlisí Formáidithe", "Show image preview": "Taispeáin réamhamharc íomhá", "Show Model": "Taispeáin Samhail", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Foinse", + "Specific users or groups": "", "Speech Playback Speed": "Luas Athsheinm Urlabhra", "Speech recognition error: {{error}}": "Earráid aitheantais cainte: {{error}}", "Speech-to-Text": "Urlabhra-go-Téacs", @@ -1999,6 +2154,7 @@ "STT Settings": "Socruithe STT", "Stylized PDF Export": "Easpórtáil PDF Stílithe", "Su_day_of_week": "Domhnaigh", + "Sub Claim": "", "Submit question": "Cuir ceist isteach", "Submit suggestion": "Cuir moladh isteach", "Subtitle": "Fotheideal", @@ -2013,8 +2169,8 @@ "Switch to JSON editor": "Athraigh go heagarthóir JSON", "Switch to visual editor": "Athraigh go dtí an t-eagarthóir amhairc", "Sync": "Sioncrónaigh", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Sioncrónaigh eolaire áitiúil leis an mbunachar eolais seo. Ní uaslódálfar ach comhaid nua agus modhnaithe. Déanfar struchtúr an eolaire a scáthánú.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Sioncrónú críochnaithe: {{added}} curtha leis, {{modified}} modhnaithe, {{deleted}} scriosta, {{unmodified}} gan athrú", "Sync Complete!": "Sioncrónú críochnaithe!", "Sync directory": "Eolaire sioncronaithe", "Sync Failed": "Theip ar an sioncrónú", @@ -2023,8 +2179,10 @@ "Syncing...": "Ag sioncrónú...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Ní shioncrónaíonn sé ach comhráite le nuashonruithe tar éis do stampa ama sioncrónaithe deireanach. Díchumasaigh chun gach comhrá a athshioncrónú.", "System": "Córas", + "System events only": "", "System Instructions": "Treoracha Córas", "System Prompt": "Treoir Chóras", + "Table": "", "Tag": "Clib", "Tags": "Clibeanna", "Tags Generation": "Giniúint Clibeanna", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Comhrá Sealadach de réir Réamhshocraithe", "Terminal": "Teirminéal", "Terminal servers saved": "Freastalaithe teirminéal sábháilte", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Scoilteoir Téacs", "Text-to-Speech": "Téacs-go-Caint", "Text-to-Speech Engine": "Inneall téacs-go-labhra", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Teanga an fhuaime ionchuir. Má sholáthraítear an teanga ionchuir i bhformáid ISO-639-1 (e.g. en), feabhsófar cruinneas agus moill. Fág bán é chun an teanga a bhrath go huathoibríoch.", "The LDAP attribute that maps to the mail that users use to sign in.": "An tréith LDAP a mhapálann don ríomhphost a úsáideann úsáideoirí chun síniú isteach.", "The LDAP attribute that maps to the username that users use to sign in.": "An tréith LDAP a mhapálann don ainm úsáideora a úsáideann úsáideoirí chun síniú isteach.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Tá an clár ceannairí i béite faoi láthair, agus d'fhéadfaimis na ríomhanna rátála a choigeartú de réir mar a dhéanfaimid an t-algartam a bheachtú.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Uasmhéid an chomhaid i MB. Má sháraíonn méid an chomhaid an teorainn seo, ní uaslódófar an comhad.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "An líon uasta na gcomhaid is féidir a úsáid ag an am céanna i gcomhrá. Má sháraíonn líon na gcomhaid an teorainn seo, ní uaslódófar na comhaid.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "An fhormáid aschuir don téacs. Is féidir é a úsáid mar 'json', 'markdown', nó 'html'. Is é 'markdown' an réamhshocrú.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Tá an fillteán seo folamh", "This is a default user permission and will remain enabled.": "Is cead úsáideora réamhshocraithe é seo agus fanfaidh sé cumasaithe.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Is gné turgnamhach í seo, b'fhéidir nach bhfeidhmeoidh sé mar a bhíothas ag súil leis agus tá sé faoi réir athraithe ag am ar bith.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Níl an tsamhail seo ar fáil go poiblí. Roghnaigh samhail eile le do thoil.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Rialaíonn an rogha seo cé chomh fada a fhanfaidh an tsamhail luchtaithe sa chuimhne i ndiaidh an iarratais (réamhshocraithe: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Rialaíonn an rogha seo cé mhéad comhartha a chaomhnaítear agus an comhthéacs á athnuachan. Mar shampla, má shocraítear go 2 é, coinneofar an 2 chomhartha dheireanacha de chomhthéacs an chomhrá. Is féidir le comhthéacs a chaomhnú cabhrú le leanúnachas comhrá a choinneáil, ach d'fhéadfadh sé laghdú a dhéanamh ar an gcumas freagairt do thopaicí nua.", @@ -2094,7 +2258,7 @@ "This will delete all models including custom models": "Scriosfaidh sé seo gach samhail lena n-áirítear samhlacha saincheaptha", "This will delete all models including custom models and cannot be undone.": "Scriosfaidh sé seo gach samhail, lena n-áirítear samhlacha saincheaptha, agus ní féidir é a chealú.", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Scriosfaidh sé seo an féilire \"{{name}}\" agus a chuid imeachtaí go léir go buan. Ní féidir an gníomh seo a chealú.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Bainfear gach comhad agus eolaire as an mbunachar eolais seo leis seo. Ní féidir an gníomh seo a chealú.", "Thorough explanation": "Míniú críochnúil", "Thought": "Smaoineamh", "Thought for {{DURATION}}": "Smaoineamh ar {{DURATION}}", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Chun tuilleadh a fhoghlaim faoi na críochphointí atá ar fáil, tabhair cuairt ar ár gcáipéisíocht.", "To select skills here, add them to the \"Skills\" workspace first.": "Chun scileanna a roghnú anseo, cuir iad leis an spás oibre \"Scileanna\" ar dtús.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Chun trealamh uirlisí a roghnú anseo, cuir iad leis an spás oibre \"Uirlisí\" ar dtús.", - "Toast notifications for new updates": "Fógraí tósta le haghaidh nuashonruithe nua", + "Toast Notifications for New Updates": "Fógraí tósta le haghaidh nuashonruithe nua", "Today": "Inniu", "Today at": "Inniu ag", "Today at {{LOCALIZED_TIME}}": "Inniu ag {{LOCALIZED_TIME}}", @@ -2130,12 +2294,14 @@ "Toggle 1 source": "Athraigh foinse amháin", "Toggle details": "Athraigh sonraí", "Toggle Dictation": "Athraigh Deachtú", - "Toggle Mute": "", + "Toggle Mute": "Athraigh Balbhaigh", "Toggle Sidebar": "Barra Taobh a Athraigh", "Toggle status history": "Athraigh stair stádais", "Toggle whether current connection is active.": "Athraigh an bhfuil an nasc reatha gníomhach.", "Token": "Comhartha", "Token counts are estimates and may not reflect actual API usage": "Is meastacháin iad comhaireamh na gcomharthaí agus ní fhéadfaidh siad úsáid iarbhír API a léiriú.", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "comharthaí", "Tokens": "Comharthaí", "Too verbose": "Ró-fhocal", @@ -2159,7 +2325,7 @@ "Top K Reranker": "Barr K Reranker", "Transformers": "Claochladáin", "Trouble accessing Ollama?": "Deacracht teacht ar Ollama?", - "Trust Proxy Environment": "Timpeallacht Iontaobhais do Phróicís", + "Trust Proxy Environment": "Timpeallacht Iontaobhais Seachfhreastalaí", "Try adjusting your search or filter to find what you are looking for.": "Bain triail as do chuardach nó do scagaire a choigeartú chun a bhfuil á lorg agat a fháil.", "Try Again": "Bain Triail Arís", "TTS Model": "Samhail TTS", @@ -2184,14 +2350,19 @@ "Unpin": "Díbhoráin", "Unpin from Sidebar": "Díbhoráin ón mBarra Taoibh", "Unravel secrets": "Rúin a réiteach", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Díroinn Comhrá", "Unsupported file type.": "Cineál comhaid nach dtacaítear leis.", "Untagged": "Gan chlib", "Untitled": "Gan Teideal", "Update": "Nuashonraigh", "Update and Copy Link": "Nuashonraigh agus Cóipeáil Nasc", + "Update Email": "", "Update for the latest features and improvements.": "Nuashonrú le haghaidh na gnéithe agus na feabhsuithe is déanaí.", + "Update Name": "", "Update password": "Nuashonrú pasfhocal", + "Update Picture": "", "Update your status": "Nuashonraigh do stádas", "Updated": "Nuashonraithe", "Updated at": "Nuashonraithe ag", @@ -2209,7 +2380,7 @@ "Upload Progress": "Dul Chun Cinn an Uaslódála", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Dul Chun Cinn Uaslódála: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Comhaid nó íomhánna uaslódáilte", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploading {{current}}/{{total}}: {{file}}": "Ag uaslódáil {{current}}/{{total}}: {{file}}", "Uploading...": "Ag uaslódáil...", "URL": "URL", "URL is required": "Tá URL ag teastáil", @@ -2218,22 +2389,28 @@ "Use": "Úsáid", "Use '#' in the prompt input to load and include your knowledge.": "Úsáid '#' san ionchur treoir chun do chuid eolais a lódáil agus a chur san áireamh.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Bain úsáid as an gcríochphointe /v1/chat/completions in ionad /v1/audio/transcriptions le haghaidh cruinneas níos fearr b’fhéidir.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Úsáid API Comhlánuithe Comhrá", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Bain úsáid as grúpaí chun d’úsáideoirí a eagrú agus ceadanna a shannadh.", "Use LLM": "Úsáid LLM", "Use no proxy to fetch page contents.": "Ná húsáid seachfhreastalaí chun inneachar an leathanaigh a fháil.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Úsáid seachfhreastalaí ainmnithe ag athróga timpeallachta http_proxy agus https_proxy chun inneachar an leathanaigh a fháil.", + "Use Web Search?": "", "user": "úsáideoir", "User": "Úsáideoir", + "User Access": "", "User Activity": "Gníomhaíocht Úsáideora", "User Groups": "Grúpaí Úsáideoirí", "User location successfully retrieved.": "Fuarthas suíomh an úsáideora go rathúil.", "User menu": "Roghchlár úsáideora", - "User Preview": "", + "User Preview": "Réamhamharc Úsáideora", "User ratings (thumbs up/down)": "Rátálacha úsáideoirí (ordóg suas/síos)", "User Status": "Stádas Úsáideora", "User Webhooks": "Crúcaí Gréasáin Úsáideoir", "Username": "Ainm Úsáideora", + "Username Claim": "", "users": "úsáideoirí", "Users": "Úsáideoirí", "Uses DefaultAzureCredential to authenticate": "Úsáideann sé DefaultAzureCredential chun fíordheimhniú", @@ -2247,6 +2424,7 @@ "Valves updated": "Comhlaí dáta", "Valves updated successfully": "Comhlaí nuashonraíodh", "variable": "athraitheach", + "Vector Field": "", "Verify Connection": "Fíoraigh Ceangal", "Verify SSL Certificate": "Fíoraigh Deimhniú SSL", "Version": "Leagan", @@ -2276,11 +2454,14 @@ "Web API": "API Gréasáin", "Web Loader Engine": "Inneall Luchtaithe Gréasáin", "Web Search": "Cuardach Gréasáin", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Inneall Cuardaigh Gréasáin", "Web Search in Chat": "Cuardach Gréasáin i gComhrá", "Web Search Query Generation": "Giniúint Iarratas Cuardach Gréasáin", + "Webhook deleted": "", "Webhook Name": "Ainm an Crúca Gréasáin", - "Webhook URL": "URL Webhook", + "Webhook saved": "", "Webhooks": "Crúcaí Gréasáin", "Webpage URLs": "URLanna leathanaigh ghréasáin", "WebUI Settings": "Socruithe WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Eochair API Cuardaigh Gréasáin Yandex", "Yandex Web Search config": "Cumraíocht Cuardaigh Gréasáin Yandex", "Yandex Web Search URL": "URL Cuardaigh Gréasáin Yandex", + "Yearly": "", "Yesterday": "Inné", "Yesterday at {{LOCALIZED_TIME}}": "Inné ag {{LOCALIZED_TIME}}", "You": "Tú", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Ní thacaíonn do bhrabhsálaí leis an gclib físeáin.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Rachaidh do ranníocaíocht iomlán go díreach chuig an bhforbróir breiseán; Ní ghlacann Open WebUI aon chéatadán. Mar sin féin, d'fhéadfadh a tháillí féin a bheith ag an ardán maoinithe roghnaithe.", "Your message text or inputs": "Téacs nó ionchur do theachtaireachta", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Tá do staitisticí úsáide sioncronaithe go rathúil.", "YouTube": "YouTube", "Youtube Language": "Teanga YouTube", diff --git a/src/lib/i18n/locales/it-IT/translation.json b/src/lib/i18n/locales/it-IT/translation.json index ca4076321e..6fe79657b1 100644 --- a/src/lib/i18n/locales/it-IT/translation.json +++ b/src/lib/i18n/locales/it-IT/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} righe nascoste", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "{{user}} Chat", "{{webUIName}} Backend Required": "{{webUIName}} Richiesta Backend", "*Prompt node ID(s) are required for image generation": "*ID nodo prompt sono necessari per la generazione di immagini", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "Controllo accessi", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Accessibile a tutti gli utenti", "Account": "Account", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Aggiungi", "Add a model ID": "Aggiungi un ID modello", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Aggiungi una breve descrizione di quello che fa questo modello", "Add a tag": "Aggiungi un tag", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Aggiungi dei file", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Aggiungi utente", "Add User Group": "Aggiungi gruppo utente", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Amministratore", "Admin Contact Email": "", "Admin Panel": "Pannello di amministrazione", + "Admin Roles": "", "Admin Settings": "Impostazioni amministratore", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Gli amministratori hanno accesso a tutti gli strumenti in qualsiasi momento; gli utenti necessitano di strumenti assegnati per ogni modello nello spazio di lavoro.", "Advanced": "", "Advanced Parameters": "Parametri avanzati", @@ -126,16 +146,21 @@ "All": "Tutti", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Tutti i modelli eliminati con successo", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Consenti chiamata", "Allow Chat Controls": "Consenti controlli chat", "Allow Chat Delete": "Consenti eliminazione chat", "Allow Chat Edit": "Consenti modifica chat", "Allow Chat Export": "Consenti esportazione chat", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "Consenti condivisione chat", "Allow Chat System Prompt": "", @@ -155,9 +180,11 @@ "Allow User Location": "Consenti posizione utente", "Allow Voice Interruption in Call": "Consenti interruzione vocale in chiamata", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Endpoint consentiti", "Allowed File Extensions": "Estensioni file permesse", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Le estensioni file permesse per il caricamento. Separa le varie estensioni con una virgola. Lascia vuoto per tutti i tipi di file.", + "Allowed Roles": "", "Already have an account?": "Hai già un account?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa al top_p e mira a garantire un equilibrio tra qualità e varietà. Il parametro p rappresenta la probabilità minima affinché un token venga considerato, rispetto alla probabilità del token più probabile. Ad esempio, con p=0.05 e il token più probabile con una probabilità di 0.9, i logits con un valore inferiore a 0.045 vengono filtrati.", "Always": "Sempre", @@ -176,6 +203,7 @@ "API Base URL": "URL base per API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Chiave API", + "API Key / Token": "", "API Key created.": "Chiave API creata.", "API Key Endpoint Restrictions": "Restrizioni Endpoint Chiave API", "API keys": "Chiavi API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Sei sicuro di voler eliminare questo messaggio?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Sei sicuro di voler disarchiviare tutte le chat archiviate?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modelli Arena", "Artifacts": "Artefatti", "Asc": "", "Ask": "Chiedi", "Ask a question": "Fai una domanda", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistente", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Agosto", "Auth": "Autenticazione", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentica", "Authentication": "Autenticazione", "Auto": "Automatico", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copia automatica della risposta negli appunti", - "Auto-playback response": "Riproduzione automatica della risposta", + "Auto-Create Groups": "", + "Auto-Playback Response": "Riproduzione automatica della risposta", "Autocomplete Generation": "Generazione dell'autocompletamento", "Autocomplete Generation Input Max Length": "Lunghezza massima input generazione dell'autocompletamento", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "Stringa autenticazione AUTOMATIC1111 Api", "AUTOMATIC1111 Base URL": "URL base AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Strumenti disponibili", "available users": "utenti disponibili", + "Available variables": "", "available!": "disponibile!", "Away": "Assente", "Awful": "Terribile", @@ -261,16 +301,17 @@ "Bad Response": "Risposta non valida", "Banners": "Banner", "Base Model (From)": "Modello base (da)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "prima", "Being lazy": "Faccio il pigro", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Endpoint di Bing Search V7", "Bing Search V7 Subscription Key": "Chiave di Iscrizione Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Chiave API di Bocha Search", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Direzione chat", + "Chat Direction": "Direzione chat", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Riduci", "Collection": "Collezione", + "Collection Field": "", "Collections": "", "Color": "Colore", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "Flusso di lavoro ComfyUI", "ComfyUI Workflow Nodes": "Nodi flusso di lavoro ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Comando", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Completamenti", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Connettiti ai tuoi endpoint API compatibili con OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Connettiti ai tuoi server di tool esterni compatibili con OpenAPI.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Connessione fallita", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contatta l'amministratore per l'accesso al servizio WebUI", "Content": "Contenuto", "Content Extraction Engine": "Motore di estrazione contenuti", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Continua risposta", "Continue with {{provider}}": "Continua con {{provider}}", "Continue with Email": "Continua con email", @@ -497,6 +550,7 @@ "Create new secret key": "Crea nuova chiave segreta", "Create note": "", "Create Note": "Crea nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Crea la tua prima nota cliccando sul pulsante + sotto.", "Created at": "Creato il", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "Nome parametro personalizzato", "Custom Parameter Value": "Valore parametro personalizzato", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Zona di pericolo", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Il modello predefinito funziona con un'ampia gamma di modelli chiamando gli strumenti una volta prima dell'esecuzione. La modalità nativa sfrutta le capacità di chiamata degli strumenti integrate nel modello, ma richiede che il modello supporti intrinsecamente questa funzionalità.", "Default Model": "Modello predefinito", "Default model updated": "Modello predefinito aggiornato", "Default permissions": "Permessi predefiniti", @@ -546,6 +600,7 @@ "Default to ALL": "Predefinito su TUTTI", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Predefinito per il recupero segmentato per un'estrazione di contenuti mirata e pertinente, questo è raccomandato per la maggior parte dei casi.", "Default User Role": "Ruolo utente predefinito", + "Default webhook": "", "Defaults": "", "Delete": "Elimina", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "Disattiva l'estrazione immagini", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Disattiva l'estrazione immagini dai PDF. Se LLM è attivo le immagini saranno didascalizzate. Predefinito a Falso.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Disabilitato", "Disconnect OAuth": "", "Discover a function": "Scopri una funzione", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset dei modello", "Discussion channel where access is based on groups and permissions": "", "Display": "Visualizza", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Visualizza emoji nella chiamata", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat", + "Display the Username Instead of You in the Chat": "Visualizza il nome utente invece di Tu nella chat", "Displays citations in the response": "Visualizza citazioni nella risposta", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Immergiti nella conoscenza", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "L'URL del server Docling è obbligatoria.", "Document": "Documento", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Modifica Permessi Predefiniti", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Modifica Memoria", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Modifica Utente", "Edit User Group": "Modifica Gruppo Utente", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Intraprendi avventure", "Embedding": "Embedding", "Embedding Batch Size": "Dimensione Batch Embedding", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Motore Modello di Embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "Abilita Esecuzione Codice", "Enable Code Interpreter": "Abilita Interprete Codice", "Enable Community Sharing": "Abilita Condivisione Community", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Abilita il blocco della memoria (mlock) per impedire che i dati del modello vengano scambiati dalla RAM. Questa opzione blocca l'insieme di pagine di lavoro del modello nella RAM, assicurando che non vengano scambiate su disco. Questo può aiutare a mantenere le prestazioni evitando errori di pagina e garantendo un accesso rapido ai dati.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Abilita il mapping della memoria (mmap) per caricare i dati del modello. Questa opzione consente al sistema di utilizzare lo spazio di archiviazione su disco come estensione della RAM trattando i file su disco come se fossero nella RAM. Questo può migliorare le prestazioni del modello consentendo un accesso più rapido ai dati. Tuttavia, potrebbe non funzionare correttamente con tutti i sistemi e può consumare una quantità significativa di spazio su disco.", "Enable Message Queue": "", "Enable Message Rating": "Abilita valutazione messaggio", "Enable Mirostat sampling for controlling perplexity.": "Abilita il campionamento Mirostat per controllare la perplessità.", "Enable New Sign Ups": "Abilita Nuove Registrazioni", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Abilitato", "End Tag": "", + "Endpoint": "", "Endpoint URL": "URL Endpoint", "Enforce Temporary Chat": "Forza Chat Temporanea", "Enhance": "Migliora", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assicurati che il tuo file CSV includa 4 colonne in questo ordine: Nome, Email, Password, Ruolo.", "Enter {{role}} message here": "Inserisci il messaggio per {{role}} qui", - "Enter a detail about yourself for your LLMs to recall": "Inserisci un dettaglio su di te per che i LLM possano ricordare", "Enter a title for the pending user info overlay. Leave empty for default.": "Inserisci un titolo per gli utente in attesa nella schermata informazioni. LAscia vuoto per il predefinito.", "Enter a watermark for the response. Leave empty for none.": "Inserisci un watermark per le risposte. Lascia vuoto per nessuno.", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Inserisci Sovrapposizione Chunk", "Enter Chunk Size": "Inserisci Dimensione Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Inserisci coppie \"token:valore_bias\" separate da virgole (esempio: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Inserisci contenuto per l'overlay di info per utenti in attesa. Lascia vuoto per predefinito.", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Inserisci URL Jupyter", "Enter Kagi Search API Key": "Inserisci Chiave API Kagi Search", "Enter Key Behavior": "Comportamento Tasto Invio", + "Enter language": "", "Enter language codes": "Inserisci i codici lingua", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Inserisci Chiave API Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Inserisci l'URL del proxy (ad es. https://user:password@host:port)", "Enter reasoning effort": "Inserisci lo sforzo di ragionamento", + "Enter Redirect URI": "", "Enter Score": "Inserisci Punteggio", "Enter SearchApi API Key": "Inserisci Chiave API SearchApi", "Enter SearchApi Engine": "Inserisci Motore SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Inserisci Chiave API SerpApi", "Enter SerpApi Engine": "Inserisci Motore SerpApi", "Enter Serper API Key": "Inserisci Chiave API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Inserisci Chiave API Serply", "Enter Serpstack API Key": "Inserisci Chiave API Serpstack", "Enter server host": "Inserisci l'host del server", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Inserisci l'URL del Server Tika", "Enter timeout in seconds": "Inserisci la scadenza in secondi", "Enter to Send": "Premi Invio per Inviare", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Inserisci Top K", "Enter Top K Reranker": "Inserisci Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Inserisci URL (ad esempio http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Valutazioni", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Chiave API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Esempio: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Esempio: TUTTI", "Example: mail": "Esempio: mail", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Esporta in CSV", "Export Tools": "", "Export Users": "", "External": "Esterno", + "External connection not found.": "", "External Document Loader URL required.": "URL esterna per il Document Loader necessaria.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Task Modello esterna", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Chiave API del web loaderesterno", "External Web Loader URL": "URL del web loader esterno", "External Web Search API Key": "Chiave API di ricerca web esterna", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Impossibile creare Chiave API.", "Failed to delete calendar": "", "Failed to delete note": "Impossibile eliminare la nota", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Impossibile recuperare i modelli", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Impossibile leggere il contenuto degli appunti", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Impossibile salvare la configurazione dei modelli", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Impossibile aggiornare le impostazioni", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Impossibile caricare il file.", "Features": "Caratteristiche", "Features Permissions": "Permessi delle funzionalità", @@ -991,6 +1082,8 @@ "File uploaded successfully": "Caricamento file riuscito", "Filename": "", "Files": "File", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Il filtro è ora disabilitato globalmente", "Filter is now globally enabled": "Il filtro è ora abilitato globalmente", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "Follow up", "Follow Up Generation": "Generazione follow up", "Follow Up Generation Prompt": "Generazione prompt follow up", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "Il filtro è ora abilitato globalmente", "Function Name": "Nome Funzione", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funzione aggiornata con successo", "Functions": "Funzioni", "Functions allow arbitrary code execution.": "Le funzioni consentono l'esecuzione di codice arbitrario.", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Gruppo creato con successo", "Group deleted successfully": "Gruppo eliminato con successo", "Group Description": "Descrizione Gruppo", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Feedback Aptico", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox Consenti moduli", "iframe Sandbox Allow Same Origin": "iframe Sandbox Consenti stessa origine", @@ -1142,6 +1243,7 @@ "Import From Link": "Importa dai link", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Aggiornamento importante", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "Mantieni nella barra laterale", "Key": "Chiave", "Key is required": "", - "Keyboard shortcuts": "Scorciatoie da tastiera", "Keyboard Shortcuts": "", "Knowledge": "Conoscenza", "Knowledge Access": "Accesso alla conoscenza", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Conoscenza condivisione pubblica", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Conoscenza aggiornata con successo", "Kokoro.js (Browser)": "Kokoro.js (Browser)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Ultima risposta", "LDAP": "LDAP", - "LDAP server updated": "Server LDAP aggiornato", "Leaderboard": "Classifica", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "Licenza", + "Lifecycle JSON": "", "Lift List": "", "Light": "Chiaro", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Accesso alla posizione non consentito", "Lost": "Perso", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Realizzato dalla Comunità Open WebUI", "Make password visible in the user interface": "Rendi la password visibile nella interfaccia utente", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gestisci le Pipeline", "Manage Tool Servers": "Gestisci i Server dei Tool", "Manage your account information.": "", + "Mapped Source": "", "March": "Marzo", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memoria cancellata con successo", "Memory deleted successfully": "Memoria eliminata con successo", "Memory updated successfully": "Memoria aggiornata con successo", + "Merge Accounts by Email": "", "Merge Responses": "Unisci Risposte", "Merged Response": "Risposta Unita", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "I messaggi inviati dopo la creazione del link non verranno condivisi. Gli utenti con l'URL saranno in grado di visualizzare la chat condivisa.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personale)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (lavoro/scuola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Chiave API di Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Altro", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Dai un nome alla tua base di conoscenza", "Name, prompt, and model are required": "", "Native": "Nativo", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "Nessuna distanza disponibile", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nessun file selezionato", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Nessun risultato trovato", "No results found": "Nessun risultato trovato", "No search query generated": "Nessuna query di ricerca generata", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Nessuno", + "Not configured": "", "Not factually correct": "Non corretto dal punto di vista fattuale", "Not helpful": "Non utile", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Notifiche desktop", "November": "Novembre", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Ottobre", "Off": "Disattivato", "Okay, Let's Go!": "Ok, andiamo!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED scuro", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Impostazioni API Ollama aggiornate", "Ollama Cloud API Key": "", "Ollama Version": "Versione Ollama", + "Omit": "", "On": "Attivato", "Once": "", "OneDrive": "OneDrive", @@ -1586,6 +1707,7 @@ "Password": "Password", "Passwords do not match.": "", "Paste Large Text as File": "Incolla Molto Testo come File", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Documento PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "in sospeso", "Pending": "In Attesa", + "Pending Accounts": "", "Pending User Overlay Content": "Contenuto utente in attesa", "Pending User Overlay Title": "Titolo utente in attesa", "Permission denied when accessing media devices": "Autorizzazione negata durante l'accesso ai dispositivi multimediali", "Permission denied when accessing microphone": "Autorizzazione negata durante l'accesso al microfono", "Permission denied when accessing microphone: {{error}}": "Autorizzazione negata durante l'accesso al microfono: {{error}}", "Permissions": "Permessi", + "Permissions reset to defaults": "", "Perplexity API Key": "Chiave API Perplexity", "Perplexity Model": "Modello Perplexity", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "Utilizzo delcontesto della Ricerca Perplexity", "Persistent": "", "Personalization": "Personalizzazione", + "Picture Claim": "", "Pin": "Appunta", "Pin to Sidebar": "", "Pinned": "Appuntato", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Si prega di compilare tutti i campi.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Si prega di selezionare prima un modello.", "Please select a model.": "Si prega di selezionare un modello.", "Please select a reason": "Si prega di selezionare un motivo", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Porta", "Ports": "", "Positive attitude": "Attitudine positiva", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Condivisione Pubblica dei Prompt", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Pubblico", "Pull \"{{searchValue}}\" from Ollama.com": "Estrai \"{{searchValue}}\" da Ollama.com", "Pull a model from Ollama.com": "Estrai un modello da Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Leggi", "Read Aloud": "Leggi ad Alta Voce", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Sforzo di ragionamento", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Registra", "Record voice": "Registra voce", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Reindirizzamento alla comunità OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Riduce la probabilità di generare sciocchezze. Un valore più alto (ad esempio 100) darà risposte più varie, mentre un valore più basso (ad esempio 10) sarà più conservativo.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Riferisciti a te stesso come \"Utente\" (ad esempio, \"L'utente sta imparando lo spagnolo\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Rifiutato quando non avrebbe dovuto", "Regenerate": "Rigenera", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Riordina Modelli", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Rispondi nel thread", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Engine di Riclassificazione", "Reranking Model": "Modello di Riclassificazione", + "Research Knowledge": "", "Reset": "Ripristina", "Reset All Models": "Ripristina Tutti i Modelli", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Reimposta immagine", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Ripristina Directory di Caricamento", "Reset Vector Storage/Knowledge": "Ripristina Archiviazione Vettoriale/Conoscenza", "Reset view": "Ripristina visualizzazione", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Input di testo ricco per la chat", "Role": "Ruolo", + "Roles Claim": "", "RTL": "RTL", "Run": "Esegui", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Il salvataggio dei registri della chat direttamente nell'archivio del browser non è più supportato. Si prega di dedicare un momento per scaricare ed eliminare i registri della chat facendo clic sul pulsante in basso. Non preoccuparti, puoi facilmente reimportare i registri della chat nel backend tramite", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Scorri al cambio di branch", "Scroll to Top": "", "Search": "Cerca", "Search a model": "Cerca un modello", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Cerca nelle chat", "Search Collection": "Cerca collezione", "Search Files": "", + "Search filters": "", "Search Filters": "Cerca filtri", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Cerca modelli", "Search Notes": "", "Search options": "Cerca opzioni", + "Search or add pattern": "", "Search Prompts": "Cerca prompt", "Search Result Count": "Conteggio dei risultati della ricerca", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Cerca su Internet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Cerca Strumenti", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Chiave API SearchApi", "SearchApi Engine": "Engine SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Seme", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Selezionare un modello di base", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Seleziona un motore", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Invia", "Send a Message": "Invia un messaggio", + "Send events for": "", "Send message": "Invia messaggio", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Invia `stream_options: { include_usage: true }` nella richiesta.\nI provider supportati restituiranno informazioni sull'utilizzo dei token nella risposta quando impostato.", "September": "Settembre", "SerpApi API Key": "Chiave API SerpApi", "SerpApi Engine": "Engine SerpApi", "Serper API Key": "Chiave API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Chiave API Serply", "Serpstack API Key": "Chiave API Serpstack", "Server connection failed": "", "Server connection verified": "Connessione al server verificata", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Imposta come predefinito", "Set as Production": "", "Set embedding model": "Imposta modello di embedding", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Condividi con la comunità OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Condivisione dei permessi", "Show": "Mostra", - "Show \"What's New\" modal on login": "Mostra il modulo \"Novità\" al login", + "Show \"What's New\" Modal on Login": "Mostra il modulo \"Novità\" al login", "Show Admin Details in Account Pending Overlay": "Mostra i dettagli dell'amministratore nella sovrapposizione dell'account in attesa", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Mostra Modello", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "sID per Songou Search API", "Sougou Search API SK": "SK per Songou Search API", "Source": "Fonte", + "Specific users or groups": "", "Speech Playback Speed": "Velocità di riproduzione vocale", "Speech recognition error: {{error}}": "Errore di riconoscimento vocale: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "Impostazioni STT", "Stylized PDF Export": "Esportazione PDF Stilizzata", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "Istruzioni di sistema", "System Prompt": "Prompt di sistema", + "Table": "", "Tag": "", "Tags": "Tag", "Tags Generation": "Generazione tag", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divisore di testo", "Text-to-Speech": "", "Text-to-Speech Engine": "Motore da testo a voce", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Il linguaggio degli input audio. Fornire la lingua in formato ISO-639-1 (es: en) migliorerà la accuratezza e la latenza. Lascia vuoto per per riconoscere il linguaggio in automatico.", "The LDAP attribute that maps to the mail that users use to sign in.": "L'attributo LDAP che mappa alla mail che gli utenti usano per accedere.", "The LDAP attribute that maps to the username that users use to sign in.": "L'attributo LDAP che mappa al nome utente che gli utenti usano per accedere.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "La classifica è attualmente in beta e potremmo regolare i calcoli dei punteggi mentre perfezioniamo l'algoritmo.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "La dimensione massima del file in MB. Se la dimensione del file supera questo limite, il file non verrà caricato.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "La dimensione massima del numero di file che possono essere utilizzati contemporaneamente nella chat. Se il numero di file supera questo limite, i file non verranno caricati.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Il formato di output per il testo. Può essere 'json', 'markdown', o 'html'. Predefinito 'markdown'.", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Questa è una funzionalità sperimentale, potrebbe non funzionare come previsto ed è soggetta a modifiche in qualsiasi momento.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Questo modello non è disponibile pubblicamente. Seleziona un altro modello.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Questa opzione controlla quanto a lungo il modello rimarrà in memoria seguendo la richiesta (predefinito: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Questa opzione controlla quanti token vengono preservati quando si aggiorna il contesto. Ad esempio, se impostato su 2, gli ultimi 2 token del contesto della conversazione verranno mantenuti. Preservare il contesto può aiutare a mantenere la continuità di una conversazione, ma potrebbe ridurre la capacità di rispondere a nuovi argomenti.", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Per saperne di più sugli endpoint disponibili, visita la nostra documentazione.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Per selezionare i toolkit qui, aggiungili prima allo spazio di lavoro \"Strumenti\".", - "Toast notifications for new updates": "Notifiche toast per nuovi aggiornamenti", + "Toast Notifications for New Updates": "Notifiche toast per nuovi aggiornamenti", "Today": "Oggi", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "Attiva/disattiva la connessione attuale quando è attiva", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Troppo prolisso", @@ -2191,14 +2361,19 @@ "Unpin": "Rimuovi fissato", "Unpin from Sidebar": "", "Unravel secrets": "Svela segreti", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Non taggato", "Untitled": "Senza titolo", "Update": "Aggiorna", "Update and Copy Link": "Aggiorna e Copia Link", + "Update Email": "", "Update for the latest features and improvements.": "Aggiorna per le ultime funzionalità e miglioramenti.", + "Update Name": "", "Update password": "Aggiorna password", + "Update Picture": "", "Update your status": "", "Updated": "Aggiornato", "Updated at": "Aggiornato il", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Usa '#' nell'input del prompt per caricare e includere la tua conoscenza.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Utilizza LLM", "Use no proxy to fetch page contents.": "Usa nessun proxy per recuperare i contenuti della pagina.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Usa il proxy designato dalle variabili di ambiente http_proxy e https_proxy per recuperare i contenuti della pagina.", + "Use Web Search?": "", "user": "utente", "User": "Utente", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Posizione utente recuperata con successo.", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "Webhook Utente", "Username": "Nome Utente", + "Username Claim": "", "users": "", "Users": "Utenti", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "Valvole aggiornate", "Valves updated successfully": "Valvole aggiornate con successo", "variable": "variabile", + "Vector Field": "", "Verify Connection": "Verifica connessione", "Verify SSL Certificate": "Verifica certificato SSL", "Version": "Versione", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "Motore di Caricamento Web", "Web Search": "Ricerca sul Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motore di Ricerca Web", "Web Search in Chat": "Ricerca Web in chat", "Web Search Query Generation": "Generazione di query di ricerca Web", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Impostazioni WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Ieri", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Tu", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Il tuo intero contributo andrà direttamente allo sviluppatore del plugin; Open WebUI non prende alcuna percentuale. Tuttavia, la piattaforma di finanziamento scelta potrebbe avere le proprie commissioni.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Lingua Youtube", diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index 799bc68f1d..28d85c798c 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "{{COUNT}} 行を抽出", "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} 行が非表示", "{{COUNT}} members": "{{COUNT}} メンバー", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} 件のソース", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} 語", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} のダウンロードがキャンセルされました", "{{modelName}} profile image": "", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "{{user}} のチャット", "{{webUIName}} Backend Required": "{{webUIName}} バックエンドが必要です", "*Prompt node ID(s) are required for image generation": "*画像生成にはプロンプトノードIDが必要です", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -54,6 +61,7 @@ "Access Control": "アクセス権制御", "Access Grants": "", "Access List": "アクセス権リスト", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "すべてのユーザーにアクセス可能", "Account": "アカウント", @@ -69,6 +77,7 @@ "Activity": "", "Add": "追加", "Add a model ID": "モデルIDを追加", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "このモデルの機能に関する簡単な説明を追加します", "Add a tag": "タグを追加", "Add a tag...": "タグを追加...", @@ -81,8 +90,10 @@ "Add Custom Prompt": "カスタムプロンプトを追加", "Add description": "", "Add Details": "より詳しく", + "Add durable context for future chats": "", "Add Files": "ファイルを追加", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -97,6 +108,7 @@ "Add to favorites": "", "Add User": "ユーザーを追加", "Add User Group": "ユーザーグループを追加", + "Add webhook": "", "Add webpage": "ウェブページを追加", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "追加設定", @@ -109,7 +121,9 @@ "Admin": "管理者", "Admin Contact Email": "管理者の連絡先メールアドレス", "Admin Panel": "管理者パネル", + "Admin Roles": "", "Admin Settings": "管理者設定", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理者は全てのツールにアクセスできます。ユーザーからはワークスペースのモデルごとに割り当てられたツールのみ使用可能です。", "Advanced": "", "Advanced Parameters": "高度なパラメーター", @@ -120,16 +134,21 @@ "All": "全て", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "全てのモデルが正常に削除されました", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "コールを許可", "Allow Chat Controls": "チャットコントロールを許可", "Allow Chat Delete": "チャットの削除を許可", "Allow Chat Edit": "チャットの編集を許可", "Allow Chat Export": "チャットのエクスポートを許可", + "Allow Chat Import": "", "Allow Chat Params": "チャットパラメータを許可", "Allow Chat Share": "チャットの共有を許可", "Allow Chat System Prompt": "チャットシステムプロンプトを許可", @@ -149,9 +168,11 @@ "Allow User Location": "ユーザーロケーションの許可", "Allow Voice Interruption in Call": "通話中に音声の割り込みを許可", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "許可されたエンドポイント", "Allowed File Extensions": "許可された拡張子", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "アップロード可能なファイル拡張子。複数の拡張子はカンマで区切ってください。空欄ですべてのファイルタイプを許可します。", + "Allowed Roles": "", "Already have an account?": "すでにアカウントをお持ちですか?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p の代替手法で、品質と多様性のバランスを確保することを目的としています。パラメータ p は、最も確率の高いトークンの確率に対する、トークンが考慮されるための最小確率を表します。たとえば、p=0.05 で最も可能性の高いトークンの確率が 0.9 の場合、0.045 未満の値を持つロジットはフィルタリングされます。", "Always": "常に", @@ -170,6 +191,7 @@ "API Base URL": "API ベース URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab MarkerサービスのAPIベースURL。デフォルトは https://www.datalab.to/api/v1/marker です", "API Key": "API キー", + "API Key / Token": "", "API Key created.": "API キーが作成されました。", "API Key Endpoint Restrictions": "API キーのエンドポイント制限", "API keys": "API キー", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "このメモリをクリアしますか? この操作は元に戻すことができません。", "Are you sure you want to delete this message?": "このメッセージを削除しますか?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "すべてのアーカイブされたチャットをアンアーカイブしますか?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arenaモデル", "Artifacts": "アーティファクト", "Asc": "", "Ask": "質問する", "Ask a question": "質問する", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "アシスタント", "Async Embedding Processing": "", "At time of event": "", @@ -220,14 +247,20 @@ "Audio": "オーディオ", "August": "8月", "Auth": "認証", + "Auth Mode": "", + "Auth required": "", "Authenticate": "認証", "Authentication": "認証", "Auto": "自動", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "クリップボードへの応答の自動コピー", - "Auto-playback response": "応答の自動再生", + "Auto-Create Groups": "", + "Auto-Playback Response": "応答の自動再生", "Autocomplete Generation": "自動補完の生成", "Autocomplete Generation Input Max Length": "自動補完生成の入力の最大長", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "AUTOMATIC1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111のAuthを入力", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 ベース URL", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "利用可能ツール", "available users": "利用可能なユーザー", + "Available variables": "", "available!": "が利用可能です!", "Away": "離席中", "Awful": "ひどい", @@ -255,16 +289,17 @@ "Bad Response": "応答が悪い", "Banners": "バナー", "Base Model (From)": "ベースモデル (From)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "ベースモデルリストキャッシュは、起動時または設定保存時にのみベースモデルを取得することでアクセスを高速化します。これにより高速になりますが、最近のベースモデルの変更が表示されない場合があります。", "Bearer": "Bearer", "before": "以前", "Being lazy": "怠惰な", - "Beta": "ベータ", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 エンドポイント", "Bing Search V7 Subscription Key": "Bing Search V7 サブスクリプションキー", "Bio": "自己紹介", "Birth Date": "生年月日", + "Blocked Groups": "", "BM25 Weight": "BM25の重み", "Bocha Search API Key": "Bocha Search APIキー", "Bold": "太字", @@ -321,7 +356,7 @@ "Chat Completions": "", "Chat Conversation": "チャットの会話", "Chat deleted.": "", - "Chat direction": "チャットの方向", + "Chat Direction": "チャットの方向", "Chat exported successfully": "", "Chat History": "チャット履歴", "Chat ID": "チャットID", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "", "Collapse": "折りたたむ", "Collection": "コレクション", + "Collection Field": "", "Collections": "コレクション", "Color": "色", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "ComfyUIワークフロー", "ComfyUI Workflow Nodes": "ComfyUIワークフローノード", "Comma separated Node Ids (e.g. 1 or 1,2)": "カンマで区切られたノードID (例: 1 または 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "コマンド", "Comment": "コメント", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Completions", "Compress Images in Channels": "チャンネルで画像を圧縮する", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "独自のOpenAI互換APIエンドポイントに接続します。", "Connect to your own OpenAPI compatible external tool servers.": "独自のOpenAPI互換外部ツールサーバーに接続します。", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "接続に失敗しました", "Connection lost. Reconnecting...": "", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "WEBUIへのアクセスについて管理者に問い合わせ下さい。", "Content": "コンテンツ", "Content Extraction Engine": "コンテンツ抽出エンジン", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "続きの応答", "Continue with {{provider}}": "{{provider}}で続ける", "Continue with Email": "メールで続ける", @@ -489,6 +536,7 @@ "Create new secret key": "新しいシークレットキーを作成", "Create note": "ノートを作成", "Create Note": "ノートを作成", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "定期的に自動実行されるプロンプトを作成します。", "Create your first note by clicking on the plus button below.": "プラスボタンをクリックして最初のノートを作成します。", "Created at": "作成日時", @@ -506,6 +554,7 @@ "Custom Gender": "", "Custom Parameter Name": "カスタムパラメータ名", "Custom Parameter Value": "カスタムパラメータ値", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "危険地帯", @@ -528,7 +577,6 @@ "Default Features": "デフォルト機能", "Default Filters": "", "Default Group": "デフォルトグループ", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "デフォルトモードは、実行前にツールを一度呼び出すことで、より広範なモデルで動作します。ネイティブモードは、モデルの組み込みのツール呼び出し機能を活用しますが、モデルがこの機能をサポートしている必要があります。", "Default Model": "デフォルトモデル", "Default model updated": "デフォルトモデルが更新されました", "Default permissions": "デフォルトの権限", @@ -538,6 +586,7 @@ "Default to ALL": "標準ではALL", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "デフォルトではセグメント化された検索を使用して、焦点を絞った関連性の高いコンテンツ抽出を行います。これはほとんどの場合に推奨されます。", "Default User Role": "デフォルトのユーザー役割", + "Default webhook": "", "Defaults": "", "Delete": "削除", "Delete {{name}}": "", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "コードインタプリタを無効化", "Disable Image Extraction": "画像の抽出を無効化", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDFからの画像の抽出を無効化します。LLMを使用 が有効の場合、画像は自動で説明文に変換されます。デフォルトで無効", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "無効", "Disconnect OAuth": "", "Discover a function": "Functionを探す", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "モデルプリセットを探してダウンロードする", "Discussion channel where access is based on groups and permissions": "", "Display": "表示", - "Display chat title in tab": "チャットのタイトルをタブに表示", + "Display Chat Title in Tab": "チャットのタイトルをタブに表示", "Display Emoji in Call": "コールで絵文字を表示", "Display Multi-model Responses in Tabs": "複数モデルの応答をタブで表示する", - "Display the username instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示", + "Display the Username Instead of You in the Chat": "チャットで「あなた」の代わりにユーザー名を表示", "Displays citations in the response": "応答に引用を表示", "Displays status updates (e.g., web search progress) in the response": "レスポンスにステータスの更新(例: ウェブ検索の進行状況)を表示します", "Dive into knowledge": "知識に飛び込む", @@ -626,6 +677,7 @@ "Docling Parameters": "", "Docling Server URL required.": "DoclingサーバーURLが必要です。", "Document": "ドキュメント", + "Document ID Field": "", "Document Intelligence": "ドキュメントインテリジェンス", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -681,12 +733,14 @@ "Edit Default Permissions": "デフォルトの許可を編集", "Edit Folder": "フォルダを編集", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "直前のメッセージを編集", "Edit Memory": "メモリを編集", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ユーザーを編集", "Edit User Group": "ユーザーグループを編集", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "編集済み", @@ -695,6 +749,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "メールアドレス", + "Email Claim": "", "Embark on adventures": "冒険に出かける", "Embedding": "埋め込み", "Embedding Batch Size": "埋め込みモデルバッチサイズ", @@ -703,6 +758,7 @@ "Embedding Model Engine": "埋め込みモデルエンジン", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "API キーを有効にする", @@ -710,22 +766,27 @@ "Enable Code Execution": "コードの実行を有効にする", "Enable Code Interpreter": "コードインタプリタを有効にする", "Enable Community Sharing": "コミュニティ共有を有効にする", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "メモリロック (mlock) を有効にして、モデルデータがRAMからスワップアウトされるのを防ぐ。このオプションは、モデルが現在使用しているページセットをRAMにロックし、ディスクにスワップアウトされないようにします。これにより、ページフォルトを回避し、高速なデータアクセスを保証することで、パフォーマンスの維持に役立ちます。 ", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "モデルデータのロードにメモリマッピング (mmap) を有効する。このオプションは、ディスクファイルをRAM内にあるかのように扱うことで、システムがディスクストレージをRAMの拡張として使用することを可能にします。これにより、より高速なデータアクセスが可能になり、モデルのパフォーマンスを向上させることができます。ただし、すべてのシステムで正しく動作するわけではなく、かなりのディスク容量を消費する可能性があります。 ", "Enable Message Queue": "", "Enable Message Rating": "メッセージ評価を有効にする", "Enable Mirostat sampling for controlling perplexity.": "Perplexityを制御するためにMirostatサンプリングを有効する。", "Enable New Sign Ups": "新規登録を有効にする", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "有効", "End Tag": "", + "Endpoint": "", "Endpoint URL": "エンドポイントURL", "Enforce Temporary Chat": "一時的なチャットを強制する", "Enhance": "改善する", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSVファイルには、次の4つの列をこの順番で含めてください: Name, Email, Password, Role。", "Enter {{role}} message here": "{{role}} メッセージをここに入力してください", - "Enter a detail about yourself for your LLMs to recall": "LLM が参照できるように、あなたに関する情報を入力してください", "Enter a title for the pending user info overlay. Leave empty for default.": "保留中のユーザー情報オーバーレイのタイトルを入力。デフォルトのままにする場合は空のままにします。", "Enter a watermark for the response. Leave empty for none.": "応答のウォーターマークを入力。なしの場合は空のままにします。", "Enter additional headers in JSON format": "", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "チャンクオーバーラップを入力", "Enter Chunk Size": "チャンクサイズを入力", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "カンマ区切りの \"token:bias_value\" ペアを入力 (例: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "保留中のユーザー情報オーバーレイの内容を入力。デフォルトのままにする場合は空のままにします。", "Enter coordinates (e.g. 51.505, -0.09)": "座標を入力", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "Jupyter URLを入力", "Enter Kagi Search API Key": "Kagi Search APIキーを入力", "Enter Key Behavior": "Enter Keyの動作", + "Enter language": "", "Enter language codes": "言語コードを入力", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Mistral APIキーを入力", @@ -800,6 +866,7 @@ "Enter prompt here.": "ここにプロンプトを入力", "Enter proxy URL (e.g. https://user:password@host:port)": "プロキシURLを入力 (例: https://user:password@host:port)", "Enter reasoning effort": "推論の努力を入力", + "Enter Redirect URI": "", "Enter Score": "スコアを入力", "Enter SearchApi API Key": "SearchApi API Keyを入力", "Enter SearchApi Engine": "SearchApi Engineを入力", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "SerpApi APIキーを入力", "Enter SerpApi Engine": "SerpApi Engineを入力", "Enter Serper API Key": "Serper APIキーの入力", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API Keyを入力", "Enter Serpstack API Key": "Serpstack APIキーの入力", "Enter server host": "サーバーホストを入力", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "Tika Server URLを入力", "Enter timeout in seconds": "タイムアウトを秒単位で入力", "Enter to Send": "送信する", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "トップ K を入力", "Enter Top K Reranker": "トップ K Rerankerを入力", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL を入力してください (例: http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "ID '{{modelId}}' のモデルはすでに存在します。他のIDを使用してください。", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "モデルIDを空にすることはできません。有効なIDを入力してください。", "Evaluations": "評価", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa APIキー", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "例: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "例: ALL", "Example: mail": "例: mail", @@ -901,12 +975,18 @@ "Export Config": "", "Export Models": "モデルをエクスポート", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CSVにエクスポート", "Export Tools": "ツールをエクスポート", "Export Users": "ユーザのエクスポート", "External": "外部", + "External connection not found.": "", "External Document Loader URL required.": "外部ドキュメントローダーのURLが必要です。", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "外部タスクモデル", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "外部ドキュメントローダーのAPIキー", "External Web Loader URL": "外部ドキュメントローダーのURL", "External Web Search API Key": "外部Web検索のAPIキー", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "APIキーの作成に失敗しました。", "Failed to delete calendar": "", "Failed to delete note": "ノートの削除に失敗しました。", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "ファイルから中身の取得に失敗しました: {{error}}", @@ -931,6 +1012,7 @@ "Failed to fetch models": "モデルの取得に失敗しました。", "Failed to generate title": "タイトルの生成に失敗しました。", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "チャットプレビューを読み込めませんでした。", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -940,6 +1022,7 @@ "Failed to move chat": "チャットの移動に失敗しました。", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "クリップボードの内容を読み取れませんでした。", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "モデルの設定の保存に失敗しました。", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "設定アップデートに失敗しました。", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "ファイルアップロードに失敗しました。", "Features": "機能", "Features Permissions": "機能の許可", @@ -983,6 +1068,8 @@ "File uploaded successfully": "ファイルアップロードが成功しました", "Filename": "ファイル名", "Files": "ファイル", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "フィルタ", "Filter is now globally disabled": "グローバルフィルタが無効です。", "Filter is now globally enabled": "グローバルフィルタが有効です。", @@ -1005,6 +1092,7 @@ "Folder options": "", "Folder updated successfully": "フォルダの更新に成功しました。", "Folders": "フォルダー", + "Folders Sharing": "", "Follow up": "関連質問", "Follow Up Generation": "関連質問の生成", "Follow Up Generation Prompt": "関連質問の生成プロンプト", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "Functionはグローバルで有効です。", "Function Name": "Function名", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Functionのアップデートが成功しました。", "Functions": "", "Functions allow arbitrary code execution.": "Functionsは任意のコード実行を許可します。", @@ -1067,7 +1156,10 @@ "Gravatar": "", "Grid": "グリッド", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "グループの作成が成功しました。", "Group deleted successfully": "グループの削除が成功しました。", "Group Description": "グループの説明", @@ -1079,6 +1171,7 @@ "H2": "見出し2", "H3": "見出し3", "Haptic Feedback": "触覚フィードバック", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "高さ", @@ -1109,6 +1202,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframeサンドボックスにフォームを許可", "iframe Sandbox Allow Same Origin": "iframeサンドボックスに同じオリジンを許可", @@ -1134,6 +1229,7 @@ "Import From Link": "リンクからインポート", "Import Models": "モデルをインポート", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "ツールをインポート", "Important Update": "重要な更新", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "サイドバーに残す", "Key": "キー", "Key is required": "キーは必須です", - "Keyboard shortcuts": "キーボードショートカット", "Keyboard Shortcuts": "キーボードショートカット", "Knowledge": "ナレッジベース", "Knowledge Access": "ナレッジアクセス", @@ -1204,6 +1299,8 @@ "Knowledge Name": "ナレッジベースの名前", "Knowledge Public Sharing": "ナレッジベースの公開共有", "Knowledge Sharing": "ナレッジベースの共有", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "ナレッジベースのアップデートに成功しました", "Kokoro.js (Browser)": "Kokoro.js (ブラウザ)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1220,7 +1317,6 @@ "Last ran": "最終実行", "Last reply": "最終応答", "LDAP": "LDAP", - "LDAP server updated": "LDAPサーバーの更新に成功しました", "Leaderboard": "リーダーボード", "Learn more": "", "Learn More": "詳しく", @@ -1242,6 +1338,7 @@ "Legacy": "", "lexical": "文法的", "License": "ライセンス", + "Lifecycle JSON": "", "Lift List": "リストを字下げ", "Light": "ライト", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1265,6 +1362,7 @@ "Location access not allowed": "位置情報のアクセスが許可されていません", "Lost": "負け", "Low": "低", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "OpenWebUI コミュニティによって作成", "Make password visible in the user interface": "UIでパスワードを可視にする", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "パイプラインの管理", "Manage Tool Servers": "ツールサーバーの管理", "Manage your account information.": "あなたのアカウント情報を管理", + "Mapped Source": "", "March": "3月", "Markdown": "マークダウン", "Markdown Header Text Splitter": "", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "メモリをクリアしました。", "Memory deleted successfully": "メモリを削除しました。", "Memory updated successfully": "メモリアップデート成功", + "Merge Accounts by Email": "", "Merge Responses": "応答を統合", "Merged Response": "統合された応答", "Message": "メッセージ", @@ -1318,9 +1418,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "リンクを作成した後で送信したメッセージは共有されません。URL を持つユーザーは共有チャットを閲覧できます。", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (個人用)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (職場/学校)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1373,6 +1476,7 @@ "Models Sharing": "モデルの共有", "Mojeek": "", "Mojeek Search API Key": "Mojeek Search APIキー", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "もっと見る", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "ナレッジベースに名前を付ける", "Name, prompt, and model are required": "名前、プロンプト、モデルの選択が必要です", "Native": "ネイティブ", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "なし", "New": "", "New Automation": "新しいオートメーション", @@ -1419,6 +1524,7 @@ "Next run": "次回実行", "No access grants. Private to you.": "アクセス権は付与されていません。あなただけが利用できます。", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "オートメーションが見つかりません", "No chats found": "チャットが見つかりません。", @@ -1431,8 +1537,10 @@ "No data": "", "No data found": "", "No distance available": "距離が利用できません", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "ファイルが選択されていません", "No files found": "", @@ -1460,6 +1568,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "プロンプトが見つかりません", + "No Repeat": "", "No results": "結果が見つかりません", "No results found": "結果が見つかりません", "No search query generated": "検索クエリは生成されません", @@ -1479,6 +1588,7 @@ "No webhooks yet": "", "Node Ids": "ノードID", "None": "なし", + "Not configured": "", "Not factually correct": "事実と異なる", "Not helpful": "役に立たない", "Not Registered": "", @@ -1494,20 +1604,25 @@ "Notifications": "デスクトップ通知", "November": "11月", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "10月", "Off": "オフ", "Okay, Let's Go!": "OK、始めましょう!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED ダーク", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API 設定が更新されました", "Ollama Cloud API Key": "", "Ollama Version": "Ollama バージョン", + "Omit": "", "On": "オン", "Once": "", "OneDrive": "", @@ -1578,6 +1693,7 @@ "Password": "パスワード", "Passwords do not match.": "パスワードが一致しません。", "Paste Large Text as File": "大きなテキストをファイルとして貼り付ける", + "Path": "", "Path copied": "", "Paused": "停止中", "PDF document (.pdf)": "PDF ドキュメント (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "保留中", "Pending": "処理中", + "Pending Accounts": "", "Pending User Overlay Content": "保留中のユーザー情報オーバーレイの内容", "Pending User Overlay Title": "保留中のユーザー情報オーバーレイのタイトル", "Permission denied when accessing media devices": "メディアデバイスへのアクセス時に権限が拒否されました", "Permission denied when accessing microphone": "マイクへのアクセス時に権限が拒否されました", "Permission denied when accessing microphone: {{error}}": "マイクへのアクセス時に権限が拒否されました: {{error}}", "Permissions": "権限", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API キー", "Perplexity Model": "Perplexity モデル", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "Perplexity Search コンテキスト使用量", "Persistent": "", "Personalization": "パーソナライズ", + "Picture Claim": "", "Pin": "ピン留め", "Pin to Sidebar": "", "Pinned": "ピン留めされています", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "すべてのフィールドを入力してください。", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "先にモデルを選択してください。", "Please select a model.": "モデルを選択してください。", "Please select a reason": "理由を選択してください。", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "ファイルがすべてアップロードされるまでお待ちください。", "Policy ID": "", + "Policy ID is required": "", "Port": "ポート", "Ports": "", "Positive attitude": "ポジティブな態度", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "プロンプトの公開共有", "Prompts Sharing": "プロンプトの共有", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "公開", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com から \"{{searchValue}}\" をプル", "Pull a model from Ollama.com": "Ollama.com からモデルをプル", @@ -1683,21 +1804,28 @@ "Read": "読み込む", "Read Aloud": "読み上げ", "Read more →": "", + "Read only": "", "Read Only": "読み取り専用", "Read-Only Access": "", "Reason": "理由", "Reasoning Effort": "推理の努力", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "録音", "Record voice": "音声を録音", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI コミュニティにリダイレクトしています", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "無意味な生成の確率を減少させます。高い値(例:100)はより多様な回答を提供し、低い値(例:10)ではより保守的になります。", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "あなたのことは「User」としてください(例:「User はスペイン語を学んでいます」)", "Reference Chats": "チャットを参照", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "拒否すべきでないのに拒否した", "Regenerate": "再生成", "Regenerate Menu": "再生成メニュー", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "モデルを並べ替え", + "Repeat": "", "Repeats": "繰り返し", "Reply": "", "Reply in Thread": "スレッドで返信", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "リランクエンジン", "Reranking Model": "リランクモデル", + "Research Knowledge": "", "Reset": "リセット", "Reset All Models": "すべてのモデルをリセット", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "画像をリセット", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "アップロードディレクトリをリセット", "Reset Vector Storage/Knowledge": "ベクターストレージとナレッジベースをリセット", "Reset view": "表示をリセット", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "1 件のソースを取得", "Rich Text Input for Chat": "チャットのリッチテキスト入力", "Role": "ロール", + "Roles Claim": "", "RTL": "RTL", "Run": "実行", "Run All": "", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "チャットログをブラウザのストレージに直接保存する機能はサポートされなくなりました。下のボタンをクリックして、チャットログをダウンロードして削除してください。ご心配なく。チャットログは、次の方法でバックエンドに簡単に再インポートできます。", "Schedule": "スケジュール", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "ブランチ変更時にスクロール", "Scroll to Top": "", "Search": "検索", "Search a model": "モデルを検索", + "Search actions": "", "Search all emojis": "絵文字を検索", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1792,6 +1930,7 @@ "Search Chats": "チャットの検索", "Search Collection": "コレクションの検索", "Search Files": "ファイルの検索", + "Search filters": "", "Search Filters": "フィルターの検索", "search for archived chats": "アーカイブされたチャットを検索", "search for folders": "フォルダを検索", @@ -1806,13 +1945,16 @@ "Search Models": "モデル検索", "Search Notes": "ノートを検索", "Search options": "検索オプション", + "Search or add pattern": "", "Search Prompts": "プロンプトを検索", "Search Result Count": "検索結果数", + "Search skills": "", "Search Skills": "Skillを検索", - "Search skills...": "", "Search the internet": "インターネットを検索", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "ツールの検索", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApiのAPIKey", "SearchApi Engine": "SearchApiエンジン", @@ -1828,7 +1970,6 @@ "Seed": "シード", "Select": "選択", "Select {{modelName}} model": "", - "Select a base model": "基本モデルの選択", "Select a base model (e.g. llama3, gpt-4o)": "基本モデルを選択 (例: llama3, gpt-4o)", "Select a conversation to preview": "プレビューする会話を選択してください", "Select a engine": "エンジンの選択", @@ -1866,18 +2007,25 @@ "semantic": "意味的", "Send": "送信", "Send a Message": "メッセージを送信", + "Send events for": "", "Send message": "メッセージを送信", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "リクエストに`stream_options: { include_usage: true }`を含めます。サポートされているプロバイダーは、レスポンスにトークン使用情報を返すようになります。", "September": "9月", "SerpApi API Key": "SerpApi APIキー", "SerpApi Engine": "SerpApiエンジン", "Serper API Key": "Serper APIキー", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply APIキー", "Serpstack API Key": "Serpstack APIキー", "Server connection failed": "", "Server connection verified": "サーバー接続が確認されました", + "Service Account": "", "Session": "セッション", + "Session expired. Please sign in again.": "", "Set as default": "デフォルトに設定", "Set as Production": "", "Set embedding model": "埋め込みモデルを設定", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "OpenWebUI コミュニティに共有", "Share your background and interests": "あなたの背景情報と興味を教えてください", + "Shared": "", "Shared Chats": "共有されたチャット", "Shared with you": "自分に共有", "Sharing Permissions": "共有に関する権限", "Show": "表示", - "Show \"What's New\" modal on login": "ログイン時に更新内容モーダルを表示", + "Show \"What's New\" Modal on Login": "ログイン時に更新内容モーダルを表示", "Show Admin Details in Account Pending Overlay": "アカウント保留中の管理者詳細を表示", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "フォーマットツールバーを表示", "Show image preview": "画像のプレビューを表示", "Show Model": "モデルを表示", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "ソース", + "Specific users or groups": "", "Speech Playback Speed": "音声の再生速度", "Speech recognition error: {{error}}": "音声認識エラー: {{error}}", "Speech-to-Text": "音声テキスト変換", @@ -1992,6 +2143,7 @@ "STT Settings": "STT設定", "Stylized PDF Export": "スタイル付きPDFエクスポート", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "サブタイトル", @@ -2016,8 +2168,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "システム", + "System events only": "", "System Instructions": "システムインストラクション", "System Prompt": "システムプロンプト", + "Table": "", "Tag": "", "Tags": "タグ", "Tags Generation": "タグ生成", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "デフォルトで一時的なチャット", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "テキスト分割", "Text-to-Speech": "テキスト音声変換", "Text-to-Speech Engine": "テキスト音声変換エンジン", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "入力音声の言語を指定します。ISO-639-1形式(例: ja)で指定すると精度や処理速度が向上します。空欄にすると自動言語検出が行われます。", "The LDAP attribute that maps to the mail that users use to sign in.": "ユーザーがサインインに使用するメールのLDAP属性。", "The LDAP attribute that maps to the username that users use to sign in.": "ユーザーがサインインに使用するユーザー名のLDAP属性。", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "リーダーボードは現在ベータ版であり、アルゴリズムを改善する際に評価計算を調整する場合があります。", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "ファイルの最大サイズ(MB単位)。この制限を超えるファイルサイズの場合、ファイルはアップロードされません。", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "一度に使用できるファイルの最大数。ファイルの数がこの制限を超える場合、ファイルはアップロードされません。", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "出力テキストの形式。'json', 'markdown', 'html'が設定できます。デフォルトは'markdown'です。", @@ -2075,6 +2234,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "実験的機能であり正常動作しない場合があります。", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "このモデルは公開されていません。別のモデルを選択してください。", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "このオプションは、モデルがリクエスト後メモリにどれくらい長く残るか設定します。 (デフォルト: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "このオプションは、コンテキストをリフレッシュする際に保持するトークンの数を制御します。例えば、2に設定すると、会話のコンテキストの最後の2つのトークンが保持されます。コンテキストを保持することで、会話の継続性を維持できますが、新しいトピックに応答する能力を低下させる可能性があります。", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "利用可能なエンドポイントについては、ドキュメントを参照してください。", "To select skills here, add them to the \"Skills\" workspace first.": "ここでSkillを選択するには、まず\"Skills\" ワークスペースに追加してください。", "To select toolkits here, add them to the \"Tools\" workspace first.": "ここでツールキットを選択するには、まず \"Tools\" ワークスペースに追加してください。", - "Toast notifications for new updates": "新しい更新のトースト通知", + "Toast Notifications for New Updates": "新しい更新のトースト通知", "Today": "今日", "Today at": "", "Today at {{LOCALIZED_TIME}}": "今日 {{LOCALIZED_TIME}}", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "この接続の有効性を切り替える", "Token": "トークン", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "冗長すぎる", @@ -2177,14 +2339,19 @@ "Unpin": "ピン留め解除", "Unpin from Sidebar": "", "Unravel secrets": "秘密を解き明かす", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "未対応のファイルタイプです", "Untagged": "タグなし", "Untitled": "タイトルなし", "Update": "更新", "Update and Copy Link": "リンクの更新とコピー", + "Update Email": "", "Update for the latest features and improvements.": "最新の機能と改善点を更新します。", + "Update Name": "", "Update password": "パスワードを更新", + "Update Picture": "", "Update your status": "ステータスを変更", "Updated": "更新されました", "Updated at": "更新日時", @@ -2211,13 +2378,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "#を入力するとナレッジベースを参照することができます。", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "LLMを使用する", "Use no proxy to fetch page contents.": "ページの内容を取得するためにプロキシを使用しません。", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "http_proxy と https_proxy 環境変数で指定されたプロキシを使用してページの内容を取得します。", + "Use Web Search?": "", "user": "ユーザー", "User": "ユーザー", + "User Access": "", "User Activity": "", "User Groups": "ユーザーグループ", "User location successfully retrieved.": "ユーザーの位置情報が正常に取得されました。", @@ -2227,6 +2399,7 @@ "User Status": "ユーザーステータス", "User Webhooks": "ユーザWebhook", "Username": "ユーザー名", + "Username Claim": "", "users": "", "Users": "ユーザー", "Uses DefaultAzureCredential to authenticate": "", @@ -2240,6 +2413,7 @@ "Valves updated": "バルブが更新されました", "Valves updated successfully": "バルブが正常に更新されました", "variable": "変数", + "Vector Field": "", "Verify Connection": "接続を確認", "Verify SSL Certificate": "SSL証明書を確認", "Version": "バージョン", @@ -2269,11 +2443,14 @@ "Web API": "ウェブAPI", "Web Loader Engine": "ウェブローダーエンジン", "Web Search": "ウェブ検索", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "ウェブ検索エンジン", "Web Search in Chat": "チャットでウェブ検索", "Web Search Query Generation": "ウェブ検索クエリ生成", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "ウェブページのURL", "WebUI Settings": "WebUI 設定", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "昨日", "Yesterday at {{LOCALIZED_TIME}}": "昨日 {{LOCALIZED_TIME}}", "You": "あなた", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "あなたの全ての寄付はプラグイン開発者へ直接送られます。Open WebUI は手数料を一切取りません。ただし、選択した資金提供プラットフォーム側に手数料が発生する場合があります。", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "YouTubeの言語", diff --git a/src/lib/i18n/locales/ka-GE/translation.json b/src/lib/i18n/locales/ka-GE/translation.json index f7190cdd2b..e78587a669 100644 --- a/src/lib/i18n/locales/ka-GE/translation.json +++ b/src/lib/i18n/locales/ka-GE/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} დამალული ხაზი", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} წყარო", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} სიტყვა", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} დრო {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} მოდელი გაუქმდა", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}-ის ჩათები", "{{webUIName}} Backend Required": "{{webUIName}} საჭიროა უკანაბოლო", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "1 წყარო", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "წვდომის კონტროლი", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "ხელმისაწვდომია ყველა მომხმარებლისთვის", "Account": "ანგარიში", @@ -72,6 +83,7 @@ "Activity": "", "Add": "დამატება", "Add a model ID": "მოდელის ID-ის დამატება", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "დაამატეთ მოკლე აღწერა იმის შესახებ, თუ რას აკეთებს ეს მოდელი", "Add a tag": "ჭდის დამატება", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "დეტალების დამატება", + "Add durable context for future chats": "", "Add Files": "ფაილების დამატება", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "მომხმარებლის დამატება", "Add User Group": "მომხმარებლის ჯგუფის დამატება", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "დამატებითი კონფიგურაცია", @@ -112,7 +127,9 @@ "Admin": "ადმინი", "Admin Contact Email": "", "Admin Panel": "ადმინისტრატორის პანელი", + "Admin Roles": "", "Admin Settings": "ადმინისტრატორის მორგება", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "დამატებითი პარამეტრები", @@ -123,16 +140,21 @@ "All": "ყველა", "All chats have been unarchived.": "ყველა ჩატი ამოღებული იქნა არქივიდან.", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "ყველა მოდელი წარმატებით წაიშალა", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "გამოძახების დაშვება", "Allow Chat Controls": "ჩატის კონტროლის ელემენტების დაშვება", "Allow Chat Delete": "ჩატის წაშლის დაშვება", "Allow Chat Edit": "ჩატის ჩასწორების დაშვება", "Allow Chat Export": "ჩატის გატანის დაშვება", + "Allow Chat Import": "", "Allow Chat Params": "ჩატის პარამეტრების დაშვება", "Allow Chat Share": "ჩატის გაზიარების დაშვება", "Allow Chat System Prompt": "ჩატის სისტემური მოთხოვნის დაშვება", @@ -152,9 +174,11 @@ "Allow User Location": "მომხმარებლის მდებარეობის დაშვება", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "დაშვებული ბოლოწერტილები", "Allowed File Extensions": "დაშვებული ფაილის გაფართოებები", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "უკვე გაქვთ ანგარიში?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "ყოველთვის", @@ -173,6 +197,7 @@ "API Base URL": "API-ის საბაზისო URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API გასაღები", + "API Key / Token": "", "API Key created.": "API გასაღები შეიქმნა.", "API Key Endpoint Restrictions": "", "API keys": "API გასაღებები", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "მართლა გნებავთ ამ შეტყობინების წასლა?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "არენის მოდელები", "Artifacts": "არტეფაქტები", "Asc": "", "Ask": "კითხვა", "Ask a question": "კითხვის დასმა", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "დამხმარე", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "აუდიო", "August": "აგვისტო", "Auth": "ავთენტ", + "Auth Mode": "", + "Auth required": "", "Authenticate": "ავთენტიკაცია", "Authentication": "ავთენტიკაცია", "Auto": "ავტო", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "პასუხის ავტომატური კოპირება ბუფერში", - "Auto-playback response": "ავტომატური დაკვრის პასუხი", + "Auto-Create Groups": "", + "Auto-Playback Response": "ავტომატური დაკვრის პასუხი", "Autocomplete Generation": "ავტოდასრულების გენერაცია", "Autocomplete Generation Input Max Length": "ავტოდასრულების გენერაციის შეყვანის მაქს. სიგრძე", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 საბაზისო მისამართი", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "ხელმისაწვდომი ხელსაწყოები", "available users": "ხელმისაწვდომი მომხმარებლები", + "Available variables": "", "available!": "ხელმისაწვდომია!", "Away": "გაცდენილი", "Awful": "საშინელი", @@ -258,16 +295,17 @@ "Bad Response": "არასწორი პასუხი", "Banners": "ბანერები", "Base Model (From)": "საბაზისო მოდელი (საიდან)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "Bearer", "before": "მითითებულ დრომდე", "Being lazy": "ზარმაცობა", - "Beta": "ბეტა", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7-ის ბოლოწერტილი", "Bing Search V7 Subscription Key": "Bing Search V7-ის გამოწერის გასაღები", "Bio": "ბიო", "Birth Date": "დაბადების თარიღი", + "Blocked Groups": "", "BM25 Weight": "BM25-ის წონა", "Bocha Search API Key": "Bocha-ის ძებნის API-ის გასაღები", "Bold": "სქელი", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "ჩატის საუბარი", "Chat deleted.": "", - "Chat direction": "ჩატის მიმართულება", + "Chat Direction": "ჩატის მიმართულება", "Chat exported successfully": "", "Chat History": "", "Chat ID": "ჩატის ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "აკეცვა", "Collection": "კოლექცია", + "Collection Field": "", "Collections": "", "Color": "ფერი", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI-ის სამუშაო პროცესი", "ComfyUI Workflow Nodes": "ComfyUI-ის სამუსაო პროცესის კვანძები", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "ბრძანება", "Comment": "კომენტარი", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "დასრულებები", "Compress Images in Channels": "გამოსახულებების შეკუმშვა არხებში", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "დაკავშირება ვერ მოხერხდა", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "შემცველობა", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "პასუხის გაგრძელება", "Continue with {{provider}}": "გაგრძელება {{provider}}-ით", "Continue with Email": "გაგრძელება ელფოსტით", @@ -493,6 +543,7 @@ "Create new secret key": "ახალი საიდუმლო გასაღების შექმნა", "Create note": "", "Create Note": "შენიშვნის შექმნა", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "შექმნის დრო", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "მორგებული პარამეტრის სახელი", "Custom Parameter Value": "მორგებული პარამეტრის მნიშვნელობა", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "საშიში ზონა", @@ -532,7 +584,6 @@ "Default Features": "ნაგულისხმევი ფუნქციები", "Default Filters": "ნაგულიხმევი ფილტრები", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "ნაგულისხმევი მოდელი", "Default model updated": "ნაგულისხმევი მოდელი განახლდა", "Default permissions": "ნაგულისხმები წვდომები", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "მომხმარებლის ნაგულისხმევი როლი", + "Default webhook": "", "Defaults": "", "Delete": "წაშლა", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "გამორთული", "Disconnect OAuth": "", "Discover a function": "აღმოაჩინეთ ფუნქცია", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "აღმოაჩინეთ, გადმოწერეთ და შეისწავლეთ მოდელის პარამეტრები", "Discussion channel where access is based on groups and permissions": "", "Display": "ჩვენება", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "ჩატში თქვენს მაგიერ მომხმარებლის სახელის ჩვენება", + "Display the Username Instead of You in the Chat": "ჩატში თქვენს მაგიერ მომხმარებლის სახელის ჩვენება", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "დოკუმენტი", + "Document ID Field": "", "Document Intelligence": "დოკუმენტის ანალიზი", "Document Intelligence endpoint required.": "დოკუმენტის ანალიზის ბოლოწერტილი აუცილებელია.", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "ნაგულისხმევი წვდომების ჩასწორება", "Edit Folder": "საქაღალდის ჩასწორება", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "მეხსიერების ჩასწორება", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "მომხმარებლის ჩასწორება", "Edit User Group": "მომხმარებლის ჯგუფის ჩასწორება", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "ჩასწორებულია", "Edited": "ჩასწორებულია", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "ელფოსტა", + "Email Claim": "", "Embark on adventures": "", "Embedding": "ჩაშენება", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "ჩაშენებული მოდელის ძრავა", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "კოდის შესრულების ჩართვა", "Enable Code Interpreter": "კოდის ინტერპრეტატორის ჩართვა", "Enable Community Sharing": "საზოგადოების გაზიარების ჩართვა", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "ახალი რეგისტრაციების ჩართვა", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "ჩართულია", "End Tag": "საბოლოო ჭდე", + "Endpoint": "", "Endpoint URL": "ბოლოწერტილის URL", "Enforce Temporary Chat": "ნაძალადევი დროებითი ჩატი", "Enhance": "გაუმჯობესება", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "დარწმუნდით, რომ თქვენი CSV-ფაილი შეიცავს 4 ველს ამ მიმდევრობით: სახელი, ელფოსტა, პაროლი, როლი.", "Enter {{role}} message here": "შეიყვანე {{role}} შეტყობინება აქ", - "Enter a detail about yourself for your LLMs to recall": "შეიყვანეთ რამე თქვენს შესახებ, რომ თქვენმა LLM-მა გაიხსენოს", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "შეიყვანეთ ფრაგმენტის გადაფარვა", "Enter Chunk Size": "შეიყვანე ფრაგმენტის ზომა", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "შეიყვანეთ Jupyter-ის URL", "Enter Kagi Search API Key": "", "Enter Key Behavior": "შეიყვანეთ გასაღების ქცევა", + "Enter language": "", "Enter language codes": "შეიყვანეთ ენის კოდები", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "შეიყვანეთ პროქსის URL (მაგ: https://user:password@host:port)", "Enter reasoning effort": "შეიყვანეთ მსჯელობის ძალისხმევა", + "Enter Redirect URI": "", "Enter Score": "შეიყვანეთ ქულა", "Enter SearchApi API Key": "შეიყვანეთ SearchApi API-ის გასაღები", "Enter SearchApi Engine": "შეიყვანეთ SearchApi-ის ძრავა", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "შეიყვანეთ SerpApi API-ის გასაღები", "Enter SerpApi Engine": "შეიყვანეთ SerpApi-ის ძრავა", "Enter Serper API Key": "შეიყვანეთ Serper API Key", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "შეიყვანეთ Serply API-ის გასაღები", "Enter Serpstack API Key": "შეიყვანეთ Serpstack API Key", "Enter server host": "შეიყვანეთ სერვერის ჰოსტი", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "შეიყვანეთ Tika-ის სერვერის URL", "Enter timeout in seconds": "შეიყვანეთ მოლოდინის ვადა წამებში", "Enter to Send": "ღილაკი Enter გასაგზავნად", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "შეიყვანეთ Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "შეიყვანეთ ბმული (მაგ: http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "შეფასებები", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API-ის გასაღები", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "მაგალითი: ALL", "Example: mail": "მაგალითი: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CVS-ში გატანა", "Export Tools": "", "Export Users": "მომხმარებლების გატანა", "External": "გარე", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "გარე ამოცანის მოდელი", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API-ის გასაღების შექმნა ჩავარდა.", "Failed to delete calendar": "", "Failed to delete note": "შენიშვნის წაშლა ჩავარდა", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "მოდელების გამოთხოვა ჩავარდა", "Failed to generate title": "სათაურის გენერაცია ჩავარდა", "Failed to import models": "მოდელების შემოტანა ჩავარდა", + "Failed to load chat": "", "Failed to load chat preview": "ვიდეოს მინიატურის ჩატვირთვა ჩავარდა", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "ჩატის გადატანა ჩავარდა", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ბუფერის შემცველობის წაკითხვა ჩავარდა", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "დიაგრამის რენდერი ჩავარდა", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "მოდელების კონფიგურაციის შენახვა ჩავარდა", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "პარამეტრების განახლება ჩავარდა", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "ფაილის ატვირთვა ჩავარდა.", "Features": "მახასიათებლები", "Features Permissions": "უფლებები ფუნქციებზე", @@ -987,6 +1075,8 @@ "File uploaded successfully": "ფაილი წარმატებით აიტვირთა", "Filename": "", "Files": "ფაილი", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "ფილტრი", "Filter is now globally disabled": "ფილტრი ახლა გლობალურად გამორთულია", "Filter is now globally enabled": "ფილტრი ახლა გლობალურად ჩართულია", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "საქაღალდე წარმატებით განახლდა", "Folders": "საქაღალდეები", + "Folders Sharing": "", "Follow up": "მიდევნება", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "ფუნქცია ახლა გლობალურად ჩართულია", "Function Name": "ფუნქციის სახელი", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "ფუნქცია წარმატებით განახლდა", "Functions": "ფუნქციები", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "გრავატარი", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "ჯგუფი წარმატებით შეიქმნა", "Group deleted successfully": "ჯგუფი წარმატებით წაიშალა", "Group Description": "ჯგუფის აღწერა", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "", + "Header variables": "", "Headers": "თავსართები", "Headers must be a valid JSON object": "", "Height": "სიმაღლე", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "შემოტანა ბმულიდან", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "შემოტანა წარმატებულია", "Import Tools": "", "Important Update": "მნიშვნელოვანი განახლება", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "დატოვება გვერდით პანელზე", "Key": "გასაღები", "Key is required": "გასაღები აუცილებელია", - "Keyboard shortcuts": "კლავიატურის მალსახმობები", "Keyboard Shortcuts": "", "Knowledge": "ცოდნა", "Knowledge Access": "წვდომა ცოდნასთან", @@ -1208,6 +1306,8 @@ "Knowledge Name": "ცოდნის სახელი", "Knowledge Public Sharing": "ცოდნის საჯარო გაზიარება", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "ცოდნა წარმატებით განახლდა", "Kokoro.js (Browser)": "Kokoro.js (ბრაუზერი)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "ბოლო პასუხი", "LDAP": "LDAP", - "LDAP server updated": "LDAP სერვერი განახლდა", "Leaderboard": "ლიდერების დაფა", "Learn more": "", "Learn More": "დაწვრილებით", @@ -1246,6 +1345,7 @@ "Legacy": "მოძველებული", "lexical": "ლექსიკური", "License": "ლიცენზია", + "Lifecycle JSON": "", "Lift List": "სიის აწევა", "Light": "ღია", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "მდებარეობასთან წვდომა დაშვებული არაა", "Lost": "წაგება", "Low": "დაბალი", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "შექმნილია OpenWebUI საზოგადოების მიერ", "Make password visible in the user interface": "პაროლის მომხმარებლის ინტერფეისში ჩვენება", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "მილსადენების მართვა", "Manage Tool Servers": "ხელსაწყოს სერვერების მართვა", "Manage your account information.": "მართეთ თქვენი ანგარიშის ინფორმაცია.", + "Mapped Source": "", "March": "მარტი", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "მოგონება წარმატებით გასუფთავდა", "Memory deleted successfully": "მოგონება წარმატებით წაიშალა", "Memory updated successfully": "მოგონება წარმატებით განახლდა", + "Merge Accounts by Email": "", "Merge Responses": "პასუხების შერწყმა", "Merged Response": "შერწყმული პასუხი", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "შეტყობინებები, რომელსაც თქვენ აგზავნით თქვენი ბმულის შექმნის შემდეგ, არ იქნება გაზიარებული. URL– ის მქონე მომხმარებლებს შეეძლებათ ნახონ საერთო ჩატი.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (პირადი)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (სამსახური/სკოლა)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "მეტი", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "საკუთარი", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "ავთენტიკაციის გარეშე", "No automations found": "", "No chats found": "ჩატების გარეშე", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "მანძილი ხელმისაწვდომი არაა", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "ფაილი არჩეული არაა", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "შეყვანები აღმოჩენილი არაა", + "No Repeat": "", "No results": "შედეგების გარეშე", "No results found": "შედეგების გარეშე", "No search query generated": "ძებნის მოთხოვნა არ შექმნილა", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "კვანძის ID-ები", "None": "არცერთი", + "Not configured": "", "Not factually correct": "მთლად სწორი არაა", "Not helpful": "სასარგებლო არაა", "Not Registered": "არაა რეგისტრირებული", @@ -1498,20 +1611,25 @@ "Notifications": "გაფრთხილებები", "November": "ნოემბერი", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "ოქტომბერი", "Off": "გამორთ", "Okay, Let's Go!": "აბა, წავედით!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED მუქი", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API-ის პარამეტრები განახლდა", "Ollama Cloud API Key": "Ollama Cloud API-ის გასაღები", "Ollama Version": "Ollama ვერსია", + "Omit": "", "On": "ჩართული", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "პაროლი", "Passwords do not match.": "პაროლები არ ემთხვევა.", "Paste Large Text as File": "დიდი ტექსტის ჩასმა ფაილის სახით", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF დოკუმენტი (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "დარჩენილი", "Pending": "დარჩენილი", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "ნებართვა უარყოფილია მიკროფონზე წვდომისას: {{error}}", "Permissions": "ნებართვები", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API-ის გასაღები", "Perplexity Model": "Perplexity-ის მოდელი", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "პერსონალიზაცია", + "Picture Claim": "", "Pin": "მიმაგრება", "Pin to Sidebar": "", "Pinned": "მიმაგრებულია", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "შეავსეთ ყველა ველი ბოლომდე.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "ჯერ აირჩიეთ მოდელი, გეთაყვა.", "Please select a model.": "აირჩიეთ მოდელი.", "Please select a reason": "აირჩიეთ მიზეზი", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "პორტი", "Ports": "", "Positive attitude": "პოზიტიური დამოკიდებულება", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "საჯარო", "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\"-ის გადმოწერა Ollama.com-იდან", "Pull a model from Ollama.com": "მოდელის გადმოწერა Ollama.com-დან", @@ -1687,21 +1811,29 @@ "Read": "წაკითხვა", "Read Aloud": "ხმამაღლა წაკითხვა", "Read more →": "მეტის წაკითხვა →", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "მიზეზი", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "ჩაწერა", "Record voice": "ხმის ჩაწერა", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "მიმდინარეობს გადამისამართება OpenWebUI-ის საზოგადოების საიტზე", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "უარა, როგორც უნდა იყოს", "Regenerate": "თავიდან გენერაცია", "Regenerate Menu": "მენიუს რეგენერაცია", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "მოდელების გადალაგება", + "Repeat": "", "Repeats": "", "Reply": "პასუხი", "Reply in Thread": "ნაკადში პასუხი", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "აუცილებელია", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Reranking მოდელი", + "Research Knowledge": "", "Reset": "ჩამოყრა", "Reset All Models": "ყველა მოდელის ჩამოყრა", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "სურათის აღდგენა", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "ატვირთვის საქაღალდის ჩამოყრა", "Reset Vector Storage/Knowledge": "", "Reset view": "ხედის ჩამოყრა", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "როლი", + "Roles Claim": "", "RTL": "RTL", "Run": "გაშვება", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "ჩეთის ისტორიის შენახვა პირდაპირ თქვენი ბრაუზერის საცავში აღარ არის მხარდაჭერილი. გთხოვთ, დაუთმოთ და წაშალოთ თქვენი ჩატის ჟურნალები ქვემოთ მოცემულ ღილაკზე დაწკაპუნებით. არ ინერვიულოთ, თქვენ შეგიძლიათ მარტივად ხელახლა შემოიტანოთ თქვენი ჩეთის ისტორია ბექენდში", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "ძებნა", "Search a model": "მოდელის ძებნა", + "Search actions": "", "Search all emojis": "ძებნა ყველა ემოჯიში", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "ძებნა ჩატებში", "Search Collection": "კოლექციის ძებნა", "Search Files": "", + "Search filters": "", "Search Filters": "ფილტრების ძებნა", "search for archived chats": "დაარქივებული ჩატების ძებნა", "search for folders": "საქაღალდეების ძებნა", @@ -1812,13 +1955,16 @@ "Search Models": "მოდელების ძებნა", "Search Notes": "შენიშვნების ძებნა", "Search options": "ძებნის მორგება", + "Search or add pattern": "", "Search Prompts": "მოთხოვნების ძებნა", "Search Result Count": "ძიების შედეგების რაოდენობა", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "ინტერნეტში ძებნა", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "ძებნის ხელსაწყოები", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API-ის გასაღები", "SearchApi Engine": "ძრავა SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "თესლი", "Select": "არჩევა", "Select {{modelName}} model": "", - "Select a base model": "აირჩიეთ საბაზისო მოდელი", "Select a base model (e.g. llama3, gpt-4o)": "აირჩიეთ საბაზისო მოდელი (მაგ: llama3, gpt-4o)", "Select a conversation to preview": "აირჩიეთ საუბარი გადასახედად", "Select a engine": "აირჩიეთ ძრავა", @@ -1872,18 +2017,25 @@ "semantic": "სემანტიკური", "Send": "გაგზავნა", "Send a Message": "შეტყობინების გაგზავნა", + "Send events for": "", "Send message": "შეტყობინების გაგზავნა", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "სექტემბერი", "SerpApi API Key": "SerpApi API-ის გასაღები", "SerpApi Engine": "ძრავა SerpApi", "Serper API Key": "Serper API-ის გასაღები", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API-ის გასაღები", "Serpstack API Key": "Serpstack API-ის გასაღები", "Server connection failed": "", "Server connection verified": "სერვერთან კავშირი გადამოწმებულია", + "Service Account": "", "Session": "სესია", + "Session expired. Please sign in again.": "", "Set as default": "ნაგულისხმევად დაყენება", "Set as Production": "", "Set embedding model": "ჩაშენებული მოდელის დაყენება", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "გაზიარება Open WebUI-ის საზოგადოებასთან", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "გაზიარებულია თქვენთვის", "Sharing Permissions": "გაზიარების წვდომები", "Show": "ჩვენება", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "დაფორმატების პანელის ჩვენება", "Show image preview": "გამოსახულების გადახედვის ჩვენება", "Show Model": "მოდელის ჩვენება", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "წყარო", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "საუბრის ამოცნობის შეცდომა: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT-ის მორგება", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "სისტემა", + "System events only": "", "System Instructions": "სისტემური ინსტრუქციები", "System Prompt": "სისტემური მოთხოვნა", + "Table": "", "Tag": "ჭდე", "Tags": "ჭდეები", "Tags Generation": "ჭდეების გენერაცია", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "დროებითი ჩატი ნაგულისხმევად", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "ტექსტის გამყოფი", "Text-to-Speech": "ტექსტის-ხმამაღლა-წაკითხვა", "Text-to-Speech Engine": "ტექსტურ-ხმოვანი ძრავი", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "დღეს", "Today at": "", "Today at {{LOCALIZED_TIME}}": "დღეს, {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "გადართვა, აქტიურია, თუ არა მიმდინარე კავშირი.", "Token": "კოდი", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "მეტისმეტად ბევრი სეტყობინება", @@ -2184,14 +2350,19 @@ "Unpin": "ჩამოხსნა", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "ჭდის გარეშე", "Untitled": "უსათაურო", "Update": "განახლება", "Update and Copy Link": "განახლება და ბმულის კოპირება", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "პაროლის განახლება", + "Update Picture": "", "Update your status": "", "Updated": "განახლებულია", "Updated at": "განახლების დრო", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "LLM-ის გამოყენება", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "მომხმარებელი", "User": "მომხმარებელი", + "User Access": "", "User Activity": "", "User Groups": "მომხმარებლის ჯგუფები", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "ვებჰუკების გამოყენება", "Username": "მომხმარებლის სახელი", + "Username Claim": "", "users": "", "Users": "მომხმარებლები", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "ონკანების განახლდა", "Valves updated successfully": "ონკანები წარმატებით განახლდა", "variable": "ცვლადი", + "Vector Field": "", "Verify Connection": "კავშირის გადამოწმება", "Verify SSL Certificate": "SSL სერტიფიკატის გადამოწმება", "Version": "ვერსია", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "ვებში ძებნა", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "ვებ საძიებო სისტემა", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI პარამეტრები", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "გუშინ", "Yesterday at {{LOCALIZED_TIME}}": "გუშინ, {{LOCALIZED_TIME}}", "You": "თქვენ", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube-ის ენა", diff --git a/src/lib/i18n/locales/kab-DZ/translation.json b/src/lib/i18n/locales/kab-DZ/translation.json index 88aaa0adca..2d0ac3dcd6 100644 --- a/src/lib/i18n/locales/kab-DZ/translation.json +++ b/src/lib/i18n/locales/kab-DZ/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} n yizirigen yeffren", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} n yiɣbula", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} n wawalen", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} ɣef {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Azdam n {{model}} yettusemmet", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Asqerdec n {{user}}", "{{webUIName}} Backend Required": "", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "1 n weɣbalu", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Asenqed n unekcum", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Yella i yiseqdacen i meṛṛa", "Account": "Amiḍan", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Rnu", "Add a model ID": "Rnu asulay n timudemt", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Rnu aglam wezzilen ɣef wayen i txeddem tmudemt-a", "Add a tag": "Rnu tabzimt", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "Rnu talqayt", + "Add durable context for future chats": "", "Add Files": "Rnu ifuyla", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Rnu aseqdac", "Add User Group": "Rnu agraw n iseqdacen", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "Tawila tamernant", @@ -112,7 +127,9 @@ "Admin": "Anebdal", "Admin Contact Email": "", "Admin Panel": "Agalis n tedbelt", + "Admin Roles": "", "Admin Settings": "Iɣewwaṛen n unedbal", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Inedbalen sɛan anekcum ɣer meṛṛa ifecka melmi i bɣan; iseqdacen ilaq ad asen-ttwamudden yifecka i yal tamudemt deg tallunt n umahil.", "Advanced": "", "Advanced Parameters": "Iɣewwaren leqqayen", @@ -123,16 +140,21 @@ "All": "Akk", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Akk timudmiwin ttwakksent akken iwata", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Sireg asiwel", "Allow Chat Controls": "Sireg isenqaden n usqerdec", "Allow Chat Delete": "Sireg tukksa n yidiwenniyen", "Allow Chat Edit": "Sireg asenfel n usqerdec", "Allow Chat Export": "Sireg asifeḍ n usqerdec", + "Allow Chat Import": "", "Allow Chat Params": "Sireg iɣewwaren n udiwenni", "Allow Chat Share": "Sireg beṭṭu n usqerdec", "Allow Chat System Prompt": "Sireg aneftaɣ n unagraw n udiwenni", @@ -152,9 +174,11 @@ "Allow User Location": "Sireg adig n useqdac", "Allow Voice Interruption in Call": "Sireg anegzum n tavuct lawan n usiwel", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "Isiɣzaf n ufaylu i yettwasirgen", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Ɣur-k·m yakan amiḍan?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Yal tikkelt", @@ -173,6 +197,7 @@ "API Base URL": "Tansa URL n taffa i API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Tasarutt API", + "API Key / Token": "", "API Key created.": "Tasarut API tennulfa-d.", "API Key Endpoint Restrictions": "Agaz n ugaz n tsarut API", "API keys": "Tisura API", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Tetḥeqqeḍ tebɣiḍ ad tekkseḍ izen-a?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Tetḥeqqemt tebɣamt ad d-tekksemt akk iqecwalen iarkasen?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Timudmiwin n Arena", "Artifacts": "Tarkisant", "Asc": "", "Ask": "Suter", "Ask a question": "Efk-d asteqsi", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Amallal", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Ameslaw", "August": "Ɣuct", "Auth": "Asesteb", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Sesteb", "Authentication": "Asesteb", "Auto": "Awurman", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Anɣal n tiririt tawurmant ɣer tecfawt", - "Auto-playback response": "Taɣuṛi tawurmant n tririt", + "Auto-Create Groups": "", + "Auto-Playback Response": "Taɣuṛi tawurmant n tririt", "Autocomplete Generation": "Asirew n yisumar", "Autocomplete Generation Input Max Length": "Tasuta tawurmant Tafulfulfulmant Input Max Length", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Azrir AUTOMATIC1111 n usesteb n API", "AUTOMATIC1111 Base URL": "URL n taffa i AUTOMATIC1111", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Ifecka i yellan", "available users": "Iseqdacen yellan", + "Available variables": "", "available!": "yella!", "Away": "Ulac", "Awful": "D tawaɣit", @@ -258,16 +295,17 @@ "Bad Response": "Yir tiririt", "Banners": "Iɣerracen", "Base Model (From)": "Tamudemt tazadurt (Seg)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Umuɣ n uzadur n tebdart Cache yessazzel anekcum s tmudmin tidusanin kan deg ubeddu neɣ deg yiɣewwaren i d-yettwasellken — amestir, maca yezmer lḥal ur d-yesskan ara ibeddilen ineggura n tmudemt azadur.", "Bearer": "", "before": "send", "Being lazy": "Ili-k d ameɛdaz", - "Beta": "Biṭa", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "Tasarut n umulteɣ Bing Search V7", "Bio": "Tameddurt", "Birth Date": "Azemz n tlalit", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Tasarut API n Bocha Search", "Bold": "Azuran", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "Asqerdec n udiwenni", "Chat deleted.": "", - "Chat direction": "Tanila n udiwenni", + "Chat Direction": "Tanila n udiwenni", "Chat exported successfully": "", "Chat History": "", "Chat ID": "Asulay ID n udiwenni", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Sneḍfes", "Collection": "Tagrumma", + "Collection Field": "", "Collections": "", "Color": "Ini", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "Asuddem n umahil n ComfyUI", "ComfyUI Workflow Nodes": "Taneddict n usuddem n umahil n ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Anezḍay", "Comment": "Awennit", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Tisemdiyin", "Compress Images in Channels": "Skussem tugniwin deg Yibuda", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Qqen ɣer wagazen-ik n taggara n API yemṣaban OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Qqen ɣer yiqeddacen-ik n yifecka imeṛṛa yeldin.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Tuqqna d-tawezɣit", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Admin n unermis i WebUI", "Content": "Agbur", "Content Extraction Engine": "Amsedday n uselkem n ugbur", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Kemmel tiririt", "Continue with {{provider}}": "Kemmel s {{provider}}", "Continue with Email": "Kemmel s yimayl", @@ -493,6 +543,7 @@ "Create new secret key": "Snulfu-d tasarut tuffirt tamaynut", "Create note": "", "Create Note": "Snulfu-d tazmilt", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Rnu tazmilt-ik⋅im tamezwarut s usiti ɣef tqeffalt ddaw.", "Created at": "Yettwarna di", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "Isem n uɣewwar udmawan", "Custom Parameter Value": "Azal n uɣewwar udmawan", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Tamnaḍt i iweɛren", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "Imsizdigen imezwura", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Tamudemt tamezwart", "Default model updated": "Tamudemt amezwar, tettwaleqqem", "Default permissions": "Tisirag timezwura", @@ -542,6 +593,7 @@ "Default to ALL": "S wudem amezwar i meṛṛa", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Ma nmuqel amek ara nɛawed ad nɛawed ad nɛawed ad nɛawed ad d-nekkes ayen yesɛan azal d wayen icudden ɣer ugbur, ilaq-as i tuget n tegnatin.", "Default User Role": "Tamlilt n useqdac amezwar", + "Default webhook": "", "Defaults": "", "Delete": "Kkes", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Sens asegzay n tengalt", "Disable Image Extraction": "Sens afsay n tugniwin", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Kkes-d asufeɣ n tugna seg PDF. Ma yella aseqdec n LLM yermed, tugniwin ad ttwakelsent s wudem awurman. Imezwura ɣer False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Yensa", "Disconnect OAuth": "", "Discover a function": "Af-d tasɣent", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Af-d, zdem-d, tesnirmeḍ-d iferdisen n tmudemt", "Discussion channel where access is based on groups and permissions": "", "Display": "Beqqeḍ", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Sken imujitin lawan n usiwel", "Display Multi-model Responses in Tabs": "Sken tririyin n waget-tmudmiwin deg waccaren", - "Display the username instead of You in the Chat": "Sken isem n useqdac deg wadeg n \"Kečč⋅Kemm\" deg yidiwenniyen", + "Display the Username Instead of You in the Chat": "Sken isem n useqdac deg wadeg n \"Kečč⋅Kemm\" deg yidiwenniyen", "Displays citations in the response": "Yeskan tibdarin deg tririt", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Kcem daxel n tmussniwin", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Tansa URL n uqeddac tuḥwaǧ.", "Document": "Imesli", + "Document ID Field": "", "Document Intelligence": "Tigzi n tsemlit", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Senfel tisirag timezwar", "Edit Folder": "Ẓreg akaram", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Ẓreg takatut", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Ẓreg aseqdac", "Edit User Group": "Ẓreg agraw n iseqdacen", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "yettwaẓreg", "Edited": "Yettwaẓrag", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Imayl", + "Email Claim": "", "Embark on adventures": "Kcem deg tmseksalin", "Embedding": "Ajmak", "Embedding Batch Size": "Teɣzi n tesmelt n ujmak", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Amsedday n tmudemt n ujmak", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Rmed aselkem n tengalt", "Enable Code Interpreter": "Rmed asegzay n tengalt", "Enable Community Sharing": "Rmed beṭṭu n temɣiwent", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Rmed Mapping (map) n usali n yisefka n tmudemt. Tifrat-a ad teǧǧ anagraw ad yesseqdec asigez n uḍebsi d asiɣzef n RAM s udawi n yifuyla n uḍebsi amzun deg RAM i llan. Aya yezmer ad yesnerni aswir n tmudemt s usireg n unekcum ɣer yisefka arurad ugar. D acu kan, yezmer lḥal ur yetteddu ara akken iwata s yinagrawen akk yernu yezmer ad yečč aṭas n tallunt n uḍebsi.", "Enable Message Queue": "", "Enable Message Rating": "Rmed aktazal n yiznan", "Enable Mirostat sampling for controlling perplexity.": "Rmed askar n Mirostat akken ad tḥekmed deg lbaṭel.", "Enable New Sign Ups": "Rmed azmul amaynut Kkret", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "D urmid", "End Tag": "Tabzimt n tagara", + "Endpoint": "", "Endpoint URL": "URL n wagaz n uzgu", "Enforce Temporary Chat": "Ḥettem idiwenniyen iskudanen", "Enhance": "Yesnernay", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Ssefqed afaylu-inek CSV deg-s 4 n tgejda deg uswir-a: Isem, Email, awal uffir, Role.", "Enter {{role}} message here": "Sekcem izen n {{role}} dagi", - "Enter a detail about yourself for your LLMs to recall": "Ssekcem-d ttfaṣil ɣef yiman-nnek akken ad d-temmektid LLMs-nnek akken ad d-temmektid", "Enter a title for the pending user info overlay. Leave empty for default.": "Sekcem azwel i ugrudem n useqdac la yettraǧun. Eǧǧ-it d ilem i umezwar.", "Enter a watermark for the response. Leave empty for none.": "Sekcem ticreḍt tafrawant i tririt. Eǧǧ-it d ilem i wulac.", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Sekcem ambiwel n yifendasen", "Enter Chunk Size": "Sekcem tiddi n iceqqfan", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Kcem ɣer tyugiwin \"token:bias_value\" i d-yezgan gar-asent (amedya: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Sekcem agbur n telɣut n useqdac yettwaṛjan. Eǧǧ ilem i tazwara.", "Enter coordinates (e.g. 51.505, -0.09)": "Sekcem-d timsidag (amedya 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Sekcem URL n Jupyter", "Enter Kagi Search API Key": "Sekcem-d tasarut API n Kagi Search", "Enter Key Behavior": "Kcem ɣer tsarut Behavior", + "Enter language": "", "Enter language codes": "Sekcem-d tangalin n tutlayin", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Enter Mistral API Tasarut", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Sekcem URL apṛuksi (amedya. https://user:password@host:port)", "Enter reasoning effort": "Sekcem ussis n uẓeɣẓen", + "Enter Redirect URI": "", "Enter Score": "Sekcem agmuḍ-ik⋅im", "Enter SearchApi API Key": "Sekcem-d tasarut API n SearchApi", "Enter SearchApi Engine": "Sekcem-d amsadday SearchApi", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Kcem ar Serp Tasarut API", "Enter SerpApi Engine": "Sekcem-d amsedday n SerpApi", "Enter Serper API Key": "Sekcem API n uqeddac Tasarut", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Sekcem API Tasarut", "Enter Serpstack API Key": "Sekcem tasarut API n Serpstack", "Enter server host": "Sekcem asenneftaɣ n uqeddac", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Sekcem tansa URL n uqeddac Tika", "Enter timeout in seconds": "Kcem ɣer wakud deg tsinin", "Enter to Send": "Sit ɣer Enter i tuzna", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Sekcem-d azal n Top K", "Enter Top K Reranker": "Kcem ɣer Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Sekcem tansa URL (amedya. http://127.0.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Iktazalen", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Tasarut API n Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Amedya: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Amedya: AKK", "Example: mail": "Amedya: imayl", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Kter ɣer CSV", "Export Tools": "", "Export Users": "Sifeḍ iseqdacen", "External": "Azɣaray", + "External connection not found.": "", "External Document Loader URL required.": "URL n uslay n yisemli azɣaray, yettwasra.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Tamudemt n temsekrit tazɣarayt", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "API n isebtar web imeṛṛa Tasarut", "External Web Loader URL": "Tansa URL tuffiɣt", "External Web Search API Key": "Tasarut API n unadi yeffɣen ɣef Web", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Ur yessaweḍ ara ad d-yesnulfu tasarut API.", "Failed to delete calendar": "", "Failed to delete note": "Ur yessaweḍ ara ad yekkes tazmilt", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "Ur yessaweḍ ara ad d-yekkes agbur seg ufaylu: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Ur ssawḍent ara ad d-awint timudmin tigennawin", "Failed to generate title": "Ur yessaweḍ ara ad d-yawi azwel", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "Yecceḍ usali n teskant n udiwenni", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "Tuccḍa deg unkaz n udiwenni", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Ur yessaweḍ ara ad iɣer agbur n tfelwit", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Ur yessaweḍ ara ad d-yessukkes tamudemt n usneftaɣ", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Yecceḍ uleqqem n yiɣewwaren", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Yecceḍ uzdam n ufaylu.", "Features": "Timahilin", "Features Permissions": "Tisirag n tmehilin", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Afaylu-nni yuli akken iwata", "Filename": "", "Files": "Ifuyla", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Imsizdeg", "Filter is now globally disabled": "Afaylu tura d ameɛdur amaḍalan", "Filter is now globally enabled": "Afaylu yettwarmed deg umaḍal tura", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "Akaram yettwaleqqem akken iwata", "Folders": "Ikaramen", + "Folders Sharing": "", "Follow up": "Aḍfaṛ", "Follow Up Generation": "Ḍfer asirew", "Follow Up Generation Prompt": "Ḍfer tiwtilin n tsuta", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Tawuri termed akka s umata", "Function Name": "Isem n tesɣent", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Tasɣent tettwaleqqem akken iwata", "Functions": "Tisɣunin", "Functions allow arbitrary code execution.": "Tiwuriwin ssirigent aselkem n tengalt tagacurant.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Agraw yennulfa-d akken iwata", "Group deleted successfully": "Agraw yettwakkes akken iwata", "Group Description": "Aglam n ugraw", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "", + "Header variables": "", "Headers": "Iqeṛṛa", "Headers must be a valid JSON object": "", "Height": "Teɣzi", @@ -1113,6 +1209,8 @@ "ID": "Asulay", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "Kter seg useɣwen", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "Taktert tella-d akken iwata", "Import Tools": "", "Important Update": "Aleqqem ahemmu", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Senṭeḍ-it deg ufeggag n yidis", "Key": "Tasarutt", "Key is required": "Tlaq tsarut", - "Keyboard shortcuts": "Inegzumen n unasiw", "Keyboard Shortcuts": "", "Knowledge": "Tamusni", "Knowledge Access": "Anekcum ɣer tmussni", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Isem n tmessunt", "Knowledge Public Sharing": "Beṭṭu azayaz n tmussniwin", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Timussniwin ttwaleqqment akken iwata", "Kokoro.js (Browser)": "Kokoro.js (Iminig)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Tiririt taneggarut", "LDAP": "LDAP", - "LDAP server updated": "Aqeddac LDAP, yettwaleqqem", "Leaderboard": "Asismel", "Learn more": "", "Learn More": "Issin ugar", @@ -1246,6 +1345,7 @@ "Legacy": "Aqbur", "lexical": "Amawal", "License": "Turagt", + "Lifecycle JSON": "", "Lift List": "Tabdart n usali", "Light": "Aceɛlal", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Anekcum ɣer tuddna", "Lost": "Iruḥ", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Texdem-it-id temɣiwant n Open WebUI", "Make password visible in the user interface": "Sken-d awal n uɛeddi deg ugrudem n useqdac", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Sefrek iseldayen", "Manage Tool Servers": "Sefrek iqeddacen n ifecka", "Manage your account information.": "Sefrek ilɣa-inek·inem n umiḍan.", + "Mapped Source": "", "March": "Meɣres", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Tettwasfeḍ tkatut akken iwata", "Memory deleted successfully": "Asmekti yettwakkes akken iwata", "Memory updated successfully": "Takatut tettwaleqqem akken iwata", + "Merge Accounts by Email": "", "Merge Responses": "Smezdi tiririyin", "Merged Response": "Tiririyin mmezdint", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Izen ara d-tazneḍ mi ara d-tesnulfuḍ aseɣwen-ik ur yettwabḍu ara. Iseqdacen yesɛan tansa URL ad izmiren ad walin adiwenni-nni yettwabḍan.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (udmawan)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (axeddim/aɣerbaz)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Tasarut API n Mojeek", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Ugar", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Mudd isem i taffa-k⋅m n tmussniwin", "Name, prompt, and model are required": "", "Native": "Asrew", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "Ulac asesteb", "No automations found": "", "No chats found": "Ulac idiwenniyen", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Ulac ameccaq yettwafen", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ulac afaylu i yettwafernen", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Ulac igmaḍ yettwafen", "No results found": "Ulac igmaḍ yettwafen", "No search query generated": "Ulac tuttra n unadi yettusirwen", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Ula d yiwen", + "Not configured": "", "Not factually correct": "", "Not helpful": "Ur infiɛ ara", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Tilɣa", "November": "Wambeṛ", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "Asulay OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Tubeṛ", "Off": "Yensa", "Okay, Let's Go!": "Yerbaḥ, aha yya!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Aberkan OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Iɣewwaren n API Olama ttwaleqqmen", "Ollama Cloud API Key": "Tasarut API n Ollama Cloud", "Ollama Version": "Lqem n Ollama", + "Omit": "", "On": "Irmed", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Awal n uɛeddi", "Passwords do not match.": "Awalen n uɛeddi ur mṣadan ara.", "Paste Large Text as File": "Senteḍ aḍris meqqren am ufaylu", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Isemli PDF (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "yettṛaǧu", "Pending": "Yegguni", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "Titre n useqdac nnig wakal", "Permission denied when accessing media devices": "Ttwagedlent tsirag lawan n unekcum ɣer yibenkan n yimidyaten", "Permission denied when accessing microphone": "Yettwagdel unekcum ɣer usawaḍ", "Permission denied when accessing microphone: {{error}}": "Yettwagdel unekcum ɣer usawaḍ: {{error}}", "Permissions": "Tisirag", + "Permissions reset to defaults": "", "Perplexity API Key": "Tasarut API n Perplexity", "Perplexity Model": "Tamudemt n Perplexity", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Asagen", + "Picture Claim": "", "Pin": "Senteḍ", "Pin to Sidebar": "", "Pinned": "Yettwasenteḍ", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Ttxil-k·m, fren tamudemt di tazwara.", "Please select a model.": "Ttxil-k, fren tamudemt.", "Please select a reason": "Ma ulac aɣilif ini-d acuɣeṛ", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Ttxil-k·m, ṛǧu alamma ulin-d akk ifuyla.", "Policy ID": "", + "Policy ID is required": "", "Port": "Tawwurt", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Beṭṭu azayaz n yineftaɣen", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Azayaz", "Pull \"{{searchValue}}\" from Ollama.com": "Awway n \"{{searchValue}}\" seg Ollama.com", "Pull a model from Ollama.com": "Zdem-d tamudemt seg Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Ɣeṛ", "Read Aloud": "Ɣeṛ-it-id s taɣect ɛlayen", "Read more →": "Ɣeṛ ugar →", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "Ssebba", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Aklas", "Record voice": "Sekles taɣect", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Aseḍfeṛ ar Temɣiwant n Open WebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Err iman-ik d \"Aseqdac\" (amedya, \"Aseqdac ilemmed taspenyulit\")", "Reference Chats": "Mselɣu idiwenniyen", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "Asirew", "Regenerate Menu": "Sarew-d umuɣ", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Ales n umizwer n tmudmiwin", + "Repeat": "", "Repeats": "", "Reply": "Tiririt", "Reply in Thread": "Err deg udiwenni", "Reply to thread...": "Err i udiwenni…", "Replying to {{NAME}}": "Tiririt i {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "yettwasra", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "Wennez", "Reset All Models": "Ales akk timudmiwin", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Ales awennez n tugna", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Wennez akaram n uzdam", "Reset Vector Storage/Knowledge": "", "Reset view": "Wennez askan", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "Yufa-d 1 n uɣbalu", "Rich Text Input for Chat": "Aḍris anesbaɣur", "Role": "Tamlilt", + "Roles Claim": "", "RTL": "RTL", "Run": "Selkem", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Abeddel n Branch", "Scroll to Top": "", "Search": "Anadi", "Search a model": "Nadi tamudemt", + "Search actions": "", "Search all emojis": "Nadi akk imujiten", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Nadi idiwenniyen", "Search Collection": "Nadi talkensit", "Search Files": "", + "Search filters": "", "Search Filters": "Imsizedgen n unadi", "search for archived chats": "", "search for folders": "anadi ɣef yikaramen", @@ -1812,13 +1955,16 @@ "Search Models": "Nadi timudmiwin", "Search Notes": "Nadi tizmilin", "Search options": "Tixtiṛiyin n unadi", + "Search or add pattern": "", "Search Prompts": "Anadi ɣef yineftaɣen", "Search Result Count": "Amḍan n yigmaḍ n unadi", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Anadi deg Internet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Nadi ifecka", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Tasarut API n SearchApi", "SearchApi Engine": "Amsadday n unadi SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Fren", "Select {{modelName}} model": "", - "Select a base model": "Fren tamudemt azadur", "Select a base model (e.g. llama3, gpt-4o)": "Fren tamudemt n taffa (amedya, llama3, gpt-4o)", "Select a conversation to preview": "Fren adiwenni i teskant", "Select a engine": "Fren amsedday", @@ -1872,18 +2017,25 @@ "semantic": "tasnamekt", "Send": "Ceyyeɛ", "Send a Message": "Ceyyeɛ izen", + "Send events for": "", "Send message": "Azen izen", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Ctembeṛ", "SerpApi API Key": "Tasarut API n SerpApi", "SerpApi Engine": "Amsedday SerpApi", "Serper API Key": "Tasarut API n Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Tasarut API n Serply", "Serpstack API Key": "Tasarut API n Serpstack", "Server connection failed": "", "Server connection verified": "Tuqqna ɣer uqeddac, tettwasenqed", + "Service Account": "", "Session": "Tiɣimit", + "Session expired. Please sign in again.": "", "Set as default": "Sbadu-t d amezwaru", "Set as Production": "", "Set embedding model": "Sbadu tamudemt n ujmak", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Bḍu i tkebbanit WebUI yeldin", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Tisirag n beṭṭu", "Show": "Sken-d", - "Show \"What's New\" modal on login": "Sken-d \"D acu i d askar amaynut\" deg uɣmis", + "Show \"What's New\" Modal on Login": "Sken-d \"D acu i d askar amaynut\" deg uɣmis", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Skan amsal n ufeggag n yifecka", "Show image preview": "Sken taskant n tugna", "Show Model": "Sken-d tamudemt", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Asulay API n Sougou Search (sID)", "Sougou Search API SK": "Tasarut tuffirt n API Sougou Search (SK)", "Source": "Aɣbalu", + "Specific users or groups": "", "Speech Playback Speed": "Arured n tɣuri n umeslay", "Speech recognition error: {{error}}": "Tuccḍa n uɛqal n wawal: {{error}}", "Speech-to-Text": "Aɛqal n taɣect", @@ -1999,6 +2154,7 @@ "STT Settings": "Iɣewwaren n uɛqal n tavect", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Anagraw", + "System events only": "", "System Instructions": "Tanaḍin n unagraw", "System Prompt": "Aneftaɣ n unagraw", + "Table": "", "Tag": "Tabzimt", "Tags": "Tibzimin", "Tags Generation": "Asirew n tebzimin", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Asqerdec uɛḍil s wudem amezwer", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Amebḍay n uḍris", "Text-to-Speech": "Aḍris-ɣer-taɣect", "Text-to-Speech Engine": "Amsadday n TTS", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "Imyerr LDAP i d-ttawint tgertilin ɣer tebratin i sseqdacen yiseqdacen akken ad zemlen.", "The LDAP attribute that maps to the username that users use to sign in.": "Imyerr LDAP i d-yeqqaren tikarḍiwin i yisem n useqdac i sseqdacen yiseqdacen akken ad zemlen.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Tafelwit n uɣella attan akka tura deg beta, dɣa nezmer ad neswati leḥsabat n ṭṭubba akken ara nessinef alguritm.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Tiddi n ufaylu afellay deg MB. Ma yella teɣzi n ufaylu tɛedda i talast-a, afaylu ur yettali ara.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Amḍan afellay n yifuyla i izemren ad ttwasqedcen ɣef tikkelt deg udiwenni. Ma yella amḍan n yifuyla iɛedda i talast-a, ifuyla ur ttalin ara.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Amasal n tuffɣa i uḍris. Tzemreḍ ad tiliḍ d 'json', d 'markdown' neɣ d 'html'. Imezwura ɣer 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ta d taɣawsa tirmitant, yezmer lḥal ur tleḥḥu ara akken i tebɣiḍ, dɣa d asentel n ubeddel melmi tebɣiḍ.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Tamudemt-a ur telli d tazayezt akk i medden. Ttxil-k·m, fren tamudemt nniḍen.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Akken ad tissineḍ ugar ɣef wagazen n taggara yellan, rzu ɣer warrat-nneɣ.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Akken ad tferneḍ ifecka da, rnu-ten, di tazwara, ɣer tallunt n umahil \"Ifecka\".", - "Toast notifications for new updates": "Ssurfet ilɣa i yileqman imaynuten", + "Toast Notifications for New Updates": "Ssurfet ilɣa i yileqman imaynuten", "Today": "Ass-a", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Ass-a, ɣef {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Sken ma yella tuqqna tamirant d turmidt.", "Token": "Ajiṭun", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "Kkes asenteḍ", "Unpin from Sidebar": "", "Unravel secrets": "Sban-d ayen yeffren", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "Tawsit n ufaylu ur tettusefrak ara.", "Untagged": "Tekkes-as tebzimt", "Untitled": "War azwel", "Update": "Muceḍ", "Update and Copy Link": "Leqqem aseɣwen", + "Update Email": "", "Update for the latest features and improvements.": "Leqqem tiɣawsiwin tineggura d usnerni.", + "Update Name": "", "Update password": "Leqqem awal n uɛeddi", + "Update Picture": "", "Update your status": "", "Updated": "Yettuleqqmen", "Updated at": "Yettwaleqqem", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Seqdec '#' deg urti n usekcem n uneftaɣ i wakken ad tɛebbiḍ timessunin-inek·inem.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Seqdec LLM", "Use no proxy to fetch page contents.": "Ur sseqdacet ara ayen yellan deg usebter apṛuksi.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Seqdec proxy i d-yesnulfa http_proxy akked https_proxy environment variables to fetch page contents.", + "Use Web Search?": "", "user": "aseqdac", "User": "Aseqdac", + "User Access": "", "User Activity": "", "User Groups": "Agraw n iseqdacen", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Webhooks n yiseqdacen", "Username": "Isem n useqdac", + "Username Claim": "", "users": "", "Users": "Iseqdacen", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Isegganen ttwaleqmen", "Valves updated successfully": "Valves ttwaleqmen akken iwata", "variable": "tamattayt", + "Vector Field": "", "Verify Connection": "Senqed tuqqna", "Verify SSL Certificate": "Senqed aselkin SSL", "Version": "Lqem", @@ -2276,11 +2454,14 @@ "Web API": "API Web", "Web Loader Engine": "Amsedday n uzdam Web", "Web Search": "Anadi deg Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Amsadday n unadi Web", "Web Search in Chat": "Anadi Web deg udiwenni", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Tansa URL n webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Iɣewwaṛen n WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Iḍelli", "Yesterday at {{LOCALIZED_TIME}}": "Iḍelli, ɣef {{LOCALIZED_TIME}}", "You": "Kečč·mm", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "Tutlayt n Youtube", diff --git a/src/lib/i18n/locales/ko-KR/translation.json b/src/lib/i18n/locales/ko-KR/translation.json index dc22345e24..523292663e 100644 --- a/src/lib/i18n/locales/ko-KR/translation.json +++ b/src/lib/i18n/locales/ko-KR/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "추출된 줄 {{COUNT}}개", "{{COUNT}} files": "{{COUNT}}개 파일", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "숨겨진 줄 {{COUNT}}개", "{{COUNT}} members": "{{COUNT}}명의 멤버", "{{count}} of {{total}} accessible_other": "", @@ -23,12 +25,15 @@ "{{count}} selected_one": "{{count}}개 선택됨", "{{count}} selected_other": "{{count}}개 선택됨", "{{COUNT}} Sources": "{{COUNT}}개의 소스", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} 단어", "{{COUNT}}d_time_ago": "{{COUNT}}일 전", "{{COUNT}}h_time_ago": "{{COUNT}}시간 전", "{{COUNT}}m_time_ago": "{{COUNT}}분 전", "{{COUNT}}w_time_ago": "{{COUNT}}주 전", "{{COUNT}}y_time_ago": "{{COUNT}}년 전", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}}일 {{LOCALIZED_TIME}}시", "{{model}} download has been canceled": "{{model}} 다운로드가 취소되었습니다.", "{{modelName}} profile image": "{{modelName}} 프로필 이미지", @@ -36,8 +41,10 @@ "{{user}}'s Chats": "{{user}}의 채팅", "{{webUIName}} Backend Required": "{{webUIName}} 백엔드가 필요합니다.", "*Prompt node ID(s) are required for image generation": "이미지 생성에는 프롬프트 노드 ID가 필요합니다.", + "1 group": "", "1 hour before": "1시간 전", "1 Source": "소스 1", + "1 user": "", "10 minutes before": "10분 전", "15 minutes before": "15분 전", "1m_time_ago": "1분 전", @@ -55,6 +62,7 @@ "Access Control": "접근 제어", "Access Grants": "접근 권한", "Access List": "접근 목록", + "Access prohibited": "", "Access updated": "접근 업데이트", "Accessible to all users": "모든 사용자가 이용할 수 있음", "Account": "계정", @@ -70,6 +78,7 @@ "Activity": "활동", "Add": "추가", "Add a model ID": "모델 ID 추가", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "모델의 기능에 대한 간단한 설명 추가", "Add a tag": "태그 추가", "Add a tag...": "태그 추가...", @@ -82,8 +91,10 @@ "Add Custom Prompt": "사용자 정의 프롬프트 추가", "Add description": "설명 추가", "Add Details": "디테일 추가", + "Add durable context for future chats": "", "Add Files": "파일 추가", "Add Image": "이미지 추가", + "Add Knowledge Connection": "", "Add location": "위치 추가", "Add Member": "멤버 추가", "Add Members": "멤버 추가", @@ -98,6 +109,7 @@ "Add to favorites": "즐겨찾기에 추가", "Add User": "사용자 추가", "Add User Group": "사용자 그룹 추가", + "Add webhook": "", "Add webpage": "웹페이지 추가", "Add your Open Terminal URL and API key in Settings → Integrations.": "설정 → 통합에서 Open Terminal URL과 API 키를 추가하세요.", "Additional Config": "추가 설정", @@ -110,7 +122,9 @@ "Admin": "관리자", "Admin Contact Email": "관리자 이메일", "Admin Panel": "관리자 패널", + "Admin Roles": "", "Admin Settings": "관리자 설정", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "관리자는 항상 모든 도구에 접근할 수 있지만, 사용자는 워크스페이스에서 모델마다 도구를 할당받아야 합니다.", "Advanced": "고급", "Advanced Parameters": "고급 매개변수", @@ -121,16 +135,21 @@ "All": "전체", "All chats have been unarchived.": "모든 채팅이 보관 해제되었습니다.", "All day": "하루 종일", + "All events": "", "All models are now hidden": "모든 모델이 이제 숨김 처리되었습니다", "All models are now visible": "모든 모델이 이제 표시됩니다", "All models deleted successfully": "성공적으로 모든 모델이 삭제되었습니다", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "전체 기간", "All Users": "모든 사용자", + "All users and system events": "", "Allow Call": "음성 통화 허용", "Allow Chat Controls": "채팅 제어 허용", "Allow Chat Delete": "채팅 삭제 허용", "Allow Chat Edit": "채팅 수정 허용", "Allow Chat Export": "채팅 내보내기 허용", + "Allow Chat Import": "", "Allow Chat Params": "채팅 매개변수 허용", "Allow Chat Share": "채팅 공유 허용", "Allow Chat System Prompt": "채팅 시스템 프롬프트 허용", @@ -150,9 +169,11 @@ "Allow User Location": "사용자 위치 활용 허용", "Allow Voice Interruption in Call": "음성 기능에서 음성 방해 허용", "Allow Web Upload": "웹 업로드 허용", + "Allowed Domains": "", "Allowed Endpoints": "허용 엔드포인트", "Allowed File Extensions": "허용 파일 확장자", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "업로드할 수 있는 파일 확장자. 여러 확장자를 구분하기 위해 쉼표로 구분합니다. 모든 파일 유형을 허용하려면 비워두세요.", + "Allowed Roles": "", "Already have an account?": "이미 계정이 있으신가요?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p의 대안으로, 품질과 다양성 간의 균형을 보장하는 것을 목표로 합니다. 매개변수 p는 가장 가능성이 높은 토큰의 확률 대비 고려될 토큰의 최소 확률을 나타냅니다. 예를 들어, p=0.05이고 가장 가능성이 높은 토큰의 확률이 0.9인 경우, 값이 0.045보다 작은 로짓은 필터링됩니다.", "Always": "항상", @@ -171,6 +192,7 @@ "API Base URL": "API 기본 URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker 서비스의 API URL. 기본값: https://www.datalab.to/api/v1/marker", "API Key": "API 키", + "API Key / Token": "", "API Key created.": "API 키가 생성되었습니다.", "API Key Endpoint Restrictions": "API 키 엔드포인트 제한", "API keys": "API 키", @@ -200,13 +222,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "정말 이 메모리를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.", "Are you sure you want to delete this message?": "정말 이 메시지를 삭제하시겠습니까?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "정말 이 버전을 삭제하시겠습니까? 하위 버전은 이 버전의 상위 버전에 다시 연결됩니다.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "정말 이 항목을 삭제하시겠습니까?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "정말 보관된 모든 채팅을 보관 해제하시겠습니까?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena 모델", "Artifacts": "아티팩트", "Asc": "오름차순", "Ask": "질문", "Ask a question": "질문하기", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "어시스턴트", "Async Embedding Processing": "비동기 임베딩 처리", "At time of event": "이벤트 발생 시", @@ -221,14 +248,20 @@ "Audio": "오디오", "August": "8월", "Auth": "인증", + "Auth Mode": "", + "Auth required": "", "Authenticate": "인증하다", "Authentication": "인증", "Auto": "자동", "Auto (Random)": "자동 (랜덤)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "응답을 클립보드에 자동 복사", - "Auto-playback response": "응답 자동 재생", + "Auto-Create Groups": "", + "Auto-Playback Response": "응답 자동 재생", "Autocomplete Generation": "자동완성 생성", "Autocomplete Generation Input Max Length": "자동완성 생성 입력 최대 길이", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Automatic1111 API 인증 문자", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 기본 URL", @@ -246,6 +279,7 @@ "Available Skills": "", "Available Tools": "사용 가능한 도구", "available users": "사용 가능 사용자", + "Available variables": "", "available!": "사용 가능!", "Away": "자리 비움", "Awful": "형편없음", @@ -256,16 +290,17 @@ "Bad Response": "잘못된 응답", "Banners": "배너", "Base Model (From)": "기본 모델(시작)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "기본 모델 목록 캐시는 시작 시 또는 설정 저장 시에만 기본 모델을 불러와 접근 속도를 높여줍니다. 이는 더 빠르지만, 최근 기본 모델 변경 사항이 반영되지 않을 수 있습니다.", "Bearer": "보유자", "before": "이전", "Being lazy": "게으름 피우기", - "Beta": "베타", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 엔드포인트", "Bing Search V7 Subscription Key": "Bing Search V7 구독 키", "Bio": "소개", "Birth Date": "생년월일", + "Blocked Groups": "", "BM25 Weight": "BM25 가중치", "Bocha Search API Key": "Bocha Search API 키", "Bold": "굵게", @@ -322,7 +357,7 @@ "Chat Completions": "채팅 완성", "Chat Conversation": "채팅 대화", "Chat deleted.": "", - "Chat direction": "채팅 방향", + "Chat Direction": "채팅 방향", "Chat exported successfully": "채팅 내보내기 성공", "Chat History": "채팅 기록", "Chat ID": "채팅 ID", @@ -394,6 +429,7 @@ "Collaboration channel where people join as members": "사람들이 멤버로 참여하는 협업 채널", "Collapse": "접기", "Collection": "컬렉션", + "Collection Field": "", "Collections": "컬렉션", "Color": "색상", "ComfyUI": "ComfyUI", @@ -403,12 +439,14 @@ "ComfyUI Workflow": "ComfyUI 워크플로", "ComfyUI Workflow Nodes": "ComfyUI 워크플로 노드", "Comma separated Node Ids (e.g. 1 or 1,2)": "쉼표로 구분된 노드 아이디 (예: 1 또는 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "명령", "Command": "명령", "Comment": "주석", "Commit Message": "커밋 메시지", "Community Reviews": "커뮤니티 리뷰", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "완성됨", "Compress Images in Channels": "채널에 이미지들 압축하기", @@ -429,6 +467,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Open Terminal 인스턴스에 연결합니다. 모든 사용자는 이 서버를 통해 파일 탐색과 터미널 도구를 사용할 수 있습니다.", "Connect to your own OpenAI compatible API endpoints.": "OpenAI 호환 API 엔드포인트에 연결합니다.", "Connect to your own OpenAPI compatible external tool servers.": "OpenAPI 호환 외부 도구 서버에 연결합니다.", + "Connected": "", "Connected ({{type}})": "{{type}}에 연결됨", "Connection failed": "연결 실패", "Connection lost. Reconnecting...": "연결이 끊겼습니다. 재연결 중...", @@ -441,8 +480,16 @@ "Contact Admin for WebUI Access": "WebUI 접속을 위해서는 관리자에게 연락에 연락하십시오", "Content": "내용", "Content Extraction Engine": "콘텐츠 추출 엔진", + "Content Field": "", "Content lengths (character counts only)": "콘텐츠 길이(문자 수만)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "응답 이어 받기", "Continue with {{provider}}": "{{provider}}로 계속", "Continue with Email": "이메일로 계속", @@ -490,6 +537,7 @@ "Create new secret key": "새로운 비밀 키 생성", "Create note": "노트 생성", "Create Note": "노트 생성", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "반복적으로 자동으로 실행되는 예약 프롬프트를 생성합니다.", "Create your first note by clicking on the plus button below.": "아래의 플러스 버튼을 클릭하여 첫 번째 노트를 생성하세요.", "Created at": "생성일", @@ -507,6 +555,7 @@ "Custom Gender": "사용자 정의 성별", "Custom Parameter Name": "사용자 정의 매개변수 이름", "Custom Parameter Value": "사용자 정의 매개변수 값", + "Custom range": "", "Daily": "매일", "Daily Messages": "일일 메시지", "Danger Zone": "위험 기능", @@ -529,7 +578,6 @@ "Default Features": "기본 기능", "Default Filters": "기본 필터", "Default Group": "기본 그룹", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "기본 모드는 실행 전에 도구를 한 번 호출하여 더 다양한 모델에서 작동합니다. 기본 모드는 모델에 내장된 도구 호출 기능을 활용하지만, 모델이 이 기능을 본질적으로 지원해야 합니다.", "Default Model": "기본 모델", "Default model updated": "기본 모델이 업데이트되었습니다.", "Default permissions": "기본 권한", @@ -539,6 +587,7 @@ "Default to ALL": "기본값: 전체", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "집중적이고 관련성 있는 콘텐츠 추출을 위해 세분화된 검색을 기본으로 하며, 대부분의 경우에 권장됩니다.", "Default User Role": "기본 사용자 역할", + "Default webhook": "", "Defaults": "기본값", "Delete": "삭제", "Delete {{name}}": "{{name}} 삭제", @@ -599,6 +648,8 @@ "Disable Code Interpreter": "코드 인터프리터 비활성화", "Disable Image Extraction": "이미지 추출 비활성화", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF에서 이미지 추출을 비활성화합니다. Use LLM이 활성화된 경우 이미지는 자동으로 캡션이 달립니다. 기본값은 False입니다.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "제한됨", "Disconnect OAuth": "", "Discover a function": "함수 검색", @@ -613,10 +664,10 @@ "Discover, download, and explore model presets": "모델 사전 설정 검색, 다운로드 및 탐색", "Discussion channel where access is based on groups and permissions": "그룹과 권한을 기반으로 액세스하는 토론 채널", "Display": "표시", - "Display chat title in tab": "탭에 채팅 목록 표시", + "Display Chat Title in Tab": "탭에 채팅 목록 표시", "Display Emoji in Call": "음성기능에서 이모지 표시", "Display Multi-model Responses in Tabs": "탭에 여러 모델 응답 표시", - "Display the username instead of You in the Chat": "채팅에서 '당신' 대신 사용자 이름 표시", + "Display the Username Instead of You in the Chat": "채팅에서 '당신' 대신 사용자 이름 표시", "Displays citations in the response": "응답에 인용 표시", "Displays status updates (e.g., web search progress) in the response": "응답에 상태 업데이트(예: 웹 검색 진행 상황)를 표시합니다", "Dive into knowledge": "지식 탐구", @@ -627,6 +678,7 @@ "Docling Parameters": "Docling 매개변수", "Docling Server URL required.": "Docling 서버 URL이 필요합니다.", "Document": "문서", + "Document ID Field": "", "Document Intelligence": "문서 인텔리전스", "Document Intelligence endpoint required.": "문서 인텔리전스 엔드포인트가 필요합니다.", "Document Intelligence Model": "문서 인텔리전스 모델", @@ -682,12 +734,14 @@ "Edit Default Permissions": "기본 권한 편집", "Edit Folder": "폴더 편집", "Edit Image": "이미지 편집", + "Edit Knowledge Connection": "", "Edit Last Message": "마지막 메시지 편집", "Edit Memory": "메모리 편집", "Edit Prompt": "프롬프트 편집", "Edit Terminal Connection": "터미널 연결 편집", "Edit User": "사용자 편집", "Edit User Group": "사용자 그룹 편집", + "Edit webhook": "", "Edit workflow.json content": "workflow.json 콘텐츠 편집", "edited": "수정됨", "Edited": "수정됨", @@ -696,6 +750,7 @@ "Eject model": "모델 추출", "ElevenLabs": "ElevenLabs", "Email": "이메일", + "Email Claim": "", "Embark on adventures": "모험을 떠나기", "Embedding": "임베딩", "Embedding Batch Size": "임베딩 배치 크기", @@ -704,6 +759,7 @@ "Embedding Model Engine": "임베딩 모델 엔진", "Emoji": "", "Emojis": "이모티콘", + "Empty": "", "Empty message": "빈 메시지", "Enable All": "모두 활성화", "Enable API Keys": "API 키 활성화", @@ -711,22 +767,27 @@ "Enable Code Execution": "코드 실행 활성화", "Enable Code Interpreter": "코드 인터프리터 활성화", "Enable Community Sharing": "커뮤니티 공유 활성화", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "모델 데이터가 RAM에서 스왑 아웃되는 것을 방지하기 위해 메모리 잠금(mlock)을 활성화합니다. 이 옵션은 모델의 작업 페이지 집합을 RAM에 잠가 디스크로 스왑 아웃되지 않도록 보장합니다. 이는 페이지 폴트를 피하고 빠른 데이터 액세스를 보장하여 성능을 유지하는 데 도움이 될 수 있습니다.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "모델 데이터를 로드하기 위해 메모리 매핑(mmap)을 활성화합니다. 이 옵션을 사용하면 시스템이 디스크 파일을 RAM에 있는 것처럼 처리하여 디스크 스토리지를 RAM의 확장으로 사용할 수 있습니다. 이는 더 빠른 데이터 액세스를 허용하여 모델 성능을 향상시킬 수 있습니다. 그러나 모든 시스템에서 올바르게 작동하지 않을 수 있으며 상당한 양의 디스크 공간을 소비할 수 있습니다.", "Enable Message Queue": "메시지 큐 활성화", "Enable Message Rating": "메시지 평가 활성화", "Enable Mirostat sampling for controlling perplexity.": "퍼플렉서티 제어를 위해 Mirostat 샘플링 활성화", "Enable New Sign Ups": "새 회원가입 활성화", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "모델이 사용하는 추론 태그를 활성화, 비활성화 또는 사용자 지정할 수 있습니다. \"활성화됨\"은 기본 태그를 사용하고, \"비활성화됨\"은 추론 태그를 끄며, \"사용자 지정\"은 직접 시작 및 종료 태그를 지정할 수 있습니다.", "Enabled": "활성화됨", "End Tag": "종료 태그", + "Endpoint": "", "Endpoint URL": "엔드포인트 URL", "Enforce Temporary Chat": "임시 채팅 강제 적용", "Enhance": "향상", "Enrich Hybrid Search Text": "하이브리드 검색 텍스트 강화", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV 파일에 이름, 이메일, 비밀번호, 역할 4개의 열이 순서대로 포함되어 있는지 확인하세요.", "Enter {{role}} message here": "여기에 {{role}} 메시지 입력", - "Enter a detail about yourself for your LLMs to recall": "자신에 대한 세부사항을 입력하여 LLM들이 기억할 수 있도록 하세요.", "Enter a title for the pending user info overlay. Leave empty for default.": "대기 중인 사용자 정보 오버레이의 제목을 입력하세요. 비워두면 기본값이 사용됩니다.", "Enter a watermark for the response. Leave empty for none.": "응답에 사용할 워터마크를 입력하세요. 비워두면 워터마크가 적용되지 않습니다.", "Enter additional headers in JSON format": "추가 헤더를 JSON 형식으로 입력하세요", @@ -743,6 +804,8 @@ "Enter Chunk Min Size Target": "청크 최소 크기 목표 입력", "Enter Chunk Overlap": "청크 중첩 입력", "Enter Chunk Size": "청크 크기 입력", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "쉼표로 구분된 \\\"토큰:편향_값\\\" 쌍 입력 (예: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "대기 중인 사용자 정보 오버레이에 들어갈 내용을 입력하세요. 비워두면 기본값이 사용됩니다.", "Enter coordinates (e.g. 51.505, -0.09)": "좌표 입력 (예: 51.505, -0.09)", @@ -780,8 +843,11 @@ "Enter Jupyter URL": "Jupyter URL 입력", "Enter Kagi Search API Key": "Kagi Search API 키 입력", "Enter Key Behavior": "키 동작 입력", + "Enter language": "", "Enter language codes": "언어 코드 입력", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "MinerU API 키 입력", "Enter Mistral API Base URL": "Mistral API Base URL 입력", "Enter Mistral API Key": "Mistral API 키 입력", @@ -801,6 +867,7 @@ "Enter prompt here.": "여기에 프롬프트를 입력하세요.", "Enter proxy URL (e.g. https://user:password@host:port)": "프록시 URL 입력(예: https://user:password@host:port)", "Enter reasoning effort": "추론 난이도", + "Enter Redirect URI": "", "Enter Score": "점수 입력", "Enter SearchApi API Key": "SearchApi API 키 입력", "Enter SearchApi Engine": "SearchApi 엔진 입력", @@ -810,6 +877,7 @@ "Enter SerpApi API Key": "SerpApi API 키 입력", "Enter SerpApi Engine": "SerpApi 엔진 입력", "Enter Serper API Key": "Serper API 키 입력", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API 키 입력", "Enter Serpstack API Key": "Serpstack API 키 입력", "Enter server host": "서버 호스트 입력", @@ -830,6 +898,8 @@ "Enter Tika Server URL": "Tika 서버 URL 입력", "Enter timeout in seconds": "시간 초과(초) 입력", "Enter to Send": "Enter로 보내기", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K 입력", "Enter Top K Reranker": "Top K 리랭커 입력", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL 입력(예: http://127.0.0.1:7860/)", @@ -870,11 +940,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "오류: ID가 '{{modelId}}'인 모델이 이미 존재합니다. 계속하려면 다른 ID를 선택하세요.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "오류: 모델 ID는 비워둘 수 없습니다. 계속하려면 유효한 ID를 입력하세요.", "Evaluations": "평가", + "Event": "", "Event created": "이벤트가 생성되었습니다.", "Event deleted": "이벤트가 삭제되었습니다.", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "이벤트 제목", "Event updated": "이벤트가 업데이트되었습니다.", + "Events": "", "Exa API Key": "Exa API 키", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "예: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "예: 전체", "Example: mail": "예: 메일", @@ -902,12 +976,18 @@ "Export Config": "설정 내보내기", "Export Models": "모델 내보내기", "Export Prompts": "프롬프트 내보내기", + "Export Skills": "", "Export to CSV": "CSV로 내보내기", "Export Tools": "도구 내보내기", "Export Users": "사용자 정보 내보내기", "External": "외부", + "External connection not found.": "", "External Document Loader URL required.": "외부 문서 로더 URL이 필요합니다.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "외부 작업 모델", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "외부 웹 로더 API 키", "External Web Loader URL": "외부 웹 로더 URL", "External Web Search API Key": "외부 웹 검색 API 키", @@ -925,6 +1005,7 @@ "Failed to create API Key.": "API 키 생성에 실패했습니다.", "Failed to delete calendar": "캘린더 삭제에 실패했습니다.", "Failed to delete note": "노트 삭제 실패", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "이미지 다운로드에 실패했습니다", "Failed to extract content from the file: {{error}}": "파일 내용 추출 실패: {{error}}", @@ -932,6 +1013,7 @@ "Failed to fetch models": "모델 조회 실패", "Failed to generate title": "제목 생성 실패", "Failed to import models": "모델 가져오기 실패", + "Failed to load chat": "", "Failed to load chat preview": "채팅 미리보기 로드 실패", "Failed to load DOCX file. Please try downloading it instead.": "DOCX 파일을 불러오지 못했습니다. 대신 다운로드해 보세요.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV 파일을 불러오지 못했습니다. 대신 다운로드해 보세요.", @@ -941,6 +1023,7 @@ "Failed to move chat": "채팅 이동 실패", "Failed to process URL: {{url}}": "URL 처리에 실패했습니다: {{url}}", "Failed to read clipboard contents": "클립보드 내용 가져오기를 실패하였습니다", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "멤버 삭제에 실패했습니다", "Failed to render diagram": "다이어그램을 표시할 수 없습니다", "Failed to render visualization": "시각화에 실패했습니다.", @@ -949,9 +1032,11 @@ "Failed to save models configuration": "모델 구성 저장 실패", "Failed to save policy: {{error}}": "정책 저장에 실패했습니다: {{error}}", "Failed to save terminal servers": "터미널 서버 저장에 실패했습니다", + "Failed to save webhook": "", "Failed to unshare chat.": "채팅 공유 해제에 실패했습니다.", "Failed to update settings": "설정 업데이트에 실패하였습니다", "Failed to update status": "상태 업데이트에 실패하였습니다", + "Failed to update webhook": "", "Failed to upload file.": "파일 업로드에 실패했습니다.", "Features": "기능", "Features Permissions": "기능 권한", @@ -984,6 +1069,8 @@ "File uploaded successfully": "파일이 성공적으로 업로드되었습니다", "Filename": "파일명", "Files": "파일", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "필터", "Filter is now globally disabled": "전반적으로 필터 비활성화됨", "Filter is now globally enabled": "전반적으로 필터 활성화됨", @@ -1006,6 +1093,7 @@ "Folder options": "폴더 옵션", "Folder updated successfully": "폴더가 성공적으로 업데이트되었습니다", "Folders": "폴더", + "Folders Sharing": "", "Follow up": "후속 질문", "Follow Up Generation": "후속 질문 생성", "Follow Up Generation Prompt": "후속 질문 생성 프롬프트", @@ -1036,6 +1124,7 @@ "Function is now globally enabled": "전반적으로 함수 활성화됨", "Function Name": "함수 이름", "Function Name Filter List": "함수 이름 필터 목록", + "Function starter": "", "Function updated successfully": "성공적으로 함수가 업데이트되었습니다", "Functions": "함수", "Functions allow arbitrary code execution.": "함수가 임의의 코드를 실행하도록 허용하였습니다", @@ -1068,7 +1157,10 @@ "Gravatar": "Gravatar", "Grid": "그리드", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "그룹 채널", + "Group Claim": "", "Group created successfully": "성공적으로 그룹을 생성했습니다", "Group deleted successfully": "성공적으로 그룹을 삭제했습니다", "Group Description": "그룹 설명", @@ -1080,6 +1172,7 @@ "H2": "제목 2", "H3": "제목 3", "Haptic Feedback": "햅틱 피드백", + "Header variables": "", "Headers": "헤더", "Headers must be a valid JSON object": "헤더는 유효한 JSON 객체여야 합니다", "Height": "높이", @@ -1110,6 +1203,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID는 \":\" 또는 \"|\" 문자를 포함할 수 없습니다", "ID copied to clipboard": "ID가 클립보드에 복사되었습닙다", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Idle 시간 초과", "iframe Sandbox Allow Forms": "iframe 샌드박스 허용 양식", "iframe Sandbox Allow Same Origin": "iframe 샌드박스에서 동일한 오리진 허용", @@ -1135,6 +1230,7 @@ "Import From Link": "링크에서 가져오기", "Import Models": "모델 가져오기", "Import Prompts": "프롬프트 가져오기", + "Import Skills": "", "Import successful": "가져오기 성공", "Import Tools": "도구 가져오기", "Important Update": "중요 업데이트", @@ -1192,7 +1288,6 @@ "Keep in Sidebar": "사이드바에 유지", "Key": "키", "Key is required": "키가 필요합니다", - "Keyboard shortcuts": "키보드 단축키", "Keyboard Shortcuts": "키보드 단축키", "Knowledge": "지식 기반", "Knowledge Access": "지식 기반 접근", @@ -1205,6 +1300,8 @@ "Knowledge Name": "지식 기반 이름", "Knowledge Public Sharing": "지식 기반 공개 공유", "Knowledge Sharing": "지식 기반 공유", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "성공적으로 지식 기반이 업데이트되었습니다", "Kokoro.js (Browser)": "Kokoro.js (브라우저)", "Kokoro.js Dtype": "Kokoro.js 데이터 유형", @@ -1221,7 +1318,6 @@ "Last ran": "마지막 실행", "Last reply": "마지막 답글", "LDAP": "LDAP", - "LDAP server updated": "LDAP 서버가 업데이트되었습니다", "Leaderboard": "리더보드", "Learn more": "자세히 알아보기", "Learn More": "자세히 알아보기", @@ -1243,6 +1339,7 @@ "Legacy": "레거시", "lexical": "어휘적", "License": "라이선스", + "Lifecycle JSON": "", "Lift List": "리스트 올리기", "Light": "라이트", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "동시 검색 쿼리 수를 제한합니다. 0은 무제한(기본값)입니다. 순차 실행하려면 1로 설정하세요(Brave 무료 요금제처럼 엄격한 속도 제한이 있는 API에 권장됩니다).", @@ -1266,6 +1363,7 @@ "Location access not allowed": "위치 접근이 허용되지 않습니다", "Lost": "패배", "Low": "낮음", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "OpenWebUI 커뮤니티에 의해 개발됨", "Make password visible in the user interface": "비밀번호 보이기", @@ -1282,6 +1380,7 @@ "Manage Pipelines": "파이프라인 관리", "Manage Tool Servers": "도구 서버 관리", "Manage your account information.": "계정 정보를 관리하세요.", + "Mapped Source": "", "March": "3월", "Markdown": "마크다운", "Markdown Header Text Splitter": "마크다운 헤더 텍스트 분할기", @@ -1309,6 +1408,7 @@ "Memory cleared successfully": "성공적으로 메모리가 정리되었습니다", "Memory deleted successfully": "성공적으로 메모리가 삭제되었습니다", "Memory updated successfully": "성공적으로 메모리가 업데이트되었습니다", + "Merge Accounts by Email": "", "Merge Responses": "응답들 결합하기", "Merged Response": "결합된 응답", "Message": "메시지", @@ -1319,9 +1419,12 @@ "messages": "메시지들", "Messages": "메시지", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "링크 생성 후에 보낸 메시지는 공유되지 않습니다. URL이 있는 사용자는 공유된 채팅을 볼 수 있습니다.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (개인용)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (회사/학교용)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "분", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "클라우드 API 모드를 사용하려면 MinerU API 키가 필요합니다.", @@ -1374,6 +1477,7 @@ "Models Sharing": "모델 공유", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API 키", + "Monday – Friday": "", "Month": "월", "Monthly": "월간", "More": "더보기", @@ -1391,6 +1495,7 @@ "Name your knowledge base": "지식 기반 이름을 지정하세요", "Name, prompt, and model are required": "이름, 프롬프트, 및 모델은 필수입니다", "Native": "네이티브", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "절대", "New": "새로 만들기", "New Automation": "새로운 자동", @@ -1420,6 +1525,7 @@ "Next run": "다음 실행", "No access grants. Private to you.": "접근 권한이 없습니다. 개인용입니다.", "No activity data": "활동 데이터가 없습니다", + "No additional headers are sent unless configured.": "", "No authentication": "권한 인증이 없습니다", "No automations found": "자동화된 항목을 찾을 수 없습니다.", "No chats found": "채팅을 찾을 수 없습니다", @@ -1432,8 +1538,10 @@ "No data": "데이터가 없습니다", "No data found": "데이터를 찾을 수 없습니다", "No distance available": "거리 불가능", + "No event webhooks configured.": "", "No execution logs available yet": "아직 실행 로그가 없습니다", "No expiration can pose security risks.": "만료 기한이 없으면 보안 위험이 발생할 수 있습니다.", + "No external knowledge sources configured.": "", "No feedback found": "피드백을 찾을 수 없습니다", "No file selected": "파일이 선택되지 않았습니다", "No files found": "파일을 찾을 수 없습니다", @@ -1461,6 +1569,7 @@ "No output items": "", "No pinned messages": "고정된 메시지가 없습니다", "No prompts found": "프롬프트를 찾을 수 없습니다", + "No Repeat": "", "No results": "결과가 없습니다", "No results found": "결과를 찾을 수 없습니다", "No search query generated": "검색어가 생성되지 않았습니다", @@ -1480,6 +1589,7 @@ "No webhooks yet": "webhook이 아직 없습니다", "Node Ids": "노드 ID", "None": "없음", + "Not configured": "", "Not factually correct": "사실상 맞지 않습니다", "Not helpful": "도움이 되지않습니다", "Not Registered": "등록되지 않았습니다", @@ -1495,20 +1605,25 @@ "Notifications": "알림", "November": "11월", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Static)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "10월", "Off": "끄기", "Okay, Let's Go!": "좋아요, 시작합시다!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED 다크", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API 세팅이 업데이트 되었습니다.", "Ollama Cloud API Key": "Ollama Cloud API Key", "Ollama Version": "Ollama 버전", + "Omit": "", "On": "켜기", "Once": "Once", "OneDrive": "OneDrive", @@ -1579,6 +1694,7 @@ "Password": "비밀번호", "Passwords do not match.": "비밀번호가 일치하지 않습니다.", "Paste Large Text as File": "큰 텍스트를 파일로 붙여넣기", + "Path": "", "Path copied": "경로가 복사되었습니다.", "Paused": "일시정지됨", "PDF document (.pdf)": "PDF 문서(.pdf)", @@ -1587,18 +1703,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "보류 중", "Pending": "보류", + "Pending Accounts": "", "Pending User Overlay Content": "대기 중인 사용자 오버레이 내용", "Pending User Overlay Title": "대기 중인 사용자 오버레이 제목", "Permission denied when accessing media devices": "미디어 장치 접근 권한이 거부되었습니다.", "Permission denied when accessing microphone": "마이크 접근 권한이 거부되었습니다.", "Permission denied when accessing microphone: {{error}}": "마이크 접근 권한이 거부되었습니다: {{error}}", "Permissions": "권한", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API 키", "Perplexity Model": "Perplexity 모델", "Perplexity Search API URL": "Perplexity 검색 API URL", "Perplexity Search Context Usage": "Perplexity 검색 컨텍스트 사용", "Persistent": "지속적", "Personalization": "개인화", + "Picture Claim": "", "Pin": "고정", "Pin to Sidebar": "사이드바에 고정", "Pinned": "고정됨", @@ -1631,13 +1750,13 @@ "Please fill in all fields.": "모두 빈칸없이 채워주세요", "Please register the OAuth client": "OAuth clith를 등록해주세요", "Please save the connection to persist the OAuth client information and do not change the ID": "OAuth 클라이언트 정보를 저장하려면 연결을 저장하고 ID를 변경하지 마세요.", - "Please select a model first.": "먼저 모델을 선택하세요.", "Please select a model.": "모델을 선택하세요.", "Please select a reason": "이유를 선택해주세요", "Please select a valid JSON file": "올바른 Json 파일을 선택해 주세요", "Please select at least one user for Direct Message channel.": "1:1 메시지 채널에 참여할 사용자를 최소 한 명 선택해주세요.", "Please wait until all files are uploaded.": "모든 파일이 업로드될 때까지 기다려 주세요.", "Policy ID": "정책 ID", + "Policy ID is required": "", "Port": "포트", "Ports": "포트", "Positive attitude": "긍정적인 자세", @@ -1667,6 +1786,8 @@ "Prompts Public Sharing": "프롬프트 공개 공유", "Prompts Sharing": "프롬프트 공유", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "공개", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com에서 \"{{searchValue}}\" 가져오기", "Pull a model from Ollama.com": "Ollama.com에서 모델 가져오기(pull)", @@ -1684,21 +1805,28 @@ "Read": "읽기", "Read Aloud": "읽어주기", "Read more →": "더 읽기 →", + "Read only": "", "Read Only": "읽기 전용", "Read-Only Access": "읽기 전용 접근", "Reason": "근거", "Reasoning Effort": "추론 난이도", "Reasoning Tags": "추론 태그", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "최근 사용", "Reconnected": "재연결됨", "Record": "녹음", "Record voice": "음성 녹음", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI 커뮤니티로 리디렉션 중", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "넌센스를 생성할 확률을 줄입니다. 값이 높을수록(예: 100) 더 다양한 답변을 제공하는 반면, 값이 낮을수록(예: 10) 더 보수적입니다.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "스스로를 \"사용자\" 라고 지칭하세요. (예: \"사용자는 영어를 배우고 있습니다\")", "Reference Chats": "채팅 참조", "Refresh": "새로 고침", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "허용되지 않았지만 허용되어야 합니다.", "Regenerate": "재생성", "Regenerate Menu": "메뉴 재생성", @@ -1731,19 +1859,26 @@ "Render Markdown in Previews": "미리보기에서 마크다운 렌더링", "Render Markdown in User Messages": "", "Reorder Models": "모델 재정렬", + "Repeat": "", "Repeats": "반복", "Reply": "답장", "Reply in Thread": "스레드로 답장하기", "Reply to thread...": "스레드로 답장하기...", "Replying to {{NAME}}": "{{NAME}}에게 답장하는 중", + "Require users to confirm before using Web Search.": "", "required": "필수", "Reranking Batch Size": "리랭킹 배치 사이즈", "Reranking Engine": "Reranking 엔진", "Reranking Model": "Reranking 모델", + "Research Knowledge": "", "Reset": "초기화", "Reset All Models": "모든 모델 초기화", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "이미지 초기화", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "업로드 디렉토리 초기화", "Reset Vector Storage/Knowledge": "벡터 저장 공간/지식 기반 초기화", "Reset view": "보기 초기화", @@ -1763,6 +1898,7 @@ "Retrieved 1 source": "검색된 source 1개", "Rich Text Input for Chat": "다양한 텍스트 서식 사용", "Role": "역할", + "Roles Claim": "", "RTL": "RTL", "Run": "실행", "Run All": "모두 실행", @@ -1781,10 +1917,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "브라우저의 저장소에 채팅 로그를 직접 저장하는 것은 더 이상 지원되지 않습니다. 아래 버튼을 클릭하여 채팅 로그를 다운로드하고 삭제하세요. 걱정 마세요. 백엔드를 통해 채팅 로그를 쉽게 다시 가져올 수 있습니다.", "Schedule": "일정", "Scheduled time must be in the future": "예약 시간은 미래여야 합니다", + "Scopes": "", "Scroll On Branch Change": "브랜치 변경 시 스크롤", "Scroll to Top": "", "Search": "검색", "Search a model": "모델 검색", + "Search actions": "", "Search all emojis": "모든 이모지 검색", "Search and manage user memories": "사용자 기억 검색 및 관리", "Search and view user chat history": "사용자 채팅 기록 검색 및 보기", @@ -1794,6 +1932,7 @@ "Search Chats": "채팅 검색", "Search Collection": "컬렉션 검색", "Search Files": "파일 검색", + "Search filters": "", "Search Filters": "필터 검색", "search for archived chats": "보관된 채팅 검색", "search for folders": "폴더 검색", @@ -1808,13 +1947,16 @@ "Search Models": "모델 검색", "Search Notes": "노트 검색", "Search options": "검색 옵션", + "Search or add pattern": "", "Search Prompts": "프롬프트 검색", "Search Result Count": "검색 결과 수", + "Search skills": "", "Search Skills": "스킬 검색", - "Search skills...": "", "Search the internet": "인터넷 검색", "Search the web and fetch URLs": "웹에서 검색하고 URL 가져오기", + "Search tools": "", "Search Tools": "검색 도구", + "Search users or groups": "", "Search, view, and manage user notes": "사용자 노트 검색, 보기, 및 관리", "SearchApi API Key": "SearchApi API 키", "SearchApi Engine": "SearchApi 엔진", @@ -1830,7 +1972,6 @@ "Seed": "시드", "Select": "선택", "Select {{modelName}} model": "{{modelName}} 모델 선택", - "Select a base model": "기본 모델 선택", "Select a base model (e.g. llama3, gpt-4o)": "기본 모델 선택 (예: llama3, gpt-4o)", "Select a conversation to preview": "대화를 선택하여 미리 보기", "Select a engine": "엔진 선택", @@ -1868,18 +2009,25 @@ "semantic": "의미적", "Send": "보내기", "Send a Message": "메시지 보내기", + "Send events for": "", "Send message": "메시지 보내기", "Send now": "지금 보내기", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "'stream_options: { include_usage: true }' 요청 보내기 \n지원되는 제공자가 토큰 사용 정보를 응답할 예정입니다", "September": "9월", "SerpApi API Key": "SerpApi API 키", "SerpApi Engine": "SerpApi 엔진", "Serper API Key": "Serper API 키", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API 키", "Serpstack API Key": "Serpstack API 키", "Server connection failed": "서버 연결 실패", "Server connection verified": "서버 연결 확인됨", + "Service Account": "", "Session": "세션", + "Session expired. Please sign in again.": "", "Set as default": "기본값으로 설정", "Set as Production": "프로덕션으로 설정", "Set embedding model": "임베딩 모델 설정", @@ -1907,15 +2055,17 @@ "Share link copied to clipboard.": "공유 링크가 클립보드에 복사되었습니다.", "Share to Open WebUI Community": "OpenWebUI 커뮤니티에 공유", "Share your background and interests": "당신의 배경과 관심사를 공유하세요", + "Shared": "", "Shared Chats": "공유된 채팅", "Shared with you": "당신과 공유됨", "Sharing Permissions": "권한 공유", "Show": "보기", - "Show \"What's New\" modal on login": "로그인시 \"새로운 기능\" 모달 보기", + "Show \"What's New\" Modal on Login": "로그인시 \"새로운 기능\" 모달 보기", "Show Admin Details in Account Pending Overlay": "사용자용 계정 보류 설명창에, 관리자 상세 정보 노출", "Show All": "모두 보기", "Show all ({{COUNT}} characters)": "모든 ({{COUNT}} 문자) 보기", "Show Files": "파일 보기", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "서식 툴바 표시", "Show image preview": "이미지 미리보기", "Show Model": "모델 보기", @@ -1959,6 +2109,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "출처", + "Specific users or groups": "", "Speech Playback Speed": "음성 재생 속도", "Speech recognition error: {{error}}": "음성 인식 오류: {{error}}", "Speech-to-Text": "음성-텍스트 변환", @@ -1995,6 +2146,7 @@ "STT Settings": "STT 설정", "Stylized PDF Export": "서식이 적용된 PDF 내보내기", "Su_day_of_week": "Su_day_of_week", + "Sub Claim": "", "Submit question": "질문 제출", "Submit suggestion": "제안 제출", "Subtitle": "부제목", @@ -2019,8 +2171,10 @@ "Syncing...": "동기화 중...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "마지막 동기화 타임스탬프 이후 업데이트된 채팅만 동기화합니다. 모든 채팅을 다시 동기화하려면 비활성화하세요.", "System": "시스템", + "System events only": "", "System Instructions": "시스템 지침", "System Prompt": "시스템 프롬프트", + "Table": "", "Tag": "태그", "Tags": "태그", "Tags Generation": "태그 생성", @@ -2041,6 +2195,12 @@ "Temporary Chat by Default": "임시 채팅을 기본값으로", "Terminal": "터미널", "Terminal servers saved": "터미널 서버 저장됨", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "텍스트 나누기", "Text-to-Speech": "텍스트-음성 변환", "Text-to-Speech Engine": "텍스트-음성 변환 엔진", @@ -2056,7 +2216,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "입력 오디오의 언어입니다. ISO-639-1 형식(예: en)으로 입력 언어를 지정하면 정확도와 지연 시간이 향상됩니다. 비워두면 자동으로 언어를 감지합니다.", "The LDAP attribute that maps to the mail that users use to sign in.": "사용자가 로그인하는 데 사용하는 메일에 매핑되는 LDAP 속성입니다.", "The LDAP attribute that maps to the username that users use to sign in.": "사용자가 로그인할 때 사용하는 사용자 이름에 매핑되는 LDAP 속성입니다.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "리더보드는 현재 베타 버전이며, 알고리즘 개선에 따라 평가 방식이 변경될 수 있습니다.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "최대 파일 크기(MB). 만약 파일 크기가 한도를 초과할 시, 파일은 업로드되지 않습니다", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "하나의 채팅에서는 사용가능한 최대 파일 수가 있습니다. 만약 파일 수가 한도를 초과할 시, 파일은 업로드되지 않습니다.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "텍스트의 출력 형식입니다. 'json', 'markdown', 또는 'html'이 될 수 있습니다. 기본값은 'markdown'입니다.", @@ -2078,6 +2237,7 @@ "This folder is empty": "이 폴더는 비어 있습니다.", "This is a default user permission and will remain enabled.": "이것은 기본 사용자 권한이며 계속 활성화됩니다.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "이것은 실험적 기능으로, 예상대로 작동하지 않을 수 있으며 언제든지 변경될 수 있습니다.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "이 모델은 공개적으로 사용할 수 없습니다. 다른 모델을 선택해주세요.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "이 옵션은 요청 처리 후 모델이 메모리에 유지하는 시간을 제어합니다. (기본값: 5분)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "이 옵션은 컨텍스트를 새로 고칠 때 보존되는 토큰의 수를 제어합니다. 예를 들어 2로 설정하면 대화 컨텍스트의 마지막 2개 토큰이 유지됩니다. 컨텍스트를 보존하면 대화의 연속성을 유지하는 데 도움이 될 수 있지만 새로운 주제에 대한 응답 능력이 감소할 수 있습니다.", @@ -2118,7 +2278,7 @@ "To learn more about available endpoints, visit our documentation.": "사용 가능한 엔드포인트에 대해 자세히 알아보려면 문서를 방문하세요.", "To select skills here, add them to the \"Skills\" workspace first.": "여기서 스킬을 선택하려면, \"스킬\" 워크스페이스에 먼저 추가하세요.", "To select toolkits here, add them to the \"Tools\" workspace first.": "여기서 도구를 선택하려면, \"도구\" 워크스페이스에 먼저 추가하세요.", - "Toast notifications for new updates": "새 업데이트 알림", + "Toast Notifications for New Updates": "새 업데이트 알림", "Today": "오늘", "Today at": "오늘은", "Today at {{LOCALIZED_TIME}}": "오늘 {{LOCALIZED_TIME}}", @@ -2132,6 +2292,8 @@ "Toggle whether current connection is active.": "현재 연결 활성화 여부 설정", "Token": "토큰", "Token counts are estimates and may not reflect actual API usage": "토큰 수는 추정치이며 실제 API 사용량을 반영하지 않을 수 있습니다.", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "토큰", "Tokens": "토큰", "Too verbose": "너무 장황합니다", @@ -2180,14 +2342,19 @@ "Unpin": "고정 해제", "Unpin from Sidebar": "사이드바 고정 해제", "Unravel secrets": "비밀 풀기", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "채팅 공유 해제", "Unsupported file type.": "지원하지 않는 파일 형식", "Untagged": "태그 해제", "Untitled": "제목 없음", "Update": "업데이트", "Update and Copy Link": "링크 업데이트 및 복사", + "Update Email": "", "Update for the latest features and improvements.": "이번 업데이트의 새로운 기능과 개선", + "Update Name": "", "Update password": "비밀번호 업데이트", + "Update Picture": "", "Update your status": "상태 업데이트", "Updated": "업데이트됨", "Updated at": "업데이트 일시", @@ -2214,13 +2381,18 @@ "Use": "사용", "Use '#' in the prompt input to load and include your knowledge.": "프롬프트 입력에서 '#'를 사용하여 지식 기반을 불러오고 포함하세요.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "더 정확한 결과를 얻으려면 /v1/audio/transcriptions 대신 /v1/chat/completions 엔드포인트를 사용해 보세요.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Chat Completions API 사용", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "그룹을 사용하여 사용자를 조직하고 권한을 할당하세요.", "Use LLM": "LLM 사용", "Use no proxy to fetch page contents.": "페이지 콘텐츠를 가져오려면 프록시를 사용하지 마세요.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "http_proxy 및 https_proxy 환경 변수로 지정된 프록시를 사용하여 페이지 콘텐츠를 가져옵니다.", + "Use Web Search?": "", "user": "사용자", "User": "사용자", + "User Access": "", "User Activity": "사용자 활동", "User Groups": "사용자 그룹", "User location successfully retrieved.": "성공적으로 사용자의 위치를 불러왔습니다", @@ -2230,6 +2402,7 @@ "User Status": "사용자 상태", "User Webhooks": "사용자 웹훅", "Username": "사용자 이름", + "Username Claim": "", "users": "사용자", "Users": "사용자", "Uses DefaultAzureCredential to authenticate": "DefaultAzureCredential을 사용하여 인증합니다", @@ -2243,6 +2416,7 @@ "Valves updated": "밸브 업데이트됨", "Valves updated successfully": "성공적으로 밸브가 업데이트되었습니다", "variable": "변수", + "Vector Field": "", "Verify Connection": "연결 확인", "Verify SSL Certificate": "SSL 인증서 확인", "Version": "버전", @@ -2272,11 +2446,14 @@ "Web API": "웹 API", "Web Loader Engine": "웹 로더 엔진", "Web Search": "웹 검색", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "웹 검색 엔진", "Web Search in Chat": "채팅에서 웹 검색", "Web Search Query Generation": "웹 검색 쿼리 생성", + "Webhook deleted": "", "Webhook Name": "웹훅 이름", - "Webhook URL": "웹훅 URL", + "Webhook saved": "", "Webhooks": "웹훅", "Webpage URLs": "웹페이지 URL", "WebUI Settings": "WebUI 설정", @@ -2319,6 +2496,7 @@ "Yandex Web Search API Key": "얀덱스 웹 검색 API 키", "Yandex Web Search config": "얀덱스 웹 검색 구성", "Yandex Web Search URL": "얀덱스 웹 검색 URL", + "Yearly": "", "Yesterday": "어제", "Yesterday at {{LOCALIZED_TIME}}": "어제 {{LOCALIZED_TIME}}", "You": "당신", @@ -2348,6 +2526,7 @@ "Your browser does not support the video tag.": "당신의 브라우저는 비디오 태그를 지원하지 않습니다.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "당신의 모든 기여는 곧바로 플러그인 개발자에게 갑니다; Open WebUI는 수수료를 받지 않습니다. 다만, 선택한 후원 플랫폼은 수수료를 가져갈 수 있습니다.", "Your message text or inputs": "당신의 메시지 텍스트 또는 입력값", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "당신의 사용 통계가 성공적으로 동기화되었습니다.", "YouTube": "유튜브", "Youtube Language": "Youtube 언어", diff --git a/src/lib/i18n/locales/lt-LT/translation.json b/src/lib/i18n/locales/lt-LT/translation.json index d27a340f34..2e551e8465 100644 --- a/src/lib/i18n/locales/lt-LT/translation.json +++ b/src/lib/i18n/locales/lt-LT/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "{{user}} susirašinėjimai", "{{webUIName}} Backend Required": "{{webUIName}} būtinas serveris", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -63,6 +79,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Paskyra", @@ -78,6 +95,7 @@ "Activity": "", "Add": "Pridėti", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Pridėti trumpą modelio aprašymą", "Add a tag": "Pridėti žymą", "Add a tag...": "", @@ -90,8 +108,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Pridėti failus", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -106,6 +126,7 @@ "Add to favorites": "", "Add User": "Pridėti naudotoją", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -118,7 +139,9 @@ "Admin": "Administratorius", "Admin Contact Email": "", "Admin Panel": "Administratorių panelė", + "Admin Roles": "", "Admin Settings": "Administratorių nustatymai", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratoriai visada turi visus įrankius. Naudotojai turi tuėti prieigą prie dokumentų per modelių nuostatas", "Advanced": "", "Advanced Parameters": "Pažengę nustatymai", @@ -129,16 +152,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -158,9 +186,11 @@ "Allow User Location": "Leisti naudotojo vietos matymą", "Allow Voice Interruption in Call": "Leisti pertraukimą skambučio metu", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Ar jau turite paskyrą?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -179,6 +209,7 @@ "API Base URL": "API basės nuoroda", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API raktas", + "API Key / Token": "", "API Key created.": "API raktas sukurtas", "API Key Endpoint Restrictions": "", "API keys": "API raktai", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -229,14 +265,20 @@ "Audio": "Audio įrašas", "August": "Rugpjūtis", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatiškai nukopijuoti atsakymą", - "Auto-playback response": "Automatinis atsakymo skaitymas", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatinis atsakymo skaitymas", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 bazės nuoroda", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "", "available users": "galimi naudotojai", + "Available variables": "", "available!": "prieinama!", "Away": "Išvykęs", "Awful": "", @@ -264,16 +307,17 @@ "Bad Response": "Neteisingas atsakymas", "Banners": "Baneriai", "Base Model (From)": "Bazinis modelis", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "prieš", "Being lazy": "Būvimas tingiu", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -330,7 +374,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Pokalbio linkmė", + "Chat Direction": "Pokalbio linkmė", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Kolekcija", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Command", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Susisiekite su administratoriumi dėl prieigos", "Content": "Turinys", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Tęsti atsakymą", "Continue with {{provider}}": "Tęsti su {{provider}}", "Continue with Email": "", @@ -501,6 +557,7 @@ "Create new secret key": "Sukurti naują slaptą raktą", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Sukurta", @@ -518,6 +575,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -540,7 +598,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Numatytasis modelis", "Default model updated": "Numatytasis modelis atnaujintas", "Default permissions": "", @@ -550,6 +607,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Numatytoji naudotojo rolė", + "Default webhook": "", "Defaults": "", "Delete": "ištrinti", "Delete {{name}}": "", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Išjungta", "Disconnect OAuth": "", "Discover a function": "Atrasti funkciją", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Atrasti ir parsisiųsti modelių konfigūracija", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Rodyti emoji pokalbiuose", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Rodyti naudotojo vardą vietoje žodžio Jūs pokalbyje", + "Display the Username Instead of You in the Chat": "Rodyti naudotojo vardą vietoje žodžio Jūs pokalbyje", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -638,6 +698,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokumentas", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -693,12 +754,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Koreguoti atminį", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Redaguoti naudotoją", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -707,6 +770,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "El. paštas", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "Embedding dydis", @@ -715,6 +779,7 @@ "Embedding Model Engine": "Embedding modelio variklis", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -722,22 +787,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Leisti dalinimąsi su bendruomene", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Aktyvuoti naujas registracijas", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Leisti", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Įsitikinkite, kad CSV failas turi 4 kolonas šiuo eiliškumu: Name, Email, Password, Role.", "Enter {{role}} message here": "Įveskite {{role}} žinutę čia", - "Enter a detail about yourself for your LLMs to recall": "Įveskite informaciją apie save jūsų modelio atminčiai", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Įveskite blokų persidengimą", "Enter Chunk Size": "Įveskite blokų dydį", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Įveskite kalbos kodus", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -812,6 +887,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Įveskite rezultatą", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Įveskite Serper API raktą", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Įveskite Serply API raktą", "Enter Serpstack API Key": "Įveskite Serpstack API raktą", "Enter server host": "", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Įveskite Tika serverio nuorodą", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Įveskite Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Įveskite nuorodą (pvz. http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -913,12 +996,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Nepavyko sukurti API rakto", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -943,6 +1033,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -952,6 +1043,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepavyko perskaityti kopijuoklės", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Nepavyko atnaujinti nustatymų", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -995,6 +1089,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Rinkmenos", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filtrai nėra leidžiami globaliai", "Filter is now globally enabled": "Filtrai globaliai leidžiami", @@ -1017,6 +1113,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Funkcijos leidžiamos", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funkcija atnaujinta sėkmingai", "Functions": "Funkcijos", "Functions allow arbitrary code execution.": "Funkcijos leidžia nekontroliuojamo kodo vykdymą", @@ -1079,7 +1177,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1091,6 +1192,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1121,6 +1223,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1146,6 +1250,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Svarbus atnaujinimas", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Klaviatūros trumpiniai", "Keyboard Shortcuts": "", "Knowledge": "Žinios", "Knowledge Access": "", @@ -1216,6 +1320,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1232,7 +1338,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1254,6 +1359,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Šviesus", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1277,6 +1383,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Sukurta OpenWebUI bendruomenės", "Make password visible in the user interface": "", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Tvarkyti procesus", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Kovas", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Atmintis ištrinta sėkmingai", "Memory deleted successfully": "Atmintis ištrinta sėkmingai", "Memory updated successfully": "Atmintis atnaujinta sėkmingai", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Sujungtas atsakymas", "Message": "", @@ -1330,9 +1439,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Žinutės, kurias siunčiate po nuorodos sukūrimo nebus matomos nuorodos turėtojams. Naudotojai su nuoroda matys žinutes iki nuorodos sukūrimo.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1385,6 +1497,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Daugiau", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1431,6 +1545,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1443,8 +1558,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nėra pasirinktų dokumentų", "No files found": "", @@ -1472,6 +1589,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Rezultatų nerasta", "No results found": "Rezultatų nerasta", "No search query generated": "Paieškos užklausa nesugeneruota", @@ -1491,6 +1609,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Nėra", + "Not configured": "", "Not factually correct": "Faktiškai netikslu", "Not helpful": "", "Not Registered": "", @@ -1506,20 +1625,25 @@ "Notifications": "Pranešimai", "November": "lapkritis", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "spalis", "Off": "Išjungta", "Okay, Let's Go!": "Gerai, važiuojam!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED tamsus", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Ollama versija", + "Omit": "", "On": "Aktyvuota", "Once": "", "OneDrive": "", @@ -1590,6 +1714,7 @@ "Password": "Slaptažodis", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokumentas (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "laukiama", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Leidimas atmestas bandant prisijungti prie medijos įrenginių", "Permission denied when accessing microphone": "Mikrofono leidimas atmestas", "Permission denied when accessing microphone: {{error}}": "Leidimas naudoti mikrofoną atmestas: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalizacija", + "Picture Claim": "", "Pin": "Smeigtukas", "Pin to Sidebar": "", "Pinned": "Įsmeigta", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Pozityvus elgesys", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Rasti \"{{searchValue}}\" iš Ollama.com", "Pull a model from Ollama.com": "Gauti modelį iš Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "", "Read Aloud": "Skaityti garsiai", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Įrašyti balsą", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Perkeliam Jus į OpenWebUI bendruomenę", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Vadinkite save Naudotoju (pvz. Naudotojas mokosi prancūzų kalbos)", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Atmesta kai neturėtų būti atmesta", "Regenerate": "Generuoti iš naujo", "Regenerate Menu": "", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Reranking modelis", + "Research Knowledge": "", "Reset": "Atkurti", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Atstatyti vaizdą", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Atkurti įkėlimų direktoiją", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Rolė", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Pokalbių saugojimas naršyklėje nebegalimas.", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Ieškoti", "Search a model": "Ieškoti modelio", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1810,6 +1960,7 @@ "Search Chats": "Ieškoti pokalbiuose", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1824,13 +1975,16 @@ "Search Models": "Ieškoti modelių", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Ieškoti užklausų", "Search Result Count": "Paieškos rezultatų skaičius", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Paieškos įrankiai", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1846,7 +2000,6 @@ "Seed": "Sėkla", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Pasirinkite bazinį modelį", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Pasirinkite variklį", @@ -1884,18 +2037,25 @@ "semantic": "", "Send": "Siųsti", "Send a Message": "Siųsti žinutę", + "Send events for": "", "Send message": "Siųsti žinutę", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "rugsėjis", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API raktas", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API raktas", "Serpstack API Key": "Serpstach API raktas", "Server connection failed": "", "Server connection verified": "Serverio sujungimas patvirtintas", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Nustatyti numatytąjį", "Set as Production": "", "Set embedding model": "", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Dalintis su OpenWebUI bendruomene", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Rodyti", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "Rodyti administratoriaus duomenis laukiant paskyros patvirtinimo", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Šaltinis", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Balso atpažinimo problema: {{error}}", "Speech-to-Text": "", @@ -2013,6 +2176,7 @@ "STT Settings": "STT nustatymai", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2037,8 +2201,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "", "System Prompt": "Sistemos užklausa", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "Balso sintezės modelis", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2096,6 +2267,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Tai eksperimentinė funkcija ir gali veikti nevisada.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Norėdami pasirinkti įrankius, pirmiausia pridėkite juos prie įrankių nuostatuose", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Šiandien", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2198,14 +2372,19 @@ "Unpin": "Atsemigti", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "Atnaujinti", "Update and Copy Link": "Atnaujinti ir kopijuoti nuorodą", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "Atnaujinti slaptažodį", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "Atnaujinta", @@ -2232,13 +2411,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "naudotojas", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Naudotojo vieta sėkmingai gauta", @@ -2248,6 +2432,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Naudotojai", "Uses DefaultAzureCredential to authenticate": "", @@ -2261,6 +2446,7 @@ "Valves updated": "Įeitys atnaujintos", "Valves updated successfully": "Įeitys atnaujintos sėkmingai", "variable": "kintamasis", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Versija", @@ -2290,11 +2476,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "Web paieška", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Web paieškos variklis", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook nuoroda", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI parametrai", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Vakar", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Jūs", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Jūsų finansinis prisidėjimas tiesiogiai keliaus modulio kūrėjui.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/lv-LV/translation.json b/src/lib/i18n/locales/lv-LV/translation.json index 48c0595bfe..422b2bdff6 100644 --- a/src/lib/i18n/locales/lv-LV/translation.json +++ b/src/lib/i18n/locales/lv-LV/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_zero": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_zero": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_zero": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} slēptās rindas", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_zero": "", @@ -28,12 +34,17 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} avoti", + "{{count}} users_zero": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} vārdi", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} plkst. {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} lejupielāde ir atcelta", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "{{user}} tērzēšanas", "{{webUIName}} Backend Required": "Nepieciešama {{webUIName}} aizmugursistēma", "*Prompt node ID(s) are required for image generation": "*Attēla ģenerēšanai nepieciešami uzvednes mezgla ID", + "1 group": "", "1 hour before": "", "1 Source": "1 avots", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "Piekļuves kontrole", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Pieejams visiem lietotājiem", "Account": "Konts", @@ -75,6 +89,7 @@ "Activity": "Aktivitāte", "Add": "Pievienot", "Add a model ID": "Pievienot modeļa ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Pievienojiet īsu aprakstu par to, ko šis modelis dara", "Add a tag": "Pievienot tagu", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Pievienot pielāgotu uzvedni", "Add description": "", "Add Details": "Pievienot detaļas", + "Add durable context for future chats": "", "Add Files": "Pievienot failus", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "Pievienot dalībnieku", "Add Members": "Pievienot dalībniekus", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Pievienot lietotāju", "Add User Group": "Pievienot lietotāju grupu", + "Add webhook": "", "Add webpage": "Pievienot tīmekļa lapu", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "Papildu konfigurācija", @@ -115,7 +133,9 @@ "Admin": "Administrators", "Admin Contact Email": "Administratora kontakt e-pasts", "Admin Panel": "Administratora panelis", + "Admin Roles": "", "Admin Settings": "Administratora iestatījumi", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratoriem vienmēr ir piekļuve visiem rīkiem; lietotājiem rīki jāpiešķir katram modelim darba vidē.", "Advanced": "", "Advanced Parameters": "Papildu parametri", @@ -126,16 +146,21 @@ "All": "Visi", "All chats have been unarchived.": "Visas tērzēšanas ir atarhivētas.", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Visi modeļi veiksmīgi dzēsti", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Atļaut zvanu", "Allow Chat Controls": "Atļaut tērzēšanas vadības", "Allow Chat Delete": "Atļaut tērzēšanas dzēšanu", "Allow Chat Edit": "Atļaut tērzēšanas rediģēšanu", "Allow Chat Export": "Atļaut tērzēšanas eksportēšanu", + "Allow Chat Import": "", "Allow Chat Params": "Atļaut tērzēšanas parametrus", "Allow Chat Share": "Atļaut tērzēšanas kopīgošanu", "Allow Chat System Prompt": "Atļaut tērzēšanas sistēmas uzvedni", @@ -155,9 +180,11 @@ "Allow User Location": "Atļaut lietotāja atrašanās vietu", "Allow Voice Interruption in Call": "Atļaut balss pārtraukšanu zvana laikā", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Atļautie galapunkti", "Allowed File Extensions": "Atļautie failu paplašinājumi", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Atļautie failu paplašinājumi augšupielādei. Atdaliet vairākus paplašinājumus ar komatiem. Atstājiet tukšu visiem failu tipiem.", + "Allowed Roles": "", "Already have an account?": "Jau ir konts?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatīva top_p, kuras mērķis ir nodrošināt kvalitātes un dažādības līdzsvaru. Parametrs p apzīmē minimālo varbūtību, lai tokens tiktu ņemts vērā, attiecībā pret visticamākā tokena varbūtību. Piemēram, ar p=0.05 un visticamākā tokena varbūtību 0.9, logiti ar vērtību mazāku par 0.045 tiek izfiltrēti.", "Always": "Vienmēr", @@ -176,6 +203,7 @@ "API Base URL": "API bāzes URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API bāzes URL Datalab Marker pakalpojumam. Noklusējums: https://www.datalab.to/api/v1/marker", "API Key": "API atslēga", + "API Key / Token": "", "API Key created.": "API atslēga izveidota.", "API Key Endpoint Restrictions": "API atslēgas galapunkta ierobežojumi", "API keys": "API atslēgas", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Vai tiešām vēlaties dzēst šo ziņojumu?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Vai tiešām vēlaties atarhivēt visas arhivētās tērzēšanas?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arēnas modeļi", "Artifacts": "Artefakti", "Asc": "Augoši", "Ask": "Jautāt", "Ask a question": "Uzdot jautājumu", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistents", "Async Embedding Processing": "Asinhronā iegulšanas apstrāde", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "Augusts", "Auth": "Autorizācija", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentificēties", "Authentication": "Autentifikācija", "Auto": "Automātiski", "Auto (Random)": "Automātiski (nejauši)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automātiski kopēt atbildi starpliktuvē", - "Auto-playback response": "Automātiski atskaņot atbildi", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automātiski atskaņot atbildi", "Autocomplete Generation": "Automātiskās pabeigšanas ģenerēšana", "Autocomplete Generation Input Max Length": "Automātiskās pabeigšanas ievades maksimālais garums", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API autorizācijas virkne", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 bāzes URL", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Pieejamie rīki", "available users": "pieejamie lietotāji", + "Available variables": "", "available!": "pieejams!", "Away": "Prom", "Awful": "Šausmīgi", @@ -261,16 +301,17 @@ "Bad Response": "Slikta atbilde", "Banners": "Baneri", "Base Model (From)": "Bāzes modelis (no)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Bāzes modeļu saraksta kešatmiņa paātrina piekļuvi, ielādējot bāzes modeļus tikai startējot vai saglabājot iestatījumus — ātrāk, bet var nerādīt nesenās bāzes modeļu izmaiņas.", "Bearer": "Bearer", "before": "pirms", "Being lazy": "Esmu slinks", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 galapunkts", "Bing Search V7 Subscription Key": "Bing Search V7 abonementa atslēga", "Bio": "Biogrāfija", "Birth Date": "Dzimšanas datums", + "Blocked Groups": "", "BM25 Weight": "BM25 svars", "Bocha Search API Key": "Bocha Search API atslēga", "Bold": "Treknraksts", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "Tērzēšanas saruna", "Chat deleted.": "", - "Chat direction": "Tērzēšanas virziens", + "Chat Direction": "Tērzēšanas virziens", "Chat exported successfully": "", "Chat History": "", "Chat ID": "Tērzēšanas ID", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Sadarbības kanāls, kurā cilvēki pievienojas kā dalībnieki", "Collapse": "Sakļaut", "Collection": "Kolekcija", + "Collection Field": "", "Collections": "Kolekcijas", "Color": "Krāsa", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "ComfyUI darbplūsma", "ComfyUI Workflow Nodes": "ComfyUI darbplūsmas mezgli", "Comma separated Node Ids (e.g. 1 or 1,2)": "Ar komatu atdalīti mezglu ID (piem., 1 vai 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Komanda", "Comment": "Komentārs", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Pabeigšanas", "Compress Images in Channels": "Saspiest attēlus kanālos", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Savienojieties ar saviem OpenAI saderīgajiem API galapunktiem.", "Connect to your own OpenAPI compatible external tool servers.": "Savienojieties ar saviem OpenAPI saderīgajiem ārējo rīku serveriem.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Savienojums neizdevās", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Sazinieties ar administratoru, lai piekļūtu WebUI", "Content": "Saturs", "Content Extraction Engine": "Satura ekstrakcijas dzinējs", + "Content Field": "", "Content lengths (character counts only)": "Satura garumi (tikai rakstzīmju skaits)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Turpināt atbildi", "Continue with {{provider}}": "Turpināt ar {{provider}}", "Continue with Email": "Turpināt ar e-pastu", @@ -497,6 +550,7 @@ "Create new secret key": "Izveidot jaunu slepeno atslēgu", "Create note": "Izveidot piezīmi", "Create Note": "Izveidot piezīmi", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Izveidojiet savu pirmo piezīmi, noklikšķinot uz pluszīmes pogas zemāk.", "Created at": "Izveidots", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "Pielāgota parametra nosaukums", "Custom Parameter Value": "Pielāgota parametra vērtība", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Bīstamā zona", @@ -536,7 +591,6 @@ "Default Features": "Noklusējuma funkcijas", "Default Filters": "Noklusējuma filtri", "Default Group": "Noklusējuma grupa", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Noklusējuma režīms darbojas ar plašāku modeļu klāstu, izsaucot rīkus vienu reizi pirms izpildes. Vietējais režīms izmanto modeļa iebūvētās rīku izsaukšanas iespējas, bet prasa, lai modelis dabiski atbalstītu šo funkciju.", "Default Model": "Noklusējuma modelis", "Default model updated": "Noklusējuma modelis atjaunināts", "Default permissions": "Noklusējuma atļaujas", @@ -546,6 +600,7 @@ "Default to ALL": "Noklusējums ir VISI", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Noklusējums ir segmentēta izgūšana fokusētai un atbilstošai satura ekstrakcijai, tas ir ieteicams vairumā gadījumu.", "Default User Role": "Noklusējuma lietotāja loma", + "Default webhook": "", "Defaults": "", "Delete": "Dzēst", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "Atspējot koda interpretatoru", "Disable Image Extraction": "Atspējot attēlu ekstrakciju", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Atspējot attēlu ekstrakciju no PDF. Ja ir iespējots Lietot LLM, attēliem automātiski tiks pievienoti paraksti. Noklusējums ir False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Atspējots", "Disconnect OAuth": "", "Discover a function": "Atklāt funkciju", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Atklājiet, lejupielādējiet un izpētiet modeļu iestatījumu kopas", "Discussion channel where access is based on groups and permissions": "Diskusiju kanāls, kur piekļuve balstās uz grupām un atļaujām", "Display": "Attēlojums", - "Display chat title in tab": "Rādīt tērzēšanas virsrakstu cilnē", + "Display Chat Title in Tab": "Rādīt tērzēšanas virsrakstu cilnē", "Display Emoji in Call": "Rādīt emocijzīmes zvana laikā", "Display Multi-model Responses in Tabs": "Rādīt vairāku modeļu atbildes cilnēs", - "Display the username instead of You in the Chat": "Rādīt lietotājvārdu nevis 'Jūs' tērzēšanā", + "Display the Username Instead of You in the Chat": "Rādīt lietotājvārdu nevis 'Jūs' tērzēšanā", "Displays citations in the response": "Rāda citātus atbildē", "Displays status updates (e.g., web search progress) in the response": "Rāda statusa atjauninājumus (piem., tīmekļa meklēšanas progresu) atbildē", "Dive into knowledge": "Ienirstiet zināšanās", @@ -634,6 +691,7 @@ "Docling Parameters": "Docling parametri", "Docling Server URL required.": "Nepieciešams Docling servera URL.", "Document": "Dokuments", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Nepieciešams Document Intelligence galapunkts.", "Document Intelligence Model": "Document Intelligence modelis", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Rediģēt noklusējuma atļaujas", "Edit Folder": "Rediģēt mapi", "Edit Image": "Rediģēt attēlu", + "Edit Knowledge Connection": "", "Edit Last Message": "Rediģēt pēdējo ziņojumu", "Edit Memory": "Rediģēt atmiņu", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Rediģēt lietotāju", "Edit User Group": "Rediģēt lietotāju grupu", + "Edit webhook": "", "Edit workflow.json content": "Rediģēt workflow.json saturu", "edited": "rediģēts", "Edited": "Rediģēts", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "E-pasts", + "Email Claim": "", "Embark on adventures": "Dodieties piedzīvojumos", "Embedding": "Iegulšana", "Embedding Batch Size": "Iegulšanas paketes izmērs", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Iegulšanas modeļa dzinējs", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "Iespējot API atslēgas", @@ -718,22 +780,27 @@ "Enable Code Execution": "Iespējot koda izpildi", "Enable Code Interpreter": "Iespējot koda interpretatoru", "Enable Community Sharing": "Iespējot kopienas kopīgošanu", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Iespējot atmiņas bloķēšanu (mlock), lai novērstu modeļa datu izņemšanu no RAM. Šī opcija bloķē modeļa darba lapu kopu RAM, nodrošinot, ka tās netiks izņemtas uz disku. Tas var palīdzēt uzturēt veiktspēju, izvairoties no lapu kļūdām un nodrošinot ātru datu piekļuvi.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Iespējot atmiņas kartēšanu (mmap), lai ielādētu modeļa datus. Šī opcija ļauj sistēmai izmantot diska krātuvi kā RAM paplašinājumu, apstrādājot diska failus tā, it kā tie būtu RAM. Tas var uzlabot modeļa veiktspēju, nodrošinot ātrāku datu piekļuvi. Tomēr tas var nedarboties pareizi ar visām sistēmām un var patērēt ievērojamu diska vietu.", "Enable Message Queue": "", "Enable Message Rating": "Iespējot ziņojumu vērtēšanu", "Enable Mirostat sampling for controlling perplexity.": "Iespējot Mirostat paraugu ņemšanu neizpratnes kontrolei.", "Enable New Sign Ups": "Iespējot jaunu reģistrāciju", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Iespējojiet, atspējojiet vai pielāgojiet modeļa izmantotos spriedumu tagus. \"Iespējots\" izmanto noklusējuma tagus, \"Atspējots\" izslēdz spriedumu tagus, un \"Pielāgots\" ļauj norādīt savus sākuma un beigu tagus.", "Enabled": "Iespējots", "End Tag": "Beigu tags", + "Endpoint": "", "Endpoint URL": "Galapunkta URL", "Enforce Temporary Chat": "Uzspiest pagaidu tērzēšanu", "Enhance": "Uzlabot", "Enrich Hybrid Search Text": "Bagātināt hibrīda meklēšanas tekstu", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Pārliecinieties, ka jūsu CSV failā ir 4 kolonnas šādā secībā: Vārds, E-pasts, Parole, Loma.", "Enter {{role}} message here": "Ievadiet {{role}} ziņojumu šeit", - "Enter a detail about yourself for your LLMs to recall": "Ievadiet detaļu par sevi, ko jūsu LLM atcerēsies", "Enter a title for the pending user info overlay. Leave empty for default.": "Ievadiet virsrakstu gaidošā lietotāja informācijas pārklājumam. Atstājiet tukšu noklusējumam.", "Enter a watermark for the response. Leave empty for none.": "Ievadiet ūdenszīmi atbildei. Atstājiet tukšu, ja nevajag.", "Enter additional headers in JSON format": "Ievadiet papildu galvenes JSON formātā", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Ievadiet fragmenta minimālā izmēra mērķi", "Enter Chunk Overlap": "Ievadiet fragmentu pārklāšanos", "Enter Chunk Size": "Ievadiet fragmenta izmēru", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Ievadiet ar komatu atdalītus \"tokens:novirzes_vērtība\" pārus (piemērs: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Ievadiet saturu gaidošā lietotāja informācijas pārklājumam. Atstājiet tukšu noklusējumam.", "Enter coordinates (e.g. 51.505, -0.09)": "Ievadiet koordinātas (piem., 51.505, -0.09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Ievadiet Jupyter URL", "Enter Kagi Search API Key": "Ievadiet Kagi Search API atslēgu", "Enter Key Behavior": "Ievadiet taustiņa uzvedību", + "Enter language": "", "Enter language codes": "Ievadiet valodu kodus", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Ievadiet MinerU API atslēgu", "Enter Mistral API Base URL": "Ievadiet Mistral API bāzes URL", "Enter Mistral API Key": "Ievadiet Mistral API atslēgu", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Ievadiet starpniekservera URL (piem., https://lietotājs:parole@host:ports)", "Enter reasoning effort": "Ievadiet spriedumu pūles", + "Enter Redirect URI": "", "Enter Score": "Ievadiet rezultātu", "Enter SearchApi API Key": "Ievadiet SearchApi API atslēgu", "Enter SearchApi Engine": "Ievadiet SearchApi dzinēju", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Ievadiet SerpApi API atslēgu", "Enter SerpApi Engine": "Ievadiet SerpApi dzinēju", "Enter Serper API Key": "Ievadiet Serper API atslēgu", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Ievadiet Serply API atslēgu", "Enter Serpstack API Key": "Ievadiet Serpstack API atslēgu", "Enter server host": "Ievadiet servera hostu", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Ievadiet Tika servera URL", "Enter timeout in seconds": "Ievadiet taimautu sekundēs", "Enter to Send": "Enter, lai nosūtītu", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Ievadiet Top K", "Enter Top K Reranker": "Ievadiet Top K pārkārtotāju", "Enter URL (e.g. http://127.0.0.1:7860/)": "Ievadiet URL (piem., http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Kļūda: Modelis ar ID '{{modelId}}' jau eksistē. Lūdzu, izvēlieties citu ID, lai turpinātu.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Kļūda: Modeļa ID nevar būt tukšs. Lūdzu, ievadiet derīgu ID, lai turpinātu.", "Evaluations": "Novērtējumi", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API atslēga", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Piemērs: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Piemērs: ALL", "Example: mail": "Piemērs: mail", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "Eksportēt modeļus", "Export Prompts": "Eksportēt uzvednes", + "Export Skills": "", "Export to CSV": "Eksportēt uz CSV", "Export Tools": "Eksportēt rīkus", "Export Users": "Eksportēt lietotājus", "External": "Ārējs", + "External connection not found.": "", "External Document Loader URL required.": "Nepieciešams ārējā dokumentu ielādētāja URL.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Ārējais uzdevumu modelis", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Ārējā tīmekļa ielādētāja API atslēga", "External Web Loader URL": "Ārējā tīmekļa ielādētāja URL", "External Web Search API Key": "Ārējās tīmekļa meklēšanas API atslēga", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Neizdevās izveidot API atslēgu.", "Failed to delete calendar": "", "Failed to delete note": "Neizdevās dzēst piezīmi", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "Neizdevās ekstrahēt saturu no faila: {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Neizdevās iegūt modeļus", "Failed to generate title": "Neizdevās ģenerēt virsrakstu", "Failed to import models": "Neizdevās importēt modeļus", + "Failed to load chat": "", "Failed to load chat preview": "Neizdevās ielādēt tērzēšanas priekšskatījumu", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Neizdevās ielādēt Excel/CSV failu. Lūdzu, mēģiniet to lejupielādēt.", @@ -948,6 +1036,7 @@ "Failed to move chat": "Neizdevās pārvietot tērzēšanu", "Failed to process URL: {{url}}": "Neizdevās apstrādāt URL: {{url}}", "Failed to read clipboard contents": "Neizdevās nolasīt starpliktuves saturu", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Neizdevās noņemt dalībnieku", "Failed to render diagram": "Neizdevās attēlot diagrammu", "Failed to render visualization": "Neizdevās attēlot vizualizāciju", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Neizdevās saglabāt modeļu konfigurāciju", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Neizdevās atjaunināt iestatījumus", "Failed to update status": "Neizdevās atjaunināt statusu", + "Failed to update webhook": "", "Failed to upload file.": "Neizdevās augšupielādēt failu.", "Features": "Funkcijas", "Features Permissions": "Funkciju atļaujas", @@ -991,6 +1082,8 @@ "File uploaded successfully": "Fails veiksmīgi augšupielādēts", "Filename": "", "Files": "Faili", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtrs", "Filter is now globally disabled": "Filtrs tagad ir globāli atspējots", "Filter is now globally enabled": "Filtrs tagad ir globāli iespējots", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "Mape veiksmīgi atjaunināta", "Folders": "Mapes", + "Folders Sharing": "", "Follow up": "Turpinājums", "Follow Up Generation": "Turpinājuma ģenerēšana", "Follow Up Generation Prompt": "Turpinājuma ģenerēšanas uzvedne", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "Funkcija tagad ir globāli iespējota", "Function Name": "Funkcijas nosaukums", "Function Name Filter List": "Funkciju nosaukumu filtru saraksts", + "Function starter": "", "Function updated successfully": "Funkcija veiksmīgi atjaunināta", "Functions": "Funkcijas", "Functions allow arbitrary code execution.": "Funkcijas atļauj patvaļīgu koda izpildi.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Režģis", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Grupas kanāls", + "Group Claim": "", "Group created successfully": "Grupa veiksmīgi izveidota", "Group deleted successfully": "Grupa veiksmīgi dzēsta", "Group Description": "Grupas apraksts", @@ -1087,6 +1185,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptiskā atgriezeniskā saite", + "Header variables": "", "Headers": "Galvenes", "Headers must be a valid JSON object": "Galvenēm jābūt derīgam JSON objektam", "Height": "Augstums", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID nedrīkst saturēt \":\" vai \"|\" rakstzīmes", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe smilškastes atļaut formas", "iframe Sandbox Allow Same Origin": "iframe smilškastes atļaut to pašu izcelsmi", @@ -1142,6 +1243,7 @@ "Import From Link": "Importēt no saites", "Import Models": "Importēt modeļus", "Import Prompts": "Importēt uzvednes", + "Import Skills": "", "Import successful": "Imports veiksmīgs", "Import Tools": "Importēt rīkus", "Important Update": "Svarīgs atjauninājums", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "Saglabāt sānjoslā", "Key": "Atslēga", "Key is required": "Atslēga ir nepieciešama", - "Keyboard shortcuts": "Tastatūras īsceļi", "Keyboard Shortcuts": "Tastatūras īsceļi", "Knowledge": "Zināšanas", "Knowledge Access": "Zināšanu piekļuve", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Zināšanu nosaukums", "Knowledge Public Sharing": "Zināšanu publiska kopīgošana", "Knowledge Sharing": "Zināšanu kopīgošana", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Zināšanas veiksmīgi atjauninātas", "Kokoro.js (Browser)": "Kokoro.js (pārlūks)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Pēdējā atbilde", "LDAP": "LDAP", - "LDAP server updated": "LDAP serveris atjaunināts", "Leaderboard": "Līderu tabula", "Learn more": "", "Learn More": "Uzzināt vairāk", @@ -1250,6 +1352,7 @@ "Legacy": "Mantojums", "lexical": "leksikāls", "License": "Licence", + "Lifecycle JSON": "", "Lift List": "Pacelt sarakstu", "Light": "Gaišs", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Ierobežot vienlaicīgos meklēšanas vaicājumus. 0 = neierobežots (noklusējums). Iestatiet 1 secīgai izpildei (ieteicams API ar stingriem ātruma ierobežojumiem, piemēram, Brave bezmaksas līmenim).", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Atrašanās vietas piekļuve nav atļauta", "Lost": "Zaudēts", "Low": "Zems", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Izveidoja Open WebUI kopiena", "Make password visible in the user interface": "Padarīt paroli redzamu lietotāja saskarnē", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Pārvaldīt konveijerlīnijas", "Manage Tool Servers": "Pārvaldīt rīku serverus", "Manage your account information.": "Pārvaldiet sava konta informāciju.", + "Mapped Source": "", "March": "Marts", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown galvenes teksta sadalītājs", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Atmiņa veiksmīgi notīrīta", "Memory deleted successfully": "Atmiņa veiksmīgi dzēsta", "Memory updated successfully": "Atmiņa veiksmīgi atjaunināta", + "Merge Accounts by Email": "", "Merge Responses": "Apvienot atbildes", "Merged Response": "Apvienotā atbilde", "Message": "Ziņojums", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Ziņojumi, ko nosūtīsiet pēc saites izveidošanas, netiks kopīgoti. Lietotāji ar URL varēs skatīt kopīgoto tērzēšanu.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personīgais)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (darbs/skola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API atslēga nepieciešama mākoņa API režīmam.", @@ -1381,6 +1490,7 @@ "Models Sharing": "Modeļu kopīgošana", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API atslēga", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Vairāk", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nosauciet savu zināšanu bāzi", "Name, prompt, and model are required": "", "Native": "Vietējais", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "Jauns", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "Nav aktivitātes datu", + "No additional headers are sent unless configured.": "", "No authentication": "Nav autentifikācijas", "No automations found": "", "No chats found": "Tērzēšanas nav atrastas", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "Attālums nav pieejams", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "Bez derīguma termiņa var rasties drošības riski.", + "No external knowledge sources configured.": "", "No feedback found": "Atsauksmes nav atrastas", "No file selected": "Fails nav izvēlēts", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "Nav piespraustu ziņojumu", "No prompts found": "Uzvednes nav atrastas", + "No Repeat": "", "No results": "Nav rezultātu", "No results found": "Rezultāti nav atrasti", "No search query generated": "Meklēšanas vaicājums nav ģenerēts", @@ -1487,6 +1602,7 @@ "No webhooks yet": "Pagaidām nav webhook", "Node Ids": "Mezglu ID", "None": "Nav", + "Not configured": "", "Not factually correct": "Faktiski nepareizi", "Not helpful": "Nav noderīgs", "Not Registered": "Nav reģistrēts", @@ -1502,20 +1618,25 @@ "Notifications": "Paziņojumi", "November": "Novembris", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktobris", "Off": "Izslēgts", "Okay, Let's Go!": "Labi, ejam!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED tumšs", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API iestatījumi atjaunināti", "Ollama Cloud API Key": "Ollama Cloud API atslēga", "Ollama Version": "Ollama versija", + "Omit": "", "On": "Ieslēgts", "Once": "", "OneDrive": "OneDrive", @@ -1586,6 +1707,7 @@ "Password": "Parole", "Passwords do not match.": "Paroles nesakrīt.", "Paste Large Text as File": "Ielīmēt lielu tekstu kā failu", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokuments (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "gaida", "Pending": "Gaida", + "Pending Accounts": "", "Pending User Overlay Content": "Gaidošā lietotāja pārklājuma saturs", "Pending User Overlay Title": "Gaidošā lietotāja pārklājuma virsraksts", "Permission denied when accessing media devices": "Piekļuve multivides ierīcēm liegta", "Permission denied when accessing microphone": "Piekļuve mikrofonam liegta", "Permission denied when accessing microphone: {{error}}": "Piekļuve mikrofonam liegta: {{error}}", "Permissions": "Atļaujas", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API atslēga", "Perplexity Model": "Perplexity modelis", "Perplexity Search API URL": "Perplexity Search API URL", "Perplexity Search Context Usage": "Perplexity meklēšanas konteksta lietojums", "Persistent": "", "Personalization": "Personalizācija", + "Picture Claim": "", "Pin": "Piespraust", "Pin to Sidebar": "", "Pinned": "Piesprausts", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Lūdzu, aizpildiet visus laukus.", "Please register the OAuth client": "Lūdzu, reģistrējiet OAuth klientu", "Please save the connection to persist the OAuth client information and do not change the ID": "Lūdzu, saglabājiet savienojumu, lai saglabātu OAuth klienta informāciju, un nemainiet ID", - "Please select a model first.": "Lūdzu, vispirms izvēlieties modeli.", "Please select a model.": "Lūdzu, izvēlieties modeli.", "Please select a reason": "Lūdzu, izvēlieties iemeslu", "Please select a valid JSON file": "Lūdzu, izvēlieties derīgu JSON failu", "Please select at least one user for Direct Message channel.": "Lūdzu, izvēlieties vismaz vienu lietotāju tiešo ziņojumu kanālam.", "Please wait until all files are uploaded.": "Lūdzu, pagaidiet, līdz visi faili ir augšupielādēti.", "Policy ID": "", + "Policy ID is required": "", "Port": "Ports", "Ports": "", "Positive attitude": "Pozitīva attieksme", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Uzvedņu publiska kopīgošana", "Prompts Sharing": "Uzvedņu kopīgošana", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Publisks", "Pull \"{{searchValue}}\" from Ollama.com": "Lejupielādēt \"{{searchValue}}\" no Ollama.com", "Pull a model from Ollama.com": "Lejupielādēt modeli no Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Lasīt", "Read Aloud": "Nolasīt skaļi", "Read more →": "Lasīt vairāk →", + "Read only": "", "Read Only": "Tikai lasīšanai", "Read-Only Access": "Tikai lasīšanas piekļuve", "Reason": "Iemesls", "Reasoning Effort": "Spriedumu pūles", "Reasoning Tags": "Spriedumu tagi", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Ierakstīt", "Record voice": "Ierakstīt balsi", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Novirza jūs uz Open WebUI kopienu", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Samazina bezjēdzīga teksta ģenerēšanas varbūtību. Augstāka vērtība (piem., 100) sniegs daudzveidīgākas atbildes, bet zemāka vērtība (piem., 10) būs konservatīvāka.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Atsaucieties uz sevi kā \"Lietotājs\" (piem., \"Lietotājs mācās spāņu valodu\")", "Reference Chats": "Atsauces tērzēšanas", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_zero": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Atteica, kad nevajadzēja", "Regenerate": "Atkārtoti ģenerēt", "Regenerate Menu": "Atkārtotas ģenerēšanas izvēlne", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Pārkārtot modeļus", + "Repeat": "", "Repeats": "", "Reply": "Atbildēt", "Reply in Thread": "Atbildēt pavedienā", "Reply to thread...": "Atbildēt pavedienā...", "Replying to {{NAME}}": "Atbild {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "nepieciešams", "Reranking Batch Size": "", "Reranking Engine": "Pārkārtošanas dzinējs", "Reranking Model": "Pārkārtošanas modelis", + "Research Knowledge": "", "Reset": "Atiestatīt", "Reset All Models": "Atiestatīt visus modeļus", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Atiestatīt attēlu", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Atiestatīt augšupielādes direktoriju", "Reset Vector Storage/Knowledge": "Atiestatīt vektoru krātuvi/zināšanas", "Reset view": "Atiestatīt skatu", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "Izgūts 1 avots", "Rich Text Input for Chat": "Bagātinātā teksta ievade tērzēšanai", "Role": "Loma", + "Roles Claim": "", "RTL": "RTL", "Run": "Palaist", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Tērzēšanas žurnālu saglabāšana tieši pārlūka krātuvē vairs netiek atbalstīta. Lūdzu, veltiet brīdi, lai lejupielādētu un dzēstu tērzēšanas žurnālus, noklikšķinot uz pogas zemāk. Neuztraucieties, jūs varat viegli atkārtoti importēt tērzēšanas žurnālus aizmugursistēmā caur", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Ritināt pie zara maiņas", "Scroll to Top": "", "Search": "Meklēt", "Search a model": "Meklēt modeli", + "Search actions": "", "Search all emojis": "Meklēt visas emocijzīmes", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Meklēt tērzēšanas", "Search Collection": "Meklēt kolekcijā", "Search Files": "", + "Search filters": "", "Search Filters": "Meklēšanas filtri", "search for archived chats": "meklēt arhivētās tērzēšanas", "search for folders": "meklēt mapes", @@ -1818,13 +1965,16 @@ "Search Models": "Meklēt modeļus", "Search Notes": "Meklēt piezīmes", "Search options": "Meklēšanas opcijas", + "Search or add pattern": "", "Search Prompts": "Meklēt uzvednes", "Search Result Count": "Meklēšanas rezultātu skaits", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Meklēt internetā", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Meklēt rīkus", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API atslēga", "SearchApi Engine": "SearchApi dzinējs", @@ -1840,7 +1990,6 @@ "Seed": "Sēkla", "Select": "Izvēlēties", "Select {{modelName}} model": "", - "Select a base model": "Izvēlieties bāzes modeli", "Select a base model (e.g. llama3, gpt-4o)": "Izvēlieties bāzes modeli (piem., llama3, gpt-4o)", "Select a conversation to preview": "Izvēlieties sarunu priekšskatījumam", "Select a engine": "Izvēlieties dzinēju", @@ -1878,18 +2027,25 @@ "semantic": "semantisks", "Send": "Nosūtīt", "Send a Message": "Nosūtīt ziņojumu", + "Send events for": "", "Send message": "Nosūtīt ziņojumu", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Nosūta `stream_options: { include_usage: true }` pieprasījumā.\nAtbalstītie pakalpojumu sniedzēji atgriezīs tokenu lietojuma informāciju atbildē, ja iestatīts.", "September": "Septembris", "SerpApi API Key": "SerpApi API atslēga", "SerpApi Engine": "SerpApi dzinējs", "Serper API Key": "Serper API atslēga", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API atslēga", "Serpstack API Key": "Serpstack API atslēga", "Server connection failed": "", "Server connection verified": "Servera savienojums pārbaudīts", + "Service Account": "", "Session": "Sesija", + "Session expired. Please sign in again.": "", "Set as default": "Iestatīt kā noklusējumu", "Set as Production": "", "Set embedding model": "Iestatīt iegulšanas modeli", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Kopīgot Open WebUI kopienā", "Share your background and interests": "Dalieties ar savu pieredzi un interesēm", + "Shared": "", "Shared Chats": "", "Shared with you": "Kopīgots ar jums", "Sharing Permissions": "Kopīgošanas atļaujas", "Show": "Rādīt", - "Show \"What's New\" modal on login": "Rādīt \"Kas jauns\" logu pie pieteikšanās", + "Show \"What's New\" Modal on Login": "Rādīt \"Kas jauns\" logu pie pieteikšanās", "Show Admin Details in Account Pending Overlay": "Rādīt administratora detaļas konta gaidīšanas pārklājumā", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "Rādīt failus", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Rādīt formatēšanas rīkjoslu", "Show image preview": "Rādīt attēla priekšskatījumu", "Show Model": "Rādīt modeli", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Avots", + "Specific users or groups": "", "Speech Playback Speed": "Runas atskaņošanas ātrums", "Speech recognition error: {{error}}": "Runas atpazīšanas kļūda: {{error}}", "Speech-to-Text": "Runa uz tekstu", @@ -2006,6 +2165,7 @@ "STT Settings": "STT iestatījumi", "Stylized PDF Export": "Stilizēts PDF eksports", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "Apakšvirsraksts", @@ -2030,8 +2190,10 @@ "Syncing...": "Sinhronizē...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sinhronizē tikai tērzēšanas ar atjauninājumiem pēc jūsu pēdējās sinhronizācijas laika zīmoga. Atspējojiet, lai atkārtoti sinhronizētu visas tērzēšanas.", "System": "Sistēma", + "System events only": "", "System Instructions": "Sistēmas instrukcijas", "System Prompt": "Sistēmas uzvedne", + "Table": "", "Tag": "Tags", "Tags": "Tagi", "Tags Generation": "Tagu ģenerēšana", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Pagaidu tērzēšana pēc noklusējuma", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Teksta sadalītājs", "Text-to-Speech": "Teksts uz runu", "Text-to-Speech Engine": "Teksta uz runas dzinējs", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Ievades audio valoda. Ievades valodas norādīšana ISO-639-1 formātā (piem., lv) uzlabos precizitāti un latentumu. Atstājiet tukšu, lai automātiski noteiktu valodu.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP atribūts, kas tiek kartēts uz e-pastu, ko lietotāji izmanto pieteikšanās.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP atribūts, kas tiek kartēts uz lietotājvārdu, ko lietotāji izmanto pieteikšanās.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Līderu tabula pašlaik ir beta versijā, un mēs varam pielāgot vērtējuma aprēķinus, uzlabojot algoritmu.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Maksimālais faila izmērs MB. Ja faila izmērs pārsniedz šo ierobežojumu, fails netiks augšupielādēts.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maksimālais failu skaits, ko var izmantot vienlaicīgi tērzēšanā. Ja failu skaits pārsniedz šo ierobežojumu, faili netiks augšupielādēti.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Teksta izvades formāts. Var būt 'json', 'markdown' vai 'html'. Noklusējums ir 'markdown'.", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "Šī ir noklusējuma lietotāja atļauja un paliks iespējota.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Šī ir eksperimentāla funkcija, tā var nedarboties kā paredzēts un var tikt mainīta jebkurā laikā.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Šis modelis nav publiski pieejams. Lūdzu, izvēlieties citu modeli.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Šī opcija kontrolē, cik ilgi modelis paliks ielādēts atmiņā pēc pieprasījuma (noklusējums: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Šī opcija kontrolē, cik tokenu tiek saglabāti, atsvaidzinot kontekstu. Piemēram, ja iestatīts uz 2, tiks saglabāti pēdējie 2 sarunas konteksta tokeni. Konteksta saglabāšana var palīdzēt uzturēt sarunas nepārtrauktību, bet var samazināt spēju atbildēt uz jaunām tēmām.", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Lai uzzinātu vairāk par pieejamajiem galapunktiem, apmeklējiet mūsu dokumentāciju.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Lai izvēlētos rīku komplektus šeit, vispirms pievienojiet tos \"Rīku\" darba videi.", - "Toast notifications for new updates": "Uznirstošie paziņojumi par jauniem atjauninājumiem", + "Toast Notifications for New Updates": "Uznirstošie paziņojumi par jauniem atjauninājumiem", "Today": "Šodien", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Šodien plkst. {{LOCALIZED_TIME}}", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "Pārslēgt, vai pašreizējais savienojums ir aktīvs.", "Token": "Tokens", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Pārāk gari", @@ -2191,14 +2361,19 @@ "Unpin": "Atspraust", "Unpin from Sidebar": "", "Unravel secrets": "Atšķetiniet noslēpumus", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "Neatbalstīts faila tips.", "Untagged": "Bez tagiem", "Untitled": "Bez nosaukuma", "Update": "Atjaunināt", "Update and Copy Link": "Atjaunināt un kopēt saiti", + "Update Email": "", "Update for the latest features and improvements.": "Atjauniniet, lai iegūtu jaunākās funkcijas un uzlabojumus.", + "Update Name": "", "Update password": "Atjaunināt paroli", + "Update Picture": "", "Update your status": "Atjauniniet savu statusu", "Updated": "Atjaunināts", "Updated at": "Atjaunināts", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Izmantojiet '#' uzvednes ievadē, lai ielādētu un iekļautu savas zināšanas.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Izmantojiet /v1/chat/completions galapunktu /v1/audio/transcriptions vietā potenciāli labākai precizitātei.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Izmantot tērzēšanas pabeigšanas API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "Izmantot LLM", "Use no proxy to fetch page contents.": "Neizmantot starpniekserveri lapu satura iegūšanai.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Izmantot starpniekserveri, kas norādīts http_proxy un https_proxy vides mainīgajos, lapu satura iegūšanai.", + "Use Web Search?": "", "user": "lietotājs", "User": "Lietotājs", + "User Access": "", "User Activity": "", "User Groups": "Lietotāju grupas", "User location successfully retrieved.": "Lietotāja atrašanās vieta veiksmīgi iegūta.", @@ -2241,6 +2421,7 @@ "User Status": "Lietotāja statuss", "User Webhooks": "Lietotāja webhook", "Username": "Lietotājvārds", + "Username Claim": "", "users": "lietotāji", "Users": "Lietotāji", "Uses DefaultAzureCredential to authenticate": "Izmanto DefaultAzureCredential autentifikācijai", @@ -2254,6 +2435,7 @@ "Valves updated": "Vārsti atjaunināti", "Valves updated successfully": "Vārsti veiksmīgi atjaunināti", "variable": "mainīgais", + "Vector Field": "", "Verify Connection": "Pārbaudīt savienojumu", "Verify SSL Certificate": "Pārbaudīt SSL sertifikātu", "Version": "Versija", @@ -2283,11 +2465,14 @@ "Web API": "Tīmekļa API", "Web Loader Engine": "Tīmekļa ielādētāja dzinējs", "Web Search": "Tīmekļa meklēšana", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Tīmekļa meklētājs", "Web Search in Chat": "Tīmekļa meklēšana tērzēšanā", "Web Search Query Generation": "Tīmekļa meklēšanas vaicājuma ģenerēšana", + "Webhook deleted": "", "Webhook Name": "Webhook nosaukums", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "Webhook", "Webpage URLs": "Tīmekļa lapu URL", "WebUI Settings": "WebUI iestatījumi", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Vakar", "Yesterday at {{LOCALIZED_TIME}}": "Vakar plkst. {{LOCALIZED_TIME}}", "You": "Jūs", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Visa jūsu iemaksa nonāks tieši pie spraudņa izstrādātāja; Open WebUI neņem nekādu procentu. Tomēr izvēlētajai finansējuma platformai var būt savas maksas.", "Your message text or inputs": "Jūsu ziņojuma teksts vai ievades", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Jūsu lietošanas statistika ir veiksmīgi sinhronizēta.", "YouTube": "YouTube", "Youtube Language": "YouTube valoda", diff --git a/src/lib/i18n/locales/ms-MY/translation.json b/src/lib/i18n/locales/ms-MY/translation.json index d9d508415b..59bb1ea08b 100644 --- a/src/lib/i18n/locales/ms-MY/translation.json +++ b/src/lib/i18n/locales/ms-MY/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "{{COUNT}} baris yang diekstrak", "{{COUNT}} files": "{{COUNT}} fail", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} baris tersembunyi", "{{COUNT}} members": "{{COUNT}} ahli", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "{{COUNT}} Baris", "{{count}} selected_other": "{{count}} terpilih", "{{COUNT}} Sources": "{{COUNT}} Sumber", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} perkataan", "{{COUNT}}d_time_ago": "{{COUNT}}h yang lalu", "{{COUNT}}h_time_ago": "{{COUNT}}j yang lalu", "{{COUNT}}m_time_ago": "{{COUNT}}m yang lalu", "{{COUNT}}w_time_ago": "{{COUNT}}mgu yang lalu", "{{COUNT}}y_time_ago": "{{COUNT}}t yang lalu", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} pada {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Muat turun {{model}} telah dibatalkan", "{{modelName}} profile image": "Imej profil {{modelName}}", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "Perbualan {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Backend diperlukan", "*Prompt node ID(s) are required for image generation": "*ID nod Prompt diperlukan untuk penjanaan imej", + "1 group": "", "1 hour before": "1 jam sebelum", "1 Source": "1 Sumber", + "1 user": "", "10 minutes before": "10 minit sebelum", "15 minutes before": "15 minit sebelum", "1m_time_ago": "1m yang lalu", @@ -54,6 +61,7 @@ "Access Control": "Kawalan Akses", "Access Grants": "Pemberian Akses", "Access List": "Senarai Akses", + "Access prohibited": "", "Access updated": "Akses dikemas kini", "Accessible to all users": "Boleh diakses oleh semua pengguna", "Account": "Akaun", @@ -69,6 +77,7 @@ "Activity": "Aktiviti", "Add": "Tambah", "Add a model ID": "Tambah ID model", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Tambah penerangan ringkas tentang apa yang model ini boleh lakukan", "Add a tag": "Tambah tag", "Add a tag...": "Tambah tag...", @@ -81,8 +90,10 @@ "Add Custom Prompt": "Tambah Prompt Tersuai", "Add description": "Tambah penerangan", "Add Details": "Tambah Butiran", + "Add durable context for future chats": "", "Add Files": "Tambah Fail", "Add Image": "Tambah Imej", + "Add Knowledge Connection": "", "Add location": "Tambah lokasi", "Add Member": "Tambah Ahli", "Add Members": "Tambah Ahli", @@ -97,6 +108,7 @@ "Add to favorites": "Tambah ke kegemaran", "Add User": "Tambah Pengguna", "Add User Group": "Tambah Kumpulan Pengguna", + "Add webhook": "", "Add webpage": "Tambah halaman web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Tambah URL Open Terminal dan kunci API anda dalam Tetapan → Integrasi.", "Additional Config": "Konfigurasi Tambahan", @@ -109,7 +121,9 @@ "Admin": "Pentadbir", "Admin Contact Email": "E-mel Pentadbir", "Admin Panel": "Panel Pentadbir", + "Admin Roles": "", "Admin Settings": "Tetapan Pentadbir", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Pentadbir mempunyai akses kepada semua alat pada setiap masa; pengguna memerlukan alat yang ditetapkan mengikut model dalam ruang kerja.", "Advanced": "Lanjutan", "Advanced Parameters": "Parameter Lanjutan", @@ -120,16 +134,21 @@ "All": "Semua", "All chats have been unarchived.": "Semua perbualan telah nyaharkib.", "All day": "Sepanjang hari", + "All events": "", "All models are now hidden": "Semua model kini tersembunyi", "All models are now visible": "Semua model kini kelihatan", "All models deleted successfully": "Semua model telah dipadamkan dengan berjaya", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Sepanjang masa", "All Users": "Semua Pengguna", + "All users and system events": "", "Allow Call": "Benarkan Panggilan", "Allow Chat Controls": "Benarkan Kawalan Perbualan", "Allow Chat Delete": "Benarkan Padam Perbualan", "Allow Chat Edit": "Benarkan Sunting Perbualan", "Allow Chat Export": "Benarkan Eksport Perbualan", + "Allow Chat Import": "", "Allow Chat Params": "Benarkan Parameter Perbualan", "Allow Chat Share": "Benarkan Kongsi Perbualan", "Allow Chat System Prompt": "Benarkan Arahan Sistem Perbualan", @@ -149,9 +168,11 @@ "Allow User Location": "Benarkan Lokasi Pengguna", "Allow Voice Interruption in Call": "Benarkan gangguan suara dalam panggilan", "Allow Web Upload": "Benarkan Muat Naik Web", + "Allowed Domains": "", "Allowed Endpoints": "Titik Akhir yang Dibenarkan", "Allowed File Extensions": "Sambungan Fail yang Dibenarkan", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Sambungan fail yang dibenarkan untuk muat naik. Pisahkan pelbagai sambungan dengan koma. Biarkan kosong untuk semua jenis fail.", + "Allowed Roles": "", "Already have an account?": "Sudah mempunyai akaun?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatif kepada top_p, dan bertujuan untuk memastikan keseimbangan antara kualiti dan kepelbagaian. Parameter p mewakili kebarangkalian minimum untuk token dipertimbangkan, relatif kepada kebarangkalian token yang paling berkemungkinan. Sebagai contoh, dengan p=0.05 dan token yang paling berkemungkinan mempunyai kebarangkalian 0.9, logit dengan nilai kurang daripada 0.045 ditapis keluar.", "Always": "Sentiasa", @@ -170,6 +191,7 @@ "API Base URL": "URL Asas API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL Asas API untuk perkhidmatan Datalab Marker. Lalai kepada: https://www.datalab.to/api/v1/marker", "API Key": "Kunci API", + "API Key / Token": "", "API Key created.": "Kunci API dicipta", "API Key Endpoint Restrictions": "Sekatan Titik Akhir Kunci API", "API keys": "Kekunci API", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Adakah anda pasti ingin memadam ingatan ini? Tindakan ini tidak boleh dibuat asal.", "Are you sure you want to delete this message?": "Adakah anda pasti ingin memadam mesej ini?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Adakah anda pasti ingin memadam versi ini? Versi anak akan dipautkan semula ke induk versi ini.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Adakah anda pasti ingin memadam ini?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Adakah anda pasti ingin menyaharkib semua perbualan yang diarkibkan?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Model Arena", "Artifacts": "Artifak", "Asc": "Naik", "Ask": "Tanya", "Ask a question": "Tanya soalan", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Pembantu", "Async Embedding Processing": "Pemprosesan Embedding Tak Segerak", "At time of event": "Pada masa acara", @@ -220,14 +247,20 @@ "Audio": "Audio", "August": "Ogos", "Auth": "Pengesahan", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Sahkan", "Authentication": "Pengesahan", "Auto": "Automatik", "Auto (Random)": "Automatik (Rawak)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Salin Respons secara Automatik ke Papan Klip", - "Auto-playback response": "Main semula respons secara automatik", + "Auto-Create Groups": "", + "Auto-Playback Response": "Main semula respons secara automatik", "Autocomplete Generation": "Penjanaan Autolengkap", "Autocomplete Generation Input Max Length": "Panjang Maksimum Input Penjanaan Autolengkap", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "URL Asas AUTOMATIC1111", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "Alat Tersedia", "available users": "pengguna tersedia", + "Available variables": "", "available!": "tersedia!", "Away": "Tiada di tempat", "Awful": "Teruk", @@ -255,16 +289,17 @@ "Bad Response": "Respons Tidak Baik", "Banners": "Sepanduk", "Base Model (From)": "Model Asas (Dari)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Senarai Cache Model Asas mempercepatkan akses dengan mengambil model asas hanya pada permulaan atau penyimpanan tetapan—lebih pantas, tetapi mungkin tidak menunjukkan perubahan model asas terbaru.", "Bearer": "Bearer", "before": "sebelum", "Being lazy": "Menjadi Malas", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Titik Akhir Bing Search V7", "Bing Search V7 Subscription Key": "Kunci Langganan Bing Search V7", "Bio": "Biografi", "Birth Date": "Tarikh Lahir", + "Blocked Groups": "", "BM25 Weight": "Berat BM25", "Bocha Search API Key": "Kunci API Bocha Search", "Bold": "Tebal", @@ -321,7 +356,7 @@ "Chat Completions": "Pelengkapan Perbualan", "Chat Conversation": "Perbualan", "Chat deleted.": "Perbualan dipadamkan.", - "Chat direction": "Arah Perbualan", + "Chat Direction": "Arah Perbualan", "Chat exported successfully": "Perbualan telah dieksport dengan berjaya", "Chat History": "Sejarah Perbualan", "Chat ID": "ID Perbualan", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "Saluran kolaborasi di mana orang menyertai sebagai ahli", "Collapse": "Lipat", "Collection": "Koleksi", + "Collection Field": "", "Collections": "Koleksi", "Color": "Warna", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "Aliran Kerja ComfyUI", "ComfyUI Workflow Nodes": "Nod Aliran Kerja ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID Nod yang dipisahkan dengan koma (cth. 1 atau 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "arahan", "Command": "Arahan", "Comment": "Komen", "Commit Message": "Mesej Komit", "Community Reviews": "Ulasan Komuniti", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Penyelesaian", "Compress Images in Channels": "Mampat Imej dalam Saluran", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Sambung ke instans Terminal Terbuka. Semua pengguna akan mempunyai akses kepada penyemakan fail dan alat terminal melalui pelayan ini.", "Connect to your own OpenAI compatible API endpoints.": "Sambung ke titik akhir API yang serasi dengan OpenAI anda sendiri.", "Connect to your own OpenAPI compatible external tool servers.": "Sambung ke pelayan alat luaran yang serasi dengan OpenAPI anda sendiri.", + "Connected": "", "Connected ({{type}})": "Disambungkan ({{type}})", "Connection failed": "Sambungan gagal", "Connection lost. Reconnecting...": "Sambungan terputus. Menyambung semula...", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "Hubungi admin untuk akses WebUI", "Content": "Kandungan", "Content Extraction Engine": "Enjin Pengekstrakan Kandungan", + "Content Field": "", "Content lengths (character counts only)": "Panjang kandungan (kiraan aksara sahaja)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Token Konteks", + "Continue": "", "Continue Response": "Teruskan Respons", "Continue with {{provider}}": "Teruskan dengan {{provider}}", "Continue with Email": "Teruskan dengan Email", @@ -489,6 +536,7 @@ "Create new secret key": "Cipta kekunci rahsia baharu", "Create note": "Buat nota", "Create Note": "Buat Nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Buat arahan berjadual yang dijalankan secara automatik secara berulang.", "Create your first note by clicking on the plus button below.": "Buat nota pertama anda dengan mengklik butang tambah di bawah.", "Created at": "Dicipta pada", @@ -506,6 +554,7 @@ "Custom Gender": "Jantina Tersuai", "Custom Parameter Name": "Nama Parameter Tersuai", "Custom Parameter Value": "Nilai Parameter Tersuai", + "Custom range": "", "Daily": "Harian", "Daily Messages": "Mesej Harian", "Danger Zone": "Zon Bahaya", @@ -528,7 +577,6 @@ "Default Features": "Ciri Lalai", "Default Filters": "Penapis Lalai", "Default Group": "Kumpulan Lalai", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Mod lalai berfungsi dengan rangkaian model yang lebih luas dengan memanggil alat sekali sebelum pelaksanaan. Mod asli memanfaatkan keupayaan panggilan alat terbina dalam model, tetapi memerlukan model untuk menyokong ciri ini secara bawaan.", "Default Model": "Model Lalai", "Default model updated": "Model lalai dikemas kini", "Default permissions": "Kebenaran Lalai", @@ -538,6 +586,7 @@ "Default to ALL": "Lalai kepada SEMUA", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Lalai kepada pengambilan tersegmen untuk pengekstrakan kandungan yang berfokus dan relevan, ini disyorkan untuk kebanyakan kes.", "Default User Role": "Peranan Pengguna Lalai", + "Default webhook": "", "Defaults": "Lalai", "Delete": "Padam", "Delete {{name}}": "Padam {{name}}", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "Nyahaktifkan Pentafsir Kod", "Disable Image Extraction": "Nyahaktifkan Pengekstrakan Imej", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Menyahaktifkan pengekstrakan imej daripada PDF. Jika Gunakan LLM diaktifkan, imej akan diselia secara automatik. Lalai kepada Palsu.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Dinyahaktifkan", "Disconnect OAuth": "Putuskan OAuth", "Discover a function": "Temui fungsi", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "Temui, muat turun dan teroka model pratetap", "Discussion channel where access is based on groups and permissions": "Saluran perbincangan di mana akses berdasarkan kumpulan dan kebenaran", "Display": "Paparan", - "Display chat title in tab": "Paparkan tajuk perbualan dalam tab", + "Display Chat Title in Tab": "Paparkan tajuk perbualan dalam tab", "Display Emoji in Call": "Paparkan Emoji dalam Panggilan", "Display Multi-model Responses in Tabs": "Paparkan Respons Multi-model dalam Tab", - "Display the username instead of You in the Chat": "Paparkan nama pengguna dan bukannya 'Anda' dalam Perbualan", + "Display the Username Instead of You in the Chat": "Paparkan nama pengguna dan bukannya 'Anda' dalam Perbualan", "Displays citations in the response": "Memaparkan petikan dalam respons", "Displays status updates (e.g., web search progress) in the response": "Memaparkan kemas kini status (cth., kemajuan carian web) dalam respons", "Dive into knowledge": "Menyelami pengetahuan", @@ -626,6 +677,7 @@ "Docling Parameters": "Parameter Docling", "Docling Server URL required.": "URL Pelayan Docling diperlukan.", "Document": "Dokumen", + "Document ID Field": "", "Document Intelligence": "Kecerdasan Dokumen", "Document Intelligence endpoint required.": "Titik akhir Dokumen Kecerdasan diperlukan.", "Document Intelligence Model": "Model Kecerdasan Dokumen", @@ -681,12 +733,14 @@ "Edit Default Permissions": "Edit Kebenaran Lalai", "Edit Folder": "Edit Folder", "Edit Image": "Edit Imej", + "Edit Knowledge Connection": "", "Edit Last Message": "Edit Mesej Terakhir", "Edit Memory": "Edit Ingatan", "Edit Prompt": "Edit Arahan", "Edit Terminal Connection": "Edit Sambungan Terminal", "Edit User": "Edit Pengguna", "Edit User Group": "Edit Kumpulan Pengguna", + "Edit webhook": "", "Edit workflow.json content": "Edit kandungan workflow.json", "edited": "disunting", "Edited": "Disunting", @@ -695,6 +749,7 @@ "Eject model": "Keluarkan model", "ElevenLabs": "ElevenLabs", "Email": "E-mel", + "Email Claim": "", "Embark on adventures": "Mula pengembaraan", "Embedding": "Embedding", "Embedding Batch Size": "Saiz Kelompok Embedding", @@ -703,6 +758,7 @@ "Embedding Model Engine": "Enjin Model Embedding", "Emoji": "", "Emojis": "Emoji", + "Empty": "", "Empty message": "Mesej kosong", "Enable All": "Aktifkan Semua", "Enable API Keys": "Aktifkan Kunci API", @@ -710,22 +766,27 @@ "Enable Code Execution": "Aktifkan Pelaksanaan Kod", "Enable Code Interpreter": "Aktifkan Pentafsir Kod", "Enable Community Sharing": "Benarkan Perkongsian Komuniti", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Aktifkan Penguncian Ingatan (mlock) untuk mencegah data model daripada ditukar keluar daripada RAM. Pilihan ini mengunci set halaman kerja model ke dalam RAM, memastikan bahawa ia tidak akan ditukar ke cakera. Ini boleh membantu mengekalkan prestasi dengan mengelakkan kesalahan halaman dan memastikan akses data yang cepat.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Aktifkan Pemetaan Ingatan (mmap) untuk memuatkan data model. Pilihan ini membenarkan sistem menggunakan storan cakera sebagai lanjutan RAM dengan memperlakukan fail cakera seolah-olah ia berada di dalam RAM. Ini boleh meningkatkan prestasi model dengan membenarkan akses data yang lebih cepat. Walau bagaimanapun, ia mungkin tidak berfungsi dengan betul pada semua sistem dan boleh menggunakan sejumlah besar ruang cakera.", "Enable Message Queue": "Aktifkan Barisan Mesej", "Enable Message Rating": "Aktifkan Penilaian Mesej", "Enable Mirostat sampling for controlling perplexity.": "Aktifkan pensampelan Mirostat untuk mengawal kekeliruan.", "Enable New Sign Ups": "Benarkan Pendaftaran Baharu", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Aktifkan, nyahaktifkan, atau sesuaikan tag penaakulan yang digunakan oleh model. \"Diaktifkan\" menggunakan tag lalai, \"Dinyahaktifkan\" mematikan tag penaakulan, dan \"Tersuai\" membenarkan anda menentukan tag permulaan dan akhir anda sendiri.", "Enabled": "Diaktifkan", "End Tag": "Tag Akhir", + "Endpoint": "", "Endpoint URL": "URL Titik Akhir", "Enforce Temporary Chat": "Kuatkuasakan Perbualan Sementara", "Enhance": "Tingkatkan", "Enrich Hybrid Search Text": "Perkaya Teks Carian Hibrid", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Pastikan fail CSV anda mengandungi 4 lajur dalam susunan ini: Nama, E-mel, Kata Laluan, Peranan.", "Enter {{role}} message here": "Masukkan mesej {{role}} di sini", - "Enter a detail about yourself for your LLMs to recall": "Masukkan butiran tentang diri anda untuk diingati oleh LLM anda", "Enter a title for the pending user info overlay. Leave empty for default.": "Masukkan tajuk untuk lapisan maklumat pengguna tertangguh. Biarkan kosong untuk lalai.", "Enter a watermark for the response. Leave empty for none.": "Masukkan tera air untuk respons. Biarkan kosong untuk tiada.", "Enter additional headers in JSON format": "Masukkan pengepala tambahan dalam format JSON", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "Masukkan Saiz Minimum Chunk Target", "Enter Chunk Overlap": "Masukkan Pertindanan Chunk", "Enter Chunk Size": "Masukkan Saiz Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Masukkan pasangan \"token:bias_value\" yang dipisahkan dengan koma (contoh: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Masukkan kandungan untuk lapisan maklumat pengguna tertangguh. Biarkan kosong untuk lalai.", "Enter coordinates (e.g. 51.505, -0.09)": "Masukkan koordinat (cth. 51.505, -0.09)", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "Masukkan URL Jupyter", "Enter Kagi Search API Key": "Masukkan Kunci API Pencarian Kagi", "Enter Key Behavior": "Kelakuan Kekunci Enter", + "Enter language": "", "Enter language codes": "Masukkan kod bahasa", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Masukkan Kunci API MinerU", "Enter Mistral API Base URL": "Masukkan URL Asas API Mistral", "Enter Mistral API Key": "Masukkan Kunci API Mistral", @@ -800,6 +866,7 @@ "Enter prompt here.": "Masukkan arahan di sini.", "Enter proxy URL (e.g. https://user:password@host:port)": "Masukkan URL proksi (contoh: https://user:password@host:port)", "Enter reasoning effort": "Masukkan usaha penaakulan", + "Enter Redirect URI": "", "Enter Score": "Masukkan Skor", "Enter SearchApi API Key": "Masukkan Kunci API SearchApi", "Enter SearchApi Engine": "Masukkan Enjin SearchApi", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "Masukkan Kunci API SerpApi", "Enter SerpApi Engine": "Masukkan Enjin SerpApi", "Enter Serper API Key": "Masukkan Kunci API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Masukkan Kunci API Serply", "Enter Serpstack API Key": "Masukkan Kunci API Serpstack", "Enter server host": "Masukkan hos pelayan", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "Masukkan URL Pelayan Tika", "Enter timeout in seconds": "Masukkan had masa dalam saat", "Enter to Send": "Tekan untuk Hantar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Masukkan 'Top K'", "Enter Top K Reranker": "Masukkan Top K Penyusun Semula", "Enter URL (e.g. http://127.0.0.1:7860/)": "Masukkan URL (cth http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Ralat: Model dengan ID '{{modelId}}' sudah wujud. Sila pilih ID yang berbeza untuk meneruskan.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Ralat: ID Model tidak boleh kosong. Sila masukkan ID yang sah untuk meneruskan.", "Evaluations": "Penilaian", + "Event": "", "Event created": "Acara dicipta", "Event deleted": "Acara dipadamkan", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Tajuk acara", "Event updated": "Acara dikemas kini", + "Events": "", "Exa API Key": "Kunci API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Example: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Contoh: SEMUA", "Example: mail": "Contoh: mail", @@ -901,12 +975,18 @@ "Export Config": "Eksport Konfigurasi", "Export Models": "Eksport Model", "Export Prompts": "Eksport Arahan", + "Export Skills": "", "Export to CSV": "Eksport ke CSV", "Export Tools": "Eksport Alat", "Export Users": "Eksport Pengguna", "External": "Luaran", + "External connection not found.": "", "External Document Loader URL required.": "URL Pemuat Dokumen Luaran diperlukan.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Model Tugas Luaran", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Kunci API Pemuat Web Luaran", "External Web Loader URL": "URL Pemuat Web Luaran", "External Web Search API Key": "Kunci API Carian Web Luaran", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "Gagal mencipta kekunci API", "Failed to delete calendar": "Gagal memadam kalendar", "Failed to delete note": "Gagal memadamkan nota", + "Failed to delete webhook": "", "Failed to disconnect": "Gagal memutuskan sambungan", "Failed to download image": "Gagal memuat turun imej", "Failed to extract content from the file: {{error}}": "Gagal mengekstrak kandungan daripada fail: {{error}}", @@ -931,6 +1012,7 @@ "Failed to fetch models": "Gagal mengambil model", "Failed to generate title": "Gagal menjana tajuk", "Failed to import models": "Gagal mengimport model", + "Failed to load chat": "", "Failed to load chat preview": "Gagal memuatkan pratonton perbualan", "Failed to load DOCX file. Please try downloading it instead.": "Gagal memuatkan fail DOCX. Sila cuba muat turun sebaliknya.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Gagal memuatkan fail Excel/CSV. Sila cuba muat turun sebaliknya.", @@ -940,6 +1022,7 @@ "Failed to move chat": "Gagal memindahkan perbualan", "Failed to process URL: {{url}}": "Gagal memproses URL: {{url}}", "Failed to read clipboard contents": "Gagal membaca kandungan papan klip", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Gagal mengeluarkan ahli", "Failed to render diagram": "Gagal memapar rajah", "Failed to render visualization": "Gagal memapar visualisasi", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "Gagal menyimpan konfigurasi model", "Failed to save policy: {{error}}": "Gagal menyimpan dasar: {{error}}", "Failed to save terminal servers": "Gagal menyimpan pelayan terminal", + "Failed to save webhook": "", "Failed to unshare chat.": "Gagal membatalkan perkongsian perbualan.", "Failed to update settings": "Gagal mengemaskini tetapan", "Failed to update status": "Gagal mengemaskini status", + "Failed to update webhook": "", "Failed to upload file.": "Gagal memuat naik fail.", "Features": "Ciri-ciri", "Features Permissions": "Kebenaran Ciri-ciri", @@ -983,6 +1068,8 @@ "File uploaded successfully": "Fail dimuat naik dengan berjaya", "Filename": "Nama fail", "Files": "Fail-Fail", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Penapis", "Filter is now globally disabled": "Tapisan kini dinyahaktifkan secara global", "Filter is now globally enabled": "Tapisan kini dibenarkan secara global", @@ -1005,6 +1092,7 @@ "Folder options": "Pilihan folder", "Folder updated successfully": "Folder berjaya dikemas kini", "Folders": "Folder-folder", + "Folders Sharing": "", "Follow up": "Susulan", "Follow Up Generation": "Penjanaan Susulan", "Follow Up Generation Prompt": "Arahan Penjanaan Susulan", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "Fungsi kini dibenarkan secara global", "Function Name": "Nama Fungsi", "Function Name Filter List": "Senarai Penapis Nama Fungsi", + "Function starter": "", "Function updated successfully": "Fungsi berjaya dikemas kini", "Functions": "Fungsi", "Functions allow arbitrary code execution.": "Fungsi membenarkan pelaksanaan kod sewenang-wenangnya.", @@ -1067,7 +1156,10 @@ "Gravatar": "Gravatar", "Grid": "Grid", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Saluran Kumpulan", + "Group Claim": "", "Group created successfully": "Kumpulan berjaya dibuat", "Group deleted successfully": "Kumpulan berjaya dipadamkan", "Group Description": "Penerangan Kumpulan", @@ -1079,6 +1171,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Maklum Balas Haptic", + "Header variables": "", "Headers": "Tajuk", "Headers must be a valid JSON object": "Tajuk mesti menjadi objek JSON yang sah", "Height": "Ketinggian", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID tidak boleh mengandungi aksara \":\" atau \"|\"", "ID copied to clipboard": "ID disalin ke papan klip", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Masa Tamat Melahu", "iframe Sandbox Allow Forms": "iframe Sandbox Benarkan Borang", "iframe Sandbox Allow Same Origin": "Benarkan Asal Sama untuk Sandbox iframe", @@ -1134,6 +1229,7 @@ "Import From Link": "Import Daripada Pautan", "Import Models": "Import Model", "Import Prompts": "Import Arahan", + "Import Skills": "", "Import successful": "Import Berjaya", "Import Tools": "Import Alat", "Important Update": "Kemas kini penting", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "Simpan dalam Bar Sisi", "Key": "Kunci", "Key is required": "Kunci diperlukan", - "Keyboard shortcuts": "Pintasan papan kekunci", "Keyboard Shortcuts": "Pintasan Papan Kekunci", "Knowledge": "Pengetahuan", "Knowledge Access": "Akses Pengetahuan", @@ -1204,6 +1299,8 @@ "Knowledge Name": "Nama Pengetahuan", "Knowledge Public Sharing": "Perkongsian Awam Pengetahuan", "Knowledge Sharing": "Perkongsian Pengetahuan", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Pengetahuan telah dikemas kini dengan berjaya", "Kokoro.js (Browser)": "Kokoro.js (Penyemak Imbas)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1220,7 +1317,6 @@ "Last ran": "Kali terakhir dijalankan", "Last reply": "Balasan terakhir", "LDAP": "LDAP", - "LDAP server updated": "Pelayan LDAP dikemas kini", "Leaderboard": "Papan Kedudukan", "Learn more": "Ketahui lebih lanjut", "Learn More": "Ketahui Lebih Lanjut", @@ -1242,6 +1338,7 @@ "Legacy": "Warisan", "lexical": "leksikal", "License": "Lesen", + "Lifecycle JSON": "", "Lift List": "Keluarkan Senarai", "Light": "Cerah", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Hadkan pertanyaan carian serentak. 0 = tanpa had (lalai). Tetapkan kepada 1 untuk pelaksanaan berurutan (disyorkan untuk API dengan had kadar ketat seperti peringkat percuma Brave).", @@ -1265,6 +1362,7 @@ "Location access not allowed": "Akses lokasi tidak dibenarkan", "Lost": "Hilang", "Low": "Rendah", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Dicipta oleh Komuniti OpenWebUI", "Make password visible in the user interface": "Buat kata laluan kelihatan dalam antara muka pengguna", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "Urus Pipeline", "Manage Tool Servers": "Urus Pelayan Alat", "Manage your account information.": "Urus maklumat akaun anda.", + "Mapped Source": "", "March": "Mac", "Markdown": "Markdown", "Markdown Header Text Splitter": "Pemisah Teks Tajuk Markdown", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "Ingatan berjaya dikosongkan", "Memory deleted successfully": "Ingatan berjaya dipadamkan", "Memory updated successfully": "Ingatan berjaya dikemas kini", + "Merge Accounts by Email": "", "Merge Responses": "Gabungkan Respons", "Merged Response": "Respons Digabungkan", "Message": "Mesej", @@ -1318,9 +1418,12 @@ "messages": "mesej", "Messages": "Mesej", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mesej yang anda hantar selepas membuat pautan anda tidak akan dikongsi. Pengguna dengan URL akan dapat melihat perbualan yang dikongsi.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (peribadi)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (kerja/sekolah)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Kunci API MinerU diperlukan untuk mod Cloud API.", @@ -1373,6 +1476,7 @@ "Models Sharing": "Perkongsian Model", "Mojeek": "Mojeek", "Mojeek Search API Key": "Kunci API Pencarian Mojeek", + "Monday – Friday": "", "Month": "Bulan", "Monthly": "Bulanan", "More": "Lagi", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "Namakan pangkalan pengetahuan anda", "Name, prompt, and model are required": "Nama, arahan, dan model diperlukan", "Native": "Asli", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Tidak Pernah", "New": "Baharu", "New Automation": "Automasi Baharu", @@ -1419,6 +1524,7 @@ "Next run": "Pelaksanaan seterusnya", "No access grants. Private to you.": "Tiada geran akses. Peribadi untuk anda.", "No activity data": "Tiada data aktiviti", + "No additional headers are sent unless configured.": "", "No authentication": "Tiada pengesahan", "No automations found": "Tiada automasi dijumpai", "No chats found": "Tiada perbualan ditemui", @@ -1431,8 +1537,10 @@ "No data": "Tiada data", "No data found": "Tiada data ditemui", "No distance available": "Tiada jarak tersedia", + "No event webhooks configured.": "", "No execution logs available yet": "Tiada log pelaksanaan tersedia lagi", "No expiration can pose security risks.": "Tiada tamat tempoh boleh menimbulkan risiko keselamatan.", + "No external knowledge sources configured.": "", "No feedback found": "Tiada maklum balas ditemui", "No file selected": "Tiada fail dipilih", "No files found": "Tiada fail ditemui", @@ -1460,6 +1568,7 @@ "No output items": "Tiada item output", "No pinned messages": "Tiada mesej disematkan", "No prompts found": "Tiada arahan ditemui", + "No Repeat": "", "No results": "Tiada keputusan dijumpai", "No results found": "Tiada keputusan dijumpai", "No search query generated": "Tiada pertanyaan carian dijana", @@ -1479,6 +1588,7 @@ "No webhooks yet": "Tiada webhook lagi", "Node Ids": "Id Nod", "None": "Tiada", + "Not configured": "", "Not factually correct": "Tidak tepat secara fakta", "Not helpful": "Tidak berguna", "Not Registered": "Tidak Didaftar", @@ -1494,20 +1604,25 @@ "Notifications": "Pemberitahuan", "November": "November", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statik)", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL Pelayan OAuth", "OAuth session disconnected": "Sesi OAuth diputuskan", "October": "Oktober", "Off": "Mati", "Okay, Let's Go!": "Baiklah, Jom!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Gelap", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Tetapan API Ollama dikemas kini", "Ollama Cloud API Key": "Kunci API Ollama Cloud", "Ollama Version": "Versi Ollama", + "Omit": "", "On": "Hidup", "Once": "Sekali", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "Kata Laluan", "Passwords do not match.": "Kata laluan tidak sepadan.", "Paste Large Text as File": "Tampal Teks Besar sebagai Fail", + "Path": "", "Path copied": "Laluan disalin", "Paused": "Dijeda", "PDF document (.pdf)": "Dokumen PDF (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "tertangguh", "Pending": "Tertangguh", + "Pending Accounts": "", "Pending User Overlay Content": "Kandungan Lapisan Pengguna Tertangguh", "Pending User Overlay Title": "Tajuk Lapisan Pengguna Tertangguh", "Permission denied when accessing media devices": "Tidak mendapat kebenaran apabila cuba mengakses peranti media", "Permission denied when accessing microphone": "Tidak mendapat kebenaran apabila cuba mengakses mikrofon", "Permission denied when accessing microphone: {{error}}": "Tidak mendapat kebenaran apabila cuba mengakses mikrofon: {{error}}", "Permissions": "Kebenaran", + "Permissions reset to defaults": "", "Perplexity API Key": "Kunci API Perplexity", "Perplexity Model": "Model Perplexity", "Perplexity Search API URL": "URL API Pencarian Perplexity", "Perplexity Search Context Usage": "Penggunaan Konteks Pencarian Perplexity", "Persistent": "Kekal", "Personalization": "Personalisasi", + "Picture Claim": "", "Pin": "Semat", "Pin to Sidebar": "Semat pada Bar Sisi", "Pinned": "Disemat", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "Sila isi semua medan.", "Please register the OAuth client": "Sila daftarkan klien OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Sila simpan sambungan untuk mengekalkan maklumat klien OAuth dan jangan ubah ID", - "Please select a model first.": "Sila pilih model terlebih dahulu.", "Please select a model.": "Sila pilih model.", "Please select a reason": "Sila pilih satu sebab", "Please select a valid JSON file": "Sila pilih fail JSON yang sah", "Please select at least one user for Direct Message channel.": "Sila pilih sekurang-kurangnya satu pengguna untuk saluran Direct Message.", "Please wait until all files are uploaded.": "Sila tunggu sehingga semua fail dimuat naik.", "Policy ID": "ID Dasar", + "Policy ID is required": "", "Port": "Port", "Ports": "Port", "Positive attitude": "Sikap positif", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "Perkongsian Awam Arahan", "Prompts Sharing": "Perkongsian Arahan", "Provider": "Pembekal", + "Provider Name": "", + "Provider URL": "", "Public": "Awam", "Pull \"{{searchValue}}\" from Ollama.com": "Tarik \"{{ searchValue }}\" daripada Ollama.com", "Pull a model from Ollama.com": "Tarik model daripada Ollama.com", @@ -1683,21 +1804,28 @@ "Read": "Baca", "Read Aloud": "Baca dengan lantang", "Read more →": "Baca lanjut →", + "Read only": "", "Read Only": "Baca Sahaja", "Read-Only Access": "Akses Baca Sahaja", "Reason": "Sebab", "Reasoning Effort": "Usaha Penaakulan", "Reasoning Tags": "Tag Penaakulan", "Reasoning text...": "Teks penaakulan...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Digunakan Baru-Baru Ini", "Reconnected": "Disambung semula", "Record": "Rakaman", "Record voice": "Rakam suara", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Membawa anda ke Komuniti OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Mengurangkan kebarangkalian menjana jawapan tanpa makna. Nilai yang lebih tinggi (cth. 100) akan memberikan jawapan yang lebih pelbagai, manakala nilai yang lebih rendah (cth. 10) akan lebih konservatif.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Rujuk diri anda sebagai \"User\" (cth, \"Pengguna sedang belajar bahasa Sepanyol\")", "Reference Chats": "Perbualan Rujukan", "Refresh": "Segarkan", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Menolak di mana ia tidak sepatutnya", "Regenerate": "Jana semula", "Regenerate Menu": "Menu Jana Semula", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "Papar Markdown dalam Pratonton", "Render Markdown in User Messages": "Papar Markdown dalam Mesej Pengguna", "Reorder Models": "Susun Semula Model", + "Repeat": "", "Repeats": "Ulangan", "Reply": "Balas", "Reply in Thread": "Balas dalam Benang", "Reply to thread...": "Balas ke benang...", "Replying to {{NAME}}": "Membalas kepada {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "diperlukan", "Reranking Batch Size": "Saiz Kelompok Penyusunan Semula", "Reranking Engine": "Enjin Penyusunan Semula", "Reranking Model": "Model Penyusunan Semula", + "Research Knowledge": "", "Reset": "Tetapkan Semula", "Reset All Models": "Tetapkan Semula Semua Model", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Tetapkan Semula Imej", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Tetapkan Semula Direktori Muat Naik", "Reset Vector Storage/Knowledge": "Tetapkan Semula Storan Vektor/Pengetahuan", "Reset view": "Tetapkan Semula Paparan", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "Mengambil 1 sumber", "Rich Text Input for Chat": "Input Teks Kaya untuk Perbualan", "Role": "Peranan", + "Roles Claim": "", "RTL": "RTL", "Run": "Jalankan", "Run All": "Jalankan Semua", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Penyimpanan log perbualan terus ke storan pelayar web anda tidak lagi disokong. Sila luangkan sedikit masa untuk memuat turun dan memadam log perbualan anda dengan mengklik butang di bawah. Jangan risau, anda boleh mengimport semula log perbualan anda dengan mudah melalui 'backend'", "Schedule": "Jadual", "Scheduled time must be in the future": "Masa dijadualkan mestilah pada masa hadapan", + "Scopes": "", "Scroll On Branch Change": "Skrol Semasa Pertukaran Cabang", "Scroll to Top": "Tatal ke Atas", "Search": "Carian", "Search a model": "Cari Model", + "Search actions": "", "Search all emojis": "Cari semua emoji", "Search and manage user memories": "Cari dan urus ingatan pengguna", "Search and view user chat history": "Cari dan lihat sejarah perbualan pengguna", @@ -1792,6 +1930,7 @@ "Search Chats": "Cari Perbualan", "Search Collection": "Cari Koleksi", "Search Files": "Cari Fail", + "Search filters": "", "Search Filters": "Penapis Carian", "search for archived chats": "cari untuk perbualan yang diarkibkan", "search for folders": "cari untuk folder", @@ -1806,13 +1945,16 @@ "Search Models": "Carian Model", "Search Notes": "Cari Nota", "Search options": "Pilihan carian", + "Search or add pattern": "", "Search Prompts": "Carian arahan", "Search Result Count": "Kiraan Hasil Carian", + "Search skills": "", "Search Skills": "Cari Kemahiran", - "Search skills...": "", "Search the internet": "Cari di internet", "Search the web and fetch URLs": "Cari di web dan ambil URL", + "Search tools": "", "Search Tools": "Alat Carian", + "Search users or groups": "", "Search, view, and manage user notes": "Cari, lihat, dan urus nota pengguna", "SearchApi API Key": "Kunci API SearchApi", "SearchApi Engine": "Enjin SearchApi", @@ -1828,7 +1970,6 @@ "Seed": "Benih", "Select": "Pilih", "Select {{modelName}} model": "Pilih model {{modelName}}", - "Select a base model": "Pilih model asas", "Select a base model (e.g. llama3, gpt-4o)": "Pilih model asas (cth. llama3, gpt-4o)", "Select a conversation to preview": "Pilih perbualan untuk pratonton", "Select a engine": "Pilih enjin", @@ -1866,18 +2007,25 @@ "semantic": "semantik", "Send": "Hantar", "Send a Message": "Hantar Pesanan", + "Send events for": "", "Send message": "Hantar pesanan", "Send now": "Hantar sekarang", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Menghantar `stream_options: { include_usage: true }` dalam permintaan. Pembekal yang disokong akan mengembalikan maklumat penggunaan token dalam respons apabila ditetapkan.", "September": "September", "SerpApi API Key": "Kunci API SerpApi", "SerpApi Engine": "Enjin SerpApi", "Serper API Key": "Kunci API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Kunci API Serply", "Serpstack API Key": "Kunci API Serpstack", "Server connection failed": "Sambungan pelayan gagal", "Server connection verified": "Sambungan pelayan disahkan", + "Service Account": "", "Session": "Sesi", + "Session expired. Please sign in again.": "", "Set as default": "Tetapkan sebagai lalai", "Set as Production": "Tetapkan sebagai Pengeluaran", "Set embedding model": "Tetapkan model Embedding", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "Pautan kongsi telah disalin ke papan klip.", "Share to Open WebUI Community": "Kongsi kepada Komuniti OpenWebUI", "Share your background and interests": "Kongsi latar belakang dan minat anda", + "Shared": "", "Shared Chats": "Perbualan yang Dikongsi", "Shared with you": "Dikongsi dengan anda", "Sharing Permissions": "Kebenaran Berkongsi", "Show": "Tunjukkan", - "Show \"What's New\" modal on login": "Paparkan modal \"Apa yang Baru\" semasa log masuk", + "Show \"What's New\" Modal on Login": "Paparkan modal \"Apa yang Baru\" semasa log masuk", "Show Admin Details in Account Pending Overlay": "Tunjukkan Butiran Pentadbir dalam Akaun Menunggu Tindanan", "Show All": "Paparkan Semua", "Show all ({{COUNT}} characters)": "Paparkan semua ({{COUNT}} aksara)", "Show Files": "Paparkan Fail", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Paparkan Bar Alatan Format", "Show image preview": "Tunjukkan pratonton imej", "Show Model": "Tunjukkan Model", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "sID API Carian Sougou", "Sougou Search API SK": "SK API Carian Sougou", "Source": "Sumber", + "Specific users or groups": "", "Speech Playback Speed": "Kelajuan Main Balik Suara", "Speech recognition error: {{error}}": "Ralat pengecaman pertuturan: {{error}}", "Speech-to-Text": "Pertuturan-ke-Teks", @@ -1992,6 +2143,7 @@ "STT Settings": "Tetapan STT", "Stylized PDF Export": "Eksport PDF Bergaya", "Su_day_of_week": "Ahd", + "Sub Claim": "", "Submit question": "Hantar soalan", "Submit suggestion": "Hantar cadangan", "Subtitle": "Subtitle", @@ -2016,8 +2168,10 @@ "Syncing...": "Sedang menyegerak...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Hanya menyegerak perbualan dengan kemas kini selepas cap masa segerak terakhir anda. Nyahaktifkan untuk menyegerak semula semua perbualan.", "System": "Sistem", + "System events only": "", "System Instructions": "Arahan Sistem", "System Prompt": "Arahan Sistem", + "Table": "", "Tag": "Tag", "Tags": "Tag-tag", "Tags Generation": "Penjanaan Tag", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "Perbualan Sementara secara Lalai", "Terminal": "Terminal", "Terminal servers saved": "Pelayan Terminal Disimpan", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Pemisah Teks", "Text-to-Speech": "Teks-ke-Ucapan", "Text-to-Speech Engine": "Enjin Teks-ke-Ucapan", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Bahasa audio input. Membekalkan bahasa input dalam format ISO-639-1 (cth. en) akan meningkatkan ketepatan dan kependaman. Biarkan kosong untuk mengesan bahasa secara automatik.", "The LDAP attribute that maps to the mail that users use to sign in.": "Atribut LDAP yang dipetakan ke mel yang digunakan pengguna untuk log masuk.", "The LDAP attribute that maps to the username that users use to sign in.": "Atribut LDAP yang dipetakan ke nama pengguna yang digunakan pengguna untuk log masuk.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Papan kedudukan kini dalam versi beta, dan kami mungkin melaraskan pengiraan penarafan apabila kami menyempurnakan algoritma.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Saiz fail maksimum dalam MB. Jika saiz fail melebihi had ini, fail tidak akan dimuat naik.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Jumlah maksimum fail yang boleh digunakan sekaligus dalam chat. Jika bilangan fail melebihi had ini, fail tidak akan dimuat naik.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Format output untuk teks. Boleh menjadi 'json', 'markdown', atau 'html'. Lalai kepada 'markdown'.", @@ -2075,6 +2234,7 @@ "This folder is empty": "Folder ini kosong", "This is a default user permission and will remain enabled.": "Ini ialah kebenaran pengguna lalai dan akan tetap didayakan.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Ini adalah ciri percubaan, ia mungkin tidak berfungsi seperti yang diharapkan dan tertakluk kepada perubahan pada bila-bila masa.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Model ini tidak tersedia secara terbuka. Sila pilih model lain.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Pilihan ini mengawal berapa lama model akan tetap dimuatkan ke dalam ingatan selepas permintaan (lalai: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Pilihan ini mengawal berapa banyak token yang disimpan apabila menyegarkan konteks. Sebagai contoh, jika ditetapkan kepada 2, 2 token terakhir konteks perbualan akan dikekalkan. Memelihara konteks boleh membantu mengekalkan kesinambungan perbualan, tetapi ia mungkin mengurangkan keupayaan untuk bertindak balas terhadap topik baru.", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "Untuk mengetahui lebih lanjut tentang titik akhir yang tersedia, lawati dokumentasi kami.", "To select skills here, add them to the \"Skills\" workspace first.": "Untuk memilih kemahiran di sini, tambahkannya ke ruang kerja \"Skills\" terlebih dahulu.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Untuk memilih kit alatan di sini, tambahkannya pada ruang kerja \"Tools\" dahulu.", - "Toast notifications for new updates": "Pemberitahuan Toast untuk kemas kini baharu", + "Toast Notifications for New Updates": "Pemberitahuan Toast untuk kemas kini baharu", "Today": "Hari Ini", "Today at": "Hari ini pada", "Today at {{LOCALIZED_TIME}}": "Hari ini pada {{LOCALIZED_TIME}}", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "Togol sama ada sambungan semasa aktif.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Kiraan token adalah anggaran dan mungkin tidak mencerminkan penggunaan API sebenar", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "token", "Tokens": "Token", "Too verbose": "Terlalu panjang lebar", @@ -2177,14 +2339,19 @@ "Unpin": "Nyahsematkan", "Unpin from Sidebar": "Nyahsemat daripada Bar Sisi", "Unravel secrets": "Ungkap Rahsia", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Batalkan Perkongsian Perbualan", "Unsupported file type.": "Jenis fail tidak disokong.", "Untagged": "Tanpa Tag", "Untitled": "Tanpa Tajuk", "Update": "Kemas Kini", "Update and Copy Link": "Kemas Kini dan Salin Pautan", + "Update Email": "", "Update for the latest features and improvements.": "Kemas kini untuk ciri dan penambahbaikan terbaru.", + "Update Name": "", "Update password": "Kemas Kini Kata Laluan", + "Update Picture": "", "Update your status": "Kemas kini status anda", "Updated": "Dikemas kini", "Updated at": "Dikemas kini pada", @@ -2211,13 +2378,18 @@ "Use": "Gunakan", "Use '#' in the prompt input to load and include your knowledge.": "Gunakan '#' dalam input arahan untuk memuatkan dan memasukkan pengetahuan anda.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Gunakan titik akhir /v1/chat/completions daripada /v1/audio/transcriptions untuk ketepatan yang berpotensi lebih baik.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Gunakan Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Gunakan kumpulan untuk menguruskan pengguna anda dan menetapkan kebenaran.", "Use LLM": "Gunakan LLM", "Use no proxy to fetch page contents.": "Jangan gunakan proksi untuk mengambil kandungan halaman.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Gunakan proksi yang ditetapkan oleh pembolehubah persekitaran http_proxy dan https_proxy untuk mengambil kandungan halaman.", + "Use Web Search?": "", "user": "pengguna", "User": "Pengguna", + "User Access": "", "User Activity": "Aktiviti Pengguna", "User Groups": "Kumpulan Pengguna", "User location successfully retrieved.": "Lokasi pengguna berjaya diambil.", @@ -2227,6 +2399,7 @@ "User Status": "Status Pengguna", "User Webhooks": "Webhook Pengguna", "Username": "Nama Pengguna", + "Username Claim": "", "users": "pengguna", "Users": "Pengguna", "Uses DefaultAzureCredential to authenticate": "Menggunakan DefaultAzureCredential untuk pengesahan", @@ -2240,6 +2413,7 @@ "Valves updated": "Valves dikemas kini", "Valves updated successfully": "Valves berjaya dikemas kini", "variable": "pembolehubah", + "Vector Field": "", "Verify Connection": "Sahkan Sambungan", "Verify SSL Certificate": "Sahkan Sijil SSL", "Version": "Versi", @@ -2269,11 +2443,14 @@ "Web API": "API Web", "Web Loader Engine": "Enjin Pemuatan Web", "Web Search": "Carian Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Enjin Carian Web", "Web Search in Chat": "Carian Web dalam Perbualan", "Web Search Query Generation": "Penjanaan Pertanyaan Carian Web", + "Webhook deleted": "", "Webhook Name": "Nama Webhook", - "Webhook URL": "URL Webhook", + "Webhook saved": "", "Webhooks": "Webhook", "Webpage URLs": "URL Halaman Web", "WebUI Settings": "Tetapan WebUI", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "Kunci API Pencarian Web Yandex", "Yandex Web Search config": "Konfigurasi Pencarian Web Yandex", "Yandex Web Search URL": "URL Pencarian Web Yandex", + "Yearly": "", "Yesterday": "Semalam", "Yesterday at {{LOCALIZED_TIME}}": "Semalam pada {{LOCALIZED_TIME}}", "You": "Anda", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "Pelayar anda tidak menyokong tag video.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Seluruh sumbangan anda akan dihantar terus kepada pembangun 'plugin'; Open WebUI tidak mengambil sebarang peratusan keuntungan daripadanya. Walau bagaimanapun, platform pembiayaan yang dipilih mungkin mempunyai caj tersendiri.", "Your message text or inputs": "Teks atau input mesej anda", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Statistik penggunaan anda telah berjaya disegerakkan.", "YouTube": "YouTube", "Youtube Language": "Bahasa YouTube", diff --git a/src/lib/i18n/locales/nb-NO/translation.json b/src/lib/i18n/locales/nb-NO/translation.json index 4c540d4a48..64d84c4a4e 100644 --- a/src/lib/i18n/locales/nb-NO/translation.json +++ b/src/lib/i18n/locales/nb-NO/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} sine samtaler", "{{webUIName}} Backend Required": "Backend til {{webUIName}} kreves", "*Prompt node ID(s) are required for image generation": "Node-ID-er for ledetekst kreves for generering av bilder", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Tilgangskontroll", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Tilgjengelig for alle brukere", "Account": "Konto", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Legg til", "Add a model ID": "Legg til en modell-ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Legg til en kort beskrivelse av hva denne modellen gjør", "Add a tag": "Legg til en tag", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Legg til filer", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Legg til bruker", "Add User Group": "Legg til brukergruppe", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Administrator", "Admin Contact Email": "", "Admin Panel": "Administratorpanel", + "Admin Roles": "", "Admin Settings": "Administratorinnstillinger", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorer har alltid tilgang til alle verktøy. Brukere må få tildelt verktøy per modell i arbeidsområdet.", "Advanced": "", "Advanced Parameters": "Avanserte parametere", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Alle modeller er slettet", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Tillatt chatkontroller", "Allow Chat Delete": "Tillat sletting av chatter", "Allow Chat Edit": "Tillat redigering av chatter", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Aktiver stedstjenester", "Allow Voice Interruption in Call": "Muliggjør taleavbrytelse i samtaler", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Tillatte endepunkter", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Har du allerede en konto?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Alltid", @@ -173,6 +197,7 @@ "API Base URL": "Absolutt API-URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API-nøkkel", + "API Key / Token": "", "API Key created.": "API-nøkkel opprettet.", "API Key Endpoint Restrictions": "Begrensninger for API-nøkkelens endepunkt", "API keys": "API-nøkler", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Er du sikker på at du vil slette denne meldingen?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Er du sikker på at du vil oppheve arkiveringen av alle arkiverte chatter?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena-modeller", "Artifacts": "Artifakter", "Asc": "", "Ask": "", "Ask a question": "Still et spørsmål", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Lyd", "August": "august", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Godkjenn", "Authentication": "Godkjenning", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Kopier svar automatisk til utklippstavlen", - "Auto-playback response": "Spill av svar automatisk", + "Auto-Create Groups": "", + "Auto-Playback Response": "Spill av svar automatisk", "Autocomplete Generation": "Generering av autofullføring", "Autocomplete Generation Input Max Length": "Maks lengde for autofullføring av inndata", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "API-Autentiseringsstreng for AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Absolutt URL for AUTOMATIC1111", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "tilgjengelige brukere", + "Available variables": "", "available!": "tilgjengelig!", "Away": "Borte", "Awful": "Fælt", @@ -258,16 +295,17 @@ "Bad Response": "Dårlig svar", "Banners": "Bannere", "Base Model (From)": "Grunnmodell (fra)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "før", "Being lazy": "Er lat", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Endepunkt for Bing Search V7", "Bing Search V7 Subscription Key": "Abonnementsnøkkel for Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "API-nøkkel for Bocha Search", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Retning på chat", + "Chat Direction": "Retning på chat", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Samling", + "Collection Field": "", "Collections": "", "Color": "Farge", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI-arbeidsflyt", "ComfyUI Workflow Nodes": "ComfyUI-arbeidsflytnoder", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Kommando", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Fullføringer", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Koble til egne OpenAI-kompatible API-endepunkter", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Kontakt administrator for å få tilgang til WebUI", "Content": "Innhold", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Fortsett svar", "Continue with {{provider}}": "Fortsett med {{provider}}", "Continue with Email": "Fortsett med e-post", @@ -493,6 +543,7 @@ "Create new secret key": "Lag ny hemmelig nøkkel", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Opprettet", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Standard modus fungerer med et bredere utvalg av modeller ved at verktøyene kalles én gang før kjøring. Opprinnelig modus utnytter modellens innebygde funksjoner for verktøykalling, men krever at modellen i seg selv støtter denne funksjonen.", "Default Model": "Standard modell", "Default model updated": "Standard modell oppdatert", "Default permissions": "Standard tillatelser", @@ -542,6 +593,7 @@ "Default to ALL": "Velg ALL som standard", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Standard brukerrolle", + "Default webhook": "", "Defaults": "", "Delete": "Slett", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Deaktivert", "Disconnect OAuth": "", "Discover a function": "Oppdag en funksjon", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Oppdag, last ned og utforsk forhåndsinnstillinger for modeller", "Discussion channel where access is based on groups and permissions": "", "Display": "Visning", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Vis emoji i samtale", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Vis brukernavnet ditt i stedet for Du i chatten", + "Display the Username Instead of You in the Chat": "Vis brukernavnet ditt i stedet for Du i chatten", "Displays citations in the response": "Vis kildehenvisninger i svaret", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Bli kjent med kunnskap", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Intelligens i dokumenter", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Rediger standard tillatelser", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Rediger minne", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Rediger bruker", "Edit User Group": "Rediger brukergruppe", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "E-postadresse", + "Email Claim": "", "Embark on adventures": "Kom med på eventyr", "Embedding": "", "Embedding Batch Size": "Batch-størrelse for innbygging", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Motor for innbygging av modeller", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "Aktiver kodetolker", "Enable Community Sharing": "Aktiver deling i fellesskap", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Aktiver Memory Locking (mlock) for å forhindre at modelldata byttes ut av RAM. Dette alternativet låser modellens arbeidssett med sider i RAM-minnet, slik at de ikke byttes ut til disk. Dette kan bidra til å opprettholde ytelsen ved å unngå sidefeil og sikre rask datatilgang.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Aktiver Memory Mapping (mmap) for å laste inn modelldata. Med dette alternativet kan systemet bruke disklagring som en utvidelse av RAM ved å behandle diskfiler som om de befant seg i RAM. Dette kan forbedre modellens ytelse ved å gi raskere datatilgang. Det er imidlertid ikke sikkert at det fungerer som det skal på alle systemer, og det kan kreve mye diskplass.", "Enable Message Queue": "", "Enable Message Rating": "Aktivert vurdering av meldinger", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Aktiver nye registreringer", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Aktivert", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Sørg for at CSV-filen din inkluderer fire kolonner i denne rekkefølgen: Navn, E-post, Passord, Rolle.", "Enter {{role}} message here": "Skriv inn {{role}} melding her", - "Enter a detail about yourself for your LLMs to recall": "Skriv inn en detalj om deg selv som språkmodellene dine kan huske", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Angi Chunk-overlapp", "Enter Chunk Size": "Angi Chunk-størrelse", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Angi URL for Jupyter", "Enter Kagi Search API Key": "Angi API-nøkkel for Kagi Search", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Angi språkkoder", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Angi proxy-URL (f.eks. https://bruker:passord@host:port)", "Enter reasoning effort": "Angi hvor mye resonneringsinnsats som skal til", + "Enter Redirect URI": "", "Enter Score": "Angi poengsum", "Enter SearchApi API Key": "Angi API-nøkkel for SearchApi", "Enter SearchApi Engine": "Angi motor for SearchApi", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Angi API-nøkkel for SerpApi", "Enter SerpApi Engine": "Angi motor for SerpApi", "Enter Serper API Key": "Angi API-nøkkel for Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Angi API-nøkkel for Serply", "Enter Serpstack API Key": "Angi API-nøkkel for Serpstack", "Enter server host": "Angi server host", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Angi server-URL for Tika", "Enter timeout in seconds": "Angi tidsavbrudd i sekunder", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Angi Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Angi URL (f.eks. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Vurderinger", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "API-nøkkel for Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Eksempel: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Eksempel: ALL", "Example: mail": "Eksempel: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Eksporter til CSV", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Kan ikke opprette en API-nøkkel.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Kan ikke hente modeller", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Kan ikke lese utklippstavlens innhold", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Kan ikke lagre konfigurasjonen av modeller", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Kan ikke oppdatere innstillinger", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Kan ikke laste opp filen.", "Features": "Funksjoner", "Features Permissions": "Tillatelser for funksjoner", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Filen er lastet opp", "Filename": "", "Files": "Filer", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filteret er nå globalt deaktivert", "Filter is now globally enabled": "Filteret er nå globalt aktivert", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funksjonen er nå aktivert globalt", "Function Name": "Funksjonens navn", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funksjonen er oppdatert", "Functions": "Funksjoner", "Functions allow arbitrary code execution.": "Funksjoner tillater vilkårlig kodekjøring.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Gruppe opprettet", "Group deleted successfully": "Gruppe slettet", "Group Description": "Beskrivelse av gruppe", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Haptisk tilbakemelding", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Viktig oppdatering", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Nøkkel", "Key is required": "", - "Keyboard shortcuts": "Hurtigtaster", "Keyboard Shortcuts": "", "Knowledge": "Kunnskap", "Knowledge Access": "Tilgang til kunnskap", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Kunnskap oppdatert", "Kokoro.js (Browser)": "Kokoro.js (nettleser)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Siste svar", "LDAP": "LDAP", - "LDAP server updated": "LDAP-server oppdatert", "Leaderboard": "Ledertavle", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Lisens", + "Lifecycle JSON": "", "Lift List": "", "Light": "Lys", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Tilgang til lokasjon er ikke tillatt", "Lost": "Tapt", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Laget av OpenWebUI-fellesskapet", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Behandle pipelines", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "mars", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Minne tømt", "Memory deleted successfully": "Minne slettet", "Memory updated successfully": "Minne oppdatert", + "Merge Accounts by Email": "", "Merge Responses": "Flette svar", "Merged Response": "Sammenslått svar", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meldinger du sender etter at du har opprettet lenken, blir ikke delt. Brukere med URL-en vil kunne se den delte chatten.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "API-nøekkel for Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Mer", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Gi kunnskapsbasen et navn", "Name, prompt, and model are required": "", "Native": "Opprinnelig", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Ingen avstand tilgjengelig", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ingen fil valgt", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Finner ingen resultater", "No results found": "Finner ingen resultater", "No search query generated": "Ingen søkespørringer er generert", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Ingen", + "Not configured": "", "Not factually correct": "Uriktig informasjon", "Not helpful": "Ikke nyttig", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Varsler", "November": "november", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth-ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "oktober", "Off": "Av", "Okay, Let's Go!": "OK, kjør på!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED mørk", "Ollama": "Ollama", "Ollama API": "Ollama-API", "Ollama API settings updated": "API-innstillinger for Ollama er oppdatert", "Ollama Cloud API Key": "", "Ollama Version": "Ollama-versjon", + "Omit": "", "On": "Aktivert", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Passord", "Passwords do not match.": "", "Paste Large Text as File": "Lim inn mye tekst som fil", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF-dokument (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "avventer", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Tilgang avslått ved bruk av medieenheter", "Permission denied when accessing microphone": "Tilgang avslått ved bruk av mikrofonen", "Permission denied when accessing microphone: {{error}}": "Tilgang avslått ved bruk av mikrofonen: {{error}}", "Permissions": "Tillatelser", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Tilpassing", + "Picture Claim": "", "Pin": "Fest", "Pin to Sidebar": "", "Pinned": "Festet", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Fyll i alle felter", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Velg en modeller først.", "Please select a model.": "Velg en modell.", "Please select a reason": "Velg en årsak", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Positiv holdning", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Hent {{searchValue}} fra Ollama.com", "Pull a model from Ollama.com": "Hent en modell fra Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Les", "Read Aloud": "Les høyt", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Resonneringsinnsats", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Ta opp tale", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Omdirigerer deg til OpenWebUI-fellesskapet", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Omtal deg selv som \"Bruker\" (f.eks. \"Bruker lærer spansk\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Avvist når det ikke burde ha blitt det", "Regenerate": "Generer på nytt", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Sorter modeller på nytt", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Svar i tråd", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Omrangeringsmodell", + "Research Knowledge": "", "Reset": "Tilbakestill", "Reset All Models": "Tilbakestill alle modeller", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Tilbakestill bilde", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Tilbakestill opplastingskatalog", "Reset Vector Storage/Knowledge": "Tilbakestill Vector-lagring/kunnskap", "Reset view": "Tilbakestill visning", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Rik tekstinndata for chat", "Role": "Rolle", + "Roles Claim": "", "RTL": "RTL", "Run": "Kjør", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Lagring av chattelogger direkte til nettleserens lagringsområde støttes ikke lenger. Ta et øyeblikk til å laste ned og slette chatteloggende dine ved å klikke på knappen nedenfor. Ikke bekymre deg, du kan enkelt importere chatteloggene dine til backend på nytt via", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Søk", "Search a model": "Søk etter en modell", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Søk etter chatter", "Search Collection": "Søk etter samling", "Search Files": "", + "Search filters": "", "Search Filters": "Søk etter filtre", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Søk etter modeller", "Search Notes": "", "Search options": "Søk etter alternativer", + "Search or add pattern": "", "Search Prompts": "Søk etter ledetekster", "Search Result Count": "Antall søkeresultater", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Søk på Internett", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Søkeverktøy", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "API-nøkkel for SearchApi", "SearchApi Engine": "Motor for SearchApi", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Velg en grunnmodell", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Velg en motor", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Send", "Send a Message": "Send en melding", + "Send events for": "", "Send message": "Send melding", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Sender `stream_options: { include_usage: true }` i forespørselen.\nStøttede leverandører returnerer informasjon i svaret om bruk av token når denne parameteren er angitt.", "September": "september", "SerpApi API Key": "Angi API-nøkkel for SerpApi", "SerpApi Engine": "Motor for SerpApi", "Serper API Key": "API-nøkkel for Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "API-nøkkel for Serply", "Serpstack API Key": "API-nøkkel for Serpstack", "Server connection failed": "", "Server connection verified": "Servertilkobling bekreftet", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Angi som standard", "Set as Production": "", "Set embedding model": "Angi innbyggingsmodell", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Del med OpenWebUI-fellesskapet", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Vis", - "Show \"What's New\" modal on login": "Vis \"Hva er nytt\"-modal ved innlogging", + "Show \"What's New\" Modal on Login": "Vis \"Hva er nytt\"-modal ved innlogging", "Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i ventende kontovisning", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Kilde", + "Specific users or groups": "", "Speech Playback Speed": "Hastighet på avspilling av tale", "Speech recognition error: {{error}}": "Feil ved talegjenkjenning: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT-innstillinger", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "System", + "System events only": "", "System Instructions": "Systeminstruksjoner", "System Prompt": "Systemledetekst", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "Genering av etiketter", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Oppdeling av tekst", "Text-to-Speech": "", "Text-to-Speech Engine": "Tekst-til-tale-motor", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP-attributtet som tilsvarer e-posten som brukerne bruker for å logge på.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP-attributtet som tilsvarer brukernavnet som brukerne bruker for å logge på.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Ledertavlen er for øyeblikket i betaversjon, og vi kommer kanskje til å justere beregningene etter hvert som vi forbedrer algoritmen.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Den maksimale filstørrelsen i MB. Hvis en filstørrelse overskrider denne grensen, blir ikke filen lastet opp.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maksimalt antall filer som kan brukes samtidig i chatten. Hvis antallet filer overskrider denne grensen, blir de ikke lastet opp.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dette er en eksperimentell funksjon. Det er mulig den ikke fungerer som forventet, og den kan endres når som helst.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Hvis du vil finne ut mer om tilgjengelige endepunkter, kan du gå til dokumentasjonen vår.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Hvis du vil velge verktøysett her, må du først legge dem til i arbeidsområdet \"Verktøy\".", - "Toast notifications for new updates": "Hurtigmelding-notifikasjon for nye oppdateringer", + "Toast Notifications for New Updates": "Hurtigmelding-notifikasjon for nye oppdateringer", "Today": "I dag", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "For omfattende", @@ -2184,14 +2350,19 @@ "Unpin": "Løsne", "Unpin from Sidebar": "", "Unravel secrets": "Avslør hemmeligheter", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Ikke merket", "Untitled": "", "Update": "Oppdater", "Update and Copy Link": "Oppdater og kopier lenke", + "Update Email": "", "Update for the latest features and improvements.": "Oppdater for å få siste funksjoner og forbedringer.", + "Update Name": "", "Update password": "Oppdater passord", + "Update Picture": "", "Update your status": "", "Updated": "Oppdatert", "Updated at": "Oppdatert", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Bruk # i ledetekstens inntastingsfelt for å laste inn og inkludere kunnskapene dine.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "bruker", "User": "Bruker", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Brukerens lokasjon hentet", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "Brukernavn", + "Username Claim": "", "users": "", "Users": "Brukere", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Ventiler oppdatert", "Valves updated successfully": "Ventilene er oppdatert", "variable": "variabel", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Versjon", @@ -2276,11 +2454,14 @@ "Web API": "Web-API", "Web Loader Engine": "", "Web Search": "Nettsøk", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Nettsøkmotor", "Web Search in Chat": "Nettsøk i chat", "Web Search Query Generation": "Genering av spørringer for nettsøk", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Innstillinger for WebUI", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "I går", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Du", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hele beløpet går uavkortet til utvikleren av tillegget. Open WebUI mottar ikke deler av beløpet. Den valgte betalingsplattformen kan ha gebyrer.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/nl-NL/translation.json b/src/lib/i18n/locales/nl-NL/translation.json index 1290a617d2..40b3a283bd 100644 --- a/src/lib/i18n/locales/nl-NL/translation.json +++ b/src/lib/i18n/locales/nl-NL/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} bestanden", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} verborgen regels", "{{COUNT}} members": "{{COUNT}} leden", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "{{count}} geselecteerd", "{{count}} selected_other": "{{count}} geselecteerd", "{{COUNT}} Sources": "{{COUNT}} bronnen", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} woorden", "{{COUNT}}d_time_ago": "{{COUNT}}d geleden", "{{COUNT}}h_time_ago": "{{COUNT}}u geleden", "{{COUNT}}m_time_ago": "{{COUNT}}m geleden", "{{COUNT}}w_time_ago": "{{COUNT}}w geleden", "{{COUNT}}y_time_ago": "{{COUNT}}j geleden", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} om {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Download van {{model}} is geannuleerd", "{{modelName}} profile image": "Profielafbeelding van {{modelName}}", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "Chats van {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Backend verplicht", "*Prompt node ID(s) are required for image generation": "*Prompt node ID(s) zijn vereist voor het genereren van afbeeldingen", + "1 group": "", "1 hour before": "1 uur voor", "1 Source": "1 bron", + "1 user": "", "10 minutes before": "10 minuten voor", "15 minutes before": "15 minuten voor", "1m_time_ago": "1m geleden", @@ -57,6 +67,7 @@ "Access Control": "Toegangsbeheer", "Access Grants": "Toegangsrechten", "Access List": "Toegangslijst", + "Access prohibited": "", "Access updated": "Toegang bijgewerkt", "Accessible to all users": "Toegankelijk voor alle gebruikers", "Account": "Account", @@ -72,6 +83,7 @@ "Activity": "Activiteit", "Add": "Toevoegen", "Add a model ID": "Voeg een model-ID toe", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Voeg een korte beschrijving toe over wat dit model doet", "Add a tag": "Voeg een tag toe", "Add a tag...": "Voeg een tag toe...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Aangepaste prompt toevoegen", "Add description": "Voeg beschrijving toe", "Add Details": "Details toevoegen", + "Add durable context for future chats": "", "Add Files": "Voeg bestanden toe", "Add Image": "Afbeelding toevoegen", + "Add Knowledge Connection": "", "Add location": "Voeg locatie toe", "Add Member": "Lid toevoegen", "Add Members": "Leden toevoegen", @@ -100,6 +114,7 @@ "Add to favorites": "Aan favorieten toevoegen", "Add User": "Voeg gebruiker toe", "Add User Group": "Voeg gebruikersgroep toe", + "Add webhook": "", "Add webpage": "Webpagina toevoegen", "Add your Open Terminal URL and API key in Settings → Integrations.": "Voeg je Open Terminal-URL en API-sleutel toe in Instellingen -> Integraties.", "Additional Config": "Extra configuratie", @@ -112,7 +127,9 @@ "Admin": "Beheerder", "Admin Contact Email": "E-mailadres van beheerder", "Admin Panel": "Beheerderspaneel", + "Admin Roles": "", "Admin Settings": "Beheerdersinstellingen", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Beheerders hebben altijd toegang tot alle gereedschappen; gebruikers moeten gereedschap toegewezen krijgen per model in de werkruimte.", "Advanced": "Geavanceerd", "Advanced Parameters": "Geavanceerde parameters", @@ -123,16 +140,21 @@ "All": "Alle", "All chats have been unarchived.": "Alle chats zijn gedearchiveerd.", "All day": "De hele dag", + "All events": "", "All models are now hidden": "Alle modellen zijn nu verborgen", "All models are now visible": "Alle modellen zijn nu zichtbaar", "All models deleted successfully": "Alle modellen zijn succesvol verwijderd", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Altijd", "All Users": "Alle gebruikers", + "All users and system events": "", "Allow Call": "Bellen toestaan", "Allow Chat Controls": "Chatbesturing toestaan", "Allow Chat Delete": "Chatverwijdering toestaan", "Allow Chat Edit": "Chatwijziging toestaan", "Allow Chat Export": "Chat exporteren toestaan", + "Allow Chat Import": "", "Allow Chat Params": "Chatparameters toestaan", "Allow Chat Share": "Chat delen toestaan", "Allow Chat System Prompt": "Systeemprompt voor chat toestaan", @@ -152,9 +174,11 @@ "Allow User Location": "Gebruikerslocatie toestaan", "Allow Voice Interruption in Call": "Stemonderbreking tijdens gesprek toestaan", "Allow Web Upload": "Webupload toestaan", + "Allowed Domains": "", "Allowed Endpoints": "Endpoints toestaan", "Allowed File Extensions": "Toegestane bestandsextensies", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Toegestane bestandsextensies voor uploaden. Scheid meerdere extensies met komma's. Laat leeg voor alle bestandstypen.", + "Allowed Roles": "", "Already have an account?": "Heb je al een account?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatief voor top_p, en streeft naar een evenwicht tussen kwaliteit en variatie. De parameter p vertegenwoordigt de minimumwaarschijnlijkheid dat een token in aanmerking wordt genomen, in verhouding tot de waarschijnlijkheid van het meest waarschijnlijke token. Bijvoorbeeld, met p=0.05 en het meest waarschijnlijke token met een waarschijnlijkheid van 0.9, worden logits met een waarde kleiner dan 0.045 uitgefilterd.", "Always": "Altijd", @@ -173,6 +197,7 @@ "API Base URL": "API Base URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API base URL voor de Datalab Marker-service. Standaard: https://www.datalab.to/api/v1/marker", "API Key": "API-sleutel", + "API Key / Token": "", "API Key created.": "API-sleutel aangemaakt.", "API Key Endpoint Restrictions": "API-sleutel endpoint-beperkingen", "API keys": "API-sleutels", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Weet je zeker dat je dit geheugen wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.", "Are you sure you want to delete this message?": "Weet je zeker dat je dit bericht wil verwijderen?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Weet je zeker dat je deze versie wilt verwijderen? Onderliggende versies worden opnieuw gekoppeld aan de bovenliggende versie.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Weet je zeker dat je dit wilt verwijderen?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Weet je zeker dat je alle gearchiveerde chats wil onarchiveren?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arenamodellen", "Artifacts": "Artefacten", "Asc": "Oplopend", "Ask": "Vraag", "Ask a question": "Stel een vraag", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "Asynchrone embeddingverwerking", "At time of event": "Op het moment van de gebeurtenis", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "augustus", "Auth": "Authenticatie", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Authenticeer", "Authentication": "Authenticatie", "Auto": "Automatisch", "Auto (Random)": "Auto (Willekeurig)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Antwoord automatisch kopiëren naar klembord", - "Auto-playback response": "Automatisch afspelen van antwoord", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatisch afspelen van antwoord", "Autocomplete Generation": "Automatische aanvullingsgeneratie", "Autocomplete Generation Input Max Length": "Maximale invoerlengte voor automatische aanvullingsgeneratie", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Automatic1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Basis-URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Beschikbare tools", "available users": "beschikbare gebruikers", + "Available variables": "", "available!": "beschikbaar!", "Away": "Afwezig", "Awful": "Verschrikkelijk", @@ -258,16 +295,17 @@ "Bad Response": "Ongeldig antwoord", "Banners": "Banners", "Base Model (From)": "Basismodel (Vanaf)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Cache voor basismodellen versnelt de toegang door basismodellen alleen op te halen bij het opstarten of bij het opslaan van instellingen. Dit is sneller, maar toont mogelijk geen recente wijzigingen in basismodellen.", "Bearer": "Bearer", "before": "voor", "Being lazy": "Lui zijn", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 Endpoint", "Bing Search V7 Subscription Key": "Bing Search V7 Subscription Key", "Bio": "Bio", "Birth Date": "Geboortedatum", + "Blocked Groups": "", "BM25 Weight": "BM25-gewicht", "Bocha Search API Key": "Bocha Search API-sleutel", "Bold": "Vet", @@ -324,7 +362,7 @@ "Chat Completions": "Chataanvullingen", "Chat Conversation": "Chatgesprek", "Chat deleted.": "", - "Chat direction": "Chatrichting", + "Chat Direction": "Chatrichting", "Chat exported successfully": "Chat succesvol geexporteerd", "Chat History": "Chatgeschiedenis", "Chat ID": "Chat-ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Samenwerkingskanaal waar mensen als leden deelnemen", "Collapse": "Inklappen", "Collection": "Verzameling", + "Collection Field": "", "Collections": "Verzamelingen", "Color": "Kleur", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI workflow", "ComfyUI Workflow Nodes": "ComfyUI workflowknopen", "Comma separated Node Ids (e.g. 1 or 1,2)": "Door komma's gescheiden node-ID's (bijv. 1 of 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "commando", "Command": "Commando", "Comment": "Reactie", "Commit Message": "Commitbericht", "Community Reviews": "Communitybeoordelingen", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Voltooiingen", "Compress Images in Channels": "Afbeeldingen in kanalen comprimeren", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Verbind met Open Terminal-instanties. Alle gebruikers krijgen via deze servers toegang tot bestandsverkenning en terminaltools.", "Connect to your own OpenAI compatible API endpoints.": "Verbind met je eigen OpenAI-compatibele API-endpoints", "Connect to your own OpenAPI compatible external tool servers.": "Verbind met je eigen OpenAPI-compatibele externe gereedschapservers", + "Connected": "", "Connected ({{type}})": "Verbonden ({{type}})", "Connection failed": "Connectie mislukt", "Connection lost. Reconnecting...": "Verbinding verbroken. Opnieuw verbinden...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Neem contact op met de beheerder voor WebUI-toegang", "Content": "Inhoud", "Content Extraction Engine": "Inhoudsextractie engine", + "Content Field": "", "Content lengths (character counts only)": "Inhoudslengtes (alleen tekentellingen)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Doorgaan met antwoord", "Continue with {{provider}}": "Ga verder met {{provider}}", "Continue with Email": "Ga door met E-mail", @@ -493,6 +543,7 @@ "Create new secret key": "Maak nieuwe geheime sleutel", "Create note": "Notitie maken", "Create Note": "Maak notitie", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Maak geplande prompts die automatisch op terugkerende basis worden uitgevoerd.", "Create your first note by clicking on the plus button below.": "Maak je eerste notitie door op de plusknop hieronder te klikken.", "Created at": "Gemaakt op", @@ -510,6 +561,7 @@ "Custom Gender": "Aangepast geslacht", "Custom Parameter Name": "Naam van aangepaste parameter", "Custom Parameter Value": "Waarde van aangepaste parameter", + "Custom range": "", "Daily": "Dagelijks", "Daily Messages": "Dagelijkse berichten", "Danger Zone": "Gevarenzone", @@ -532,7 +584,6 @@ "Default Features": "Standaardfuncties", "Default Filters": "Standaardfilters", "Default Group": "Standaardgroep", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "De standaardmodus werkt met een breder scala aan modellen door gereedschappen één keer aan te roepen voordat ze worden uitgevoerd. De native modus maakt gebruik van de ingebouwde mogelijkheden van het model om gereedschappen aan te roepen, maar vereist dat het model deze functie inherent ondersteunt.", "Default Model": "Standaardmodel", "Default model updated": "Standaardmodel bijgewerkt", "Default permissions": "Standaardrechten", @@ -542,6 +593,7 @@ "Default to ALL": "Standaard op ALL", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Standaard gesegmenteerd ophalen voor gerichte en relevante inhoudsextractie, dit wordt aanbevolen voor de meeste gevallen.", "Default User Role": "Standaard gebruikersrol", + "Default webhook": "", "Defaults": "Standaardwaarden", "Delete": "Verwijderen", "Delete {{name}}": "{{name}} verwijderen", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Code-interpretatie uitschakelen", "Disable Image Extraction": "Afbeeldingsextractie uitschakelen", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Schakel afbeeldingsextractie uit de PDF uit. Als Use LLM is ingeschakeld, krijgen afbeeldingen automatisch beschrijvingen. Standaard is False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Uitgeschakeld", "Disconnect OAuth": "", "Discover a function": "Ontdek een functie", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Ontdek, download en verken model presets", "Discussion channel where access is based on groups and permissions": "Discussiekanaal waarbij toegang is gebaseerd op groepen en machtigingen", "Display": "Toon", - "Display chat title in tab": "Chattitel weergeven in tabblad", + "Display Chat Title in Tab": "Chattitel weergeven in tabblad", "Display Emoji in Call": "Emoji tonen tijdens gesprek", "Display Multi-model Responses in Tabs": "Multimodelantwoorden in tabbladen weergeven", - "Display the username instead of You in the Chat": "Toon de gebruikersnaam in plaats van Jij in de Chat", + "Display the Username Instead of You in the Chat": "Toon de gebruikersnaam in plaats van Jij in de Chat", "Displays citations in the response": "Toon citaten in het antwoord", "Displays status updates (e.g., web search progress) in the response": "Toont statusupdates (bijv. voortgang van webzoekopdrachten) in het antwoord", "Dive into knowledge": "Verken kennis", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling-parameters", "Docling Server URL required.": "Docling server-URL benodigd", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Document Intelligence-endpoint is vereist.", "Document Intelligence Model": "Document Intelligence-model", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Bewerk standaardrechten", "Edit Folder": "Map bewerken", "Edit Image": "Afbeelding bewerken", + "Edit Knowledge Connection": "", "Edit Last Message": "Laatste bericht bewerken", "Edit Memory": "Bewerk geheugen", "Edit Prompt": "Prompt bewerken", "Edit Terminal Connection": "Terminalverbinding bewerken", "Edit User": "Wijzig gebruiker", "Edit User Group": "Bewerk gebruikergroep", + "Edit webhook": "", "Edit workflow.json content": "workflow.json-inhoud bewerken", "edited": "bewerkt", "Edited": "Bewerkt", @@ -699,6 +756,7 @@ "Eject model": "Model uitwerpen", "ElevenLabs": "ElevenLabs", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "Ga op avonturen", "Embedding": "Embedding", "Embedding Batch Size": "Embedding batchgrootte", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Embedding Model Engine", "Emoji": "", "Emojis": "Emojis", + "Empty": "", "Empty message": "Leeg bericht", "Enable All": "Alles inschakelen", "Enable API Keys": "API-sleutels inschakelen", @@ -714,22 +773,27 @@ "Enable Code Execution": "Code-uitvoer inschakelen", "Enable Code Interpreter": "Code-interpretatie inschakelen", "Enable Community Sharing": "Delen via de community inschakelen", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Schakel Memory Locking (mlock) in om te voorkomen dat modelgegevens uit het RAM worden verwisseld. Deze optie vergrendelt de werkset pagina's van het model in het RAM, zodat ze niet naar de schijf worden uitgewisseld. Dit kan helpen om de prestaties op peil te houden door paginafouten te voorkomen en snelle gegevenstoegang te garanderen.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Schakel Memory Mapping (mmap) in om modelgegevens te laden. Deze optie laat het systeem schijfopslag gebruiken als een uitbreiding van RAM door schijfbestanden te behandelen alsof ze in RAM zitten. Dit kan de prestaties van het model verbeteren door snellere gegevenstoegang mogelijk te maken. Het is echter mogelijk dat deze optie niet op alle systemen correct werkt en een aanzienlijke hoeveelheid schijfruimte in beslag kan nemen.", "Enable Message Queue": "Berichtenwachtrij inschakelen", "Enable Message Rating": "Schakel berichtbeoordeling in", "Enable Mirostat sampling for controlling perplexity.": "Mirostat-sampling in om perplexiteit te controleren inschakelen.", "Enable New Sign Ups": "Schakel nieuwe registraties in", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Schakel de redeneringstags die door het model worden gebruikt in, uit of pas ze aan. \"Ingeschakeld\" gebruikt standaardtags, \"Uitgeschakeld\" zet redeneringstags uit en \"Aangepast\" laat je je eigen begin- en eindtags instellen.", "Enabled": "Ingeschakeld", "End Tag": "Eindtag", + "Endpoint": "", "Endpoint URL": "Endpoint-URL", "Enforce Temporary Chat": "Tijdelijke chat afdwingen", "Enhance": "Verbeteren", "Enrich Hybrid Search Text": "Hybride zoektekst verrijken", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Zorg ervoor dat je CSV-bestand de volgende vier kolommen in deze volgorde bevat: Naam, E-mail, Wachtwoord, Rol.", "Enter {{role}} message here": "Voeg {{role}} bericht hier toe", - "Enter a detail about yourself for your LLMs to recall": "Voer een detail over jezelf in zodat LLM's het kunnen onthouden", "Enter a title for the pending user info overlay. Leave empty for default.": "Voer een titel in voor de overlay met wachtende gebruikersinfo. Laat leeg voor standaard.", "Enter a watermark for the response. Leave empty for none.": "Voer een watermerk in voor het antwoord. Laat leeg voor geen.", "Enter additional headers in JSON format": "Voer extra headers in JSON-indeling in", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Voer doel voor minimale chunkgrootte in", "Enter Chunk Overlap": "Voeg Chunk Overlap toe", "Enter Chunk Size": "Voeg Chunk Size toe", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Voer kommagescheiden \"token:bias_waarde\" paren in (bijv. 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Voer inhoud in voor de overlay met wachtende gebruikersinfo. Laat leeg voor standaard.", "Enter coordinates (e.g. 51.505, -0.09)": "Voer coordinaten in (bijv. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Voer Jupyter-URL in", "Enter Kagi Search API Key": "Voer Kagi Search API-sleutel in", "Enter Key Behavior": "Voer sleutelgedrag in", + "Enter language": "", "Enter language codes": "Voeg taalcodes toe", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Voer MinerU API-sleutel in", "Enter Mistral API Base URL": "Voer Mistral API-basis-URL in", "Enter Mistral API Key": "Voer Mistral API-sleutel in", @@ -804,6 +873,7 @@ "Enter prompt here.": "Voer hier je prompt in.", "Enter proxy URL (e.g. https://user:password@host:port)": "Voer proxy-URL in (bijv. https://gebruiker:wachtwoord@host:port)", "Enter reasoning effort": "Voer redeneerinspanning in", + "Enter Redirect URI": "", "Enter Score": "Voeg score toe", "Enter SearchApi API Key": "Voer SearchApi API-sleutel in", "Enter SearchApi Engine": "Voer SearchApi-Engine in", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Voer SerpApi API-sleutel in", "Enter SerpApi Engine": "Voer SerpApi-engine in", "Enter Serper API Key": "Voer de Serper API-sleutel in", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Voer Serply API-sleutel in", "Enter Serpstack API Key": "Voer de Serpstack API-sleutel in", "Enter server host": "Voer serverhost in", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Voer Tika Server URL in", "Enter timeout in seconds": "Voer time-out in seconden in", "Enter to Send": "Enter om te sturen", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Voeg Top K toe", "Enter Top K Reranker": "Voer Top K-reranker in", "Enter URL (e.g. http://127.0.0.1:7860/)": "Voer URL in (Bijv. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Fout: Een model met de ID '{{modelId}}' bestaat al. Selecteer een andere ID om door te gaan.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Fout: Model-ID mag niet leeg zijn. Voer een geldige ID in om door te gaan.", "Evaluations": "Beoordelingen", + "Event": "", "Event created": "Gebeurtenis aangemaakt", "Event deleted": "Gebeurtenis verwijderd", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Gebeurtenis titel", "Event updated": "Gebeurtenis bijgewerkt", + "Events": "", "Exa API Key": "Exa API-sleutel", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Voorbeeld: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Voorbeeld: ALL", "Example: mail": "Voorbeeld: mail", @@ -905,12 +982,18 @@ "Export Config": "Configuratie exporteren", "Export Models": "Modellen exporteren", "Export Prompts": "Prompts exporteren", + "Export Skills": "", "Export to CSV": "Exporteer naar CSV", "Export Tools": "Tools exporteren", "Export Users": "Gebruikers exporteren", "External": "Extern", + "External connection not found.": "", "External Document Loader URL required.": "Externe documentloader-URL is vereist.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Extern taakmodel", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Externe webloader-API-sleutel", "External Web Loader URL": "Externe webloader-URL", "External Web Search API Key": "Externe webzoek-API-sleutel", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Kan API Key niet aanmaken.", "Failed to delete calendar": "Kalender verwijderen mislukt", "Failed to delete note": "Notitie verwijderen mislukt", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "Afbeelding downloaden mislukt", "Failed to extract content from the file: {{error}}": "Inhoud uit bestand extraheren mislukt: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Kan modellen niet ophalen", "Failed to generate title": "Titel genereren mislukt", "Failed to import models": "Modellen importeren mislukt", + "Failed to load chat": "", "Failed to load chat preview": "Voorvertoning van chat laden mislukt", "Failed to load DOCX file. Please try downloading it instead.": "DOCX-bestand laden mislukt. Probeer het in plaats daarvan te downloaden.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-bestand laden mislukt. Probeer het in plaats daarvan te downloaden.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Chat verplaatsen mislukt", "Failed to process URL: {{url}}": "URL verwerken mislukt: {{url}}", "Failed to read clipboard contents": "Kan klembord inhoud niet lezen", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Lid verwijderen mislukt", "Failed to render diagram": "Diagram renderen mislukt", "Failed to render visualization": "Visualisatie renderen mislukt", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Het is niet gelukt om de modelconfiguratie op te slaan", "Failed to save policy: {{error}}": "Beleid opslaan mislukt: {{error}}", "Failed to save terminal servers": "Terminalservers opslaan mislukt", + "Failed to save webhook": "", "Failed to unshare chat.": "Delen van chat opheffen mislukt.", "Failed to update settings": "Instellingen konden niet worden bijgewerkt.", "Failed to update status": "Status bijwerken mislukt", + "Failed to update webhook": "", "Failed to upload file.": "Bestand kon niet worden geüpload.", "Features": "Functies", "Features Permissions": "Functietoestemmingen", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Bestand succesvol geüpload", "Filename": "Bestandsnaam", "Files": "Bestanden", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filter", "Filter is now globally disabled": "Filter is nu globaal uitgeschakeld", "Filter is now globally enabled": "Filter is nu globaal ingeschakeld", @@ -1009,6 +1099,7 @@ "Folder options": "Mapopties", "Folder updated successfully": "Map succesvol bijgewerkt", "Folders": "Mappen", + "Folders Sharing": "", "Follow up": "Vervolg", "Follow Up Generation": "Vervolggeneratie", "Follow Up Generation Prompt": "Prompt voor vervolggeneratie", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Functie is nu globaal ingeschakeld", "Function Name": "Functienaam", "Function Name Filter List": "Filterlijst voor functienamen", + "Function starter": "", "Function updated successfully": "Functienaam succesvol aangepast", "Functions": "Functies", "Functions allow arbitrary code execution.": "Functies staan willekeurige code-uitvoering toe", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Raster", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Groepskanaal", + "Group Claim": "", "Group created successfully": "Groep succesvol aangemaakt", "Group deleted successfully": "Groep succesvol verwijderd", "Group Description": "Groepsbeschrijving", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Haptische feedback", + "Header variables": "", "Headers": "headers", "Headers must be a valid JSON object": "Headers moeten een geldig JSON-object zijn", "Height": "Hoogte", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID mag geen tekens \":\" of \"|\" bevatten", "ID copied to clipboard": "ID gekopieerd naar klembord", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Inactiviteitstime-out", "iframe Sandbox Allow Forms": "iframe-sandbox formulieren toestaan", "iframe Sandbox Allow Same Origin": "iframe-sandbox zelfde oorsprong toestaan", @@ -1138,6 +1236,7 @@ "Import From Link": "Importeren via link", "Import Models": "Modellen importeren", "Import Prompts": "Prompts importeren", + "Import Skills": "", "Import successful": "Importeren geslaagd", "Import Tools": "Tools importeren", "Important Update": "Belangrijke update", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "In zijbalk houden", "Key": "Sleutel", "Key is required": "Sleutel is vereist", - "Keyboard shortcuts": "Toetsenbordsnelkoppelingen", "Keyboard Shortcuts": "Toetsenbordsnelkoppelingen", "Knowledge": "Kennis", "Knowledge Access": "Kennistoegang", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Kennisnaam", "Knowledge Public Sharing": "Publieke kennisdeling", "Knowledge Sharing": "Kennisdeling", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Kennis succesvol bijgewerkt", "Kokoro.js (Browser)": "Kokoro.js (Browser)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Laatst uitgevoerd", "Last reply": "Laatste antwoord", "LDAP": "LDAP", - "LDAP server updated": "LDAP-server bijgewerkt", "Leaderboard": "Klassement", "Learn more": "Meer informatie", "Learn More": "Meer informatie", @@ -1246,6 +1345,7 @@ "Legacy": "Legacy", "lexical": "lexicaal", "License": "Licentie", + "Lifecycle JSON": "", "Lift List": "Lift-lijst", "Light": "Licht", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Beperk gelijktijdige zoekopdrachten. 0 = onbeperkt (standaard). Stel in op 1 voor sequentiele uitvoering (aanbevolen voor API's met strikte rate limits, zoals Brave free tier).", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Locatietoegang niet toegestaan", "Lost": "Verloren", "Low": "Laag", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LNR", "Made by Open WebUI Community": "Gemaakt door OpenWebUI Community", "Make password visible in the user interface": "Maak wachtwoord zichtbaar in de gebruikersinterface", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Pijplijnen beheren", "Manage Tool Servers": "Beheer gereedschapservers", "Manage your account information.": "Beheer je accountinformatie.", + "Mapped Source": "", "March": "maart", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown-koptekstsplitser", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Geheugen succesvol vrijgemaakt", "Memory deleted successfully": "Geheugen succesvol verwijderd", "Memory updated successfully": "Geheugen succesvol bijgewerkt", + "Merge Accounts by Email": "", "Merge Responses": "Voeg antwoorden samen", "Merged Response": "Samengevoegd antwoord", "Message": "Bericht", @@ -1322,9 +1425,12 @@ "messages": "berichten", "Messages": "Berichten", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Berichten die je verzendt nadat je jouw link hebt gemaakt, worden niet gedeeld. Gebruikers met de URL kunnen de gedeelde chat bekijken.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (persoonlijk)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (werk/opleiding)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API-sleutel vereist voor Cloud API-modus.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Modellen delen", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API-sleutel", + "Monday – Friday": "", "Month": "Maand", "Monthly": "Maandelijks", "More": "Meer", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Geef je kennisbasis een naam", "Name, prompt, and model are required": "Naam, prompt en model zijn verplicht", "Native": "Native", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Nooit", "New": "Nieuw", "New Automation": "Nieuwe automatisering", @@ -1423,6 +1531,7 @@ "Next run": "Volgende uitvoering", "No access grants. Private to you.": "Geen toegangsrechten. Alleen privé voor jou.", "No activity data": "Geen activiteitsgegevens", + "No additional headers are sent unless configured.": "", "No authentication": "Geen authenticatie", "No automations found": "Geen automatiseringen gevonden", "No chats found": "Geen chats gevonden", @@ -1435,8 +1544,10 @@ "No data": "Geen gegevens", "No data found": "Geen gegevens gevonden", "No distance available": "Geen afstand beschikbaar", + "No event webhooks configured.": "", "No execution logs available yet": "Geen uitvoerlogs beschikbaar", "No expiration can pose security risks.": "Geen vervaldatum kan veiligheidsrisico's opleveren.", + "No external knowledge sources configured.": "", "No feedback found": "Geen feedback gevonden", "No file selected": "Geen bestand geselecteerd", "No files found": "Geen bestanden gevonden", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "Geen vastgemaakte berichten", "No prompts found": "Geen prompts gevonden", + "No Repeat": "", "No results": "Geen resultaten gevonden", "No results found": "Geen resultaten gevonden", "No search query generated": "Geen zoekopdracht gegenereerd", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Nog geen webhooks", "Node Ids": "Node-ID's", "None": "Geen", + "Not configured": "", "Not factually correct": "Niet feitelijk juist", "Not helpful": "Niet nuttig", "Not Registered": "Niet geregistreerd", @@ -1498,20 +1611,25 @@ "Notifications": "Notificaties", "November": "november", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statisch)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "oktober", "Off": "Uit", "Okay, Let's Go!": "Oké, laten we gaan!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Donker", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API-instellingen bijgewerkt", "Ollama Cloud API Key": "Ollama Cloud API-sleutel", "Ollama Version": "Ollama Versie", + "Omit": "", "On": "Aan", "Once": "Eenmalig", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Wachtwoord", "Passwords do not match.": "Wachtwoorden komen niet overeen.", "Paste Large Text as File": "Plak grote tekst als bestand", + "Path": "", "Path copied": "Pad gekopieerd", "Paused": "Gepauzeerd", "PDF document (.pdf)": "PDF document (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "wachtend", "Pending": "In afwachting", + "Pending Accounts": "", "Pending User Overlay Content": "Inhoud van overlay voor wachtende gebruiker", "Pending User Overlay Title": "Titel van overlay voor wachtende gebruiker", "Permission denied when accessing media devices": "Toegang geweigerd bij het toegang krijgen tot media-apparaten", "Permission denied when accessing microphone": "Toegang geweigerd bij toegang tot de microfoon", "Permission denied when accessing microphone: {{error}}": "Toestemming geweigerd bij toegang tot microfoon: {{error}}", "Permissions": "Toestemmingen", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API-sleutel", "Perplexity Model": "Perplexity-model", "Perplexity Search API URL": "Perplexity Search API-URL", "Perplexity Search Context Usage": "Gebruik van zoekcontext voor Perplexity", "Persistent": "Persistent", "Personalization": "Personalisatie", + "Picture Claim": "", "Pin": "Zet vast", "Pin to Sidebar": "Vastzetten in zijbalk", "Pinned": "Vastgezet", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Voer alle velden in", "Please register the OAuth client": "Registreer de OAuth-client", "Please save the connection to persist the OAuth client information and do not change the ID": "Sla de verbinding op om de OAuth-clientinformatie te bewaren en wijzig de ID niet", - "Please select a model first.": "Selecteer eerst een model", "Please select a model.": "Selecteer een model", "Please select a reason": "Voer een reden in", "Please select a valid JSON file": "Selecteer een geldig JSON-bestand", "Please select at least one user for Direct Message channel.": "Selecteer ten minste een gebruiker voor het Direct Message-kanaal.", "Please wait until all files are uploaded.": "Wacht tot alle bestanden zijn geüpload.", "Policy ID": "Beleid-ID", + "Policy ID is required": "", "Port": "Poort", "Ports": "Poorten", "Positive attitude": "Positieve houding", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Publiek prompts delen", "Prompts Sharing": "Prompts delen", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Publiek", "Pull \"{{searchValue}}\" from Ollama.com": "Haal \"{{searchValue}}\" uit Ollama.com", "Pull a model from Ollama.com": "Haal een model van Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Voorlezen", "Read Aloud": "Voorlezen", "Read more →": "Lees meer →", + "Read only": "", "Read Only": "Alleen lezen", "Read-Only Access": "Alleen-lezen-toegang", "Reason": "Reden", "Reasoning Effort": "Redeneerinspanning", "Reasoning Tags": "Redeneertags", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Onlangs gebruikt", "Reconnected": "Opnieuw verbonden", "Record": "Opnemen", "Record voice": "Neem stem op", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Je wordt doorgestuurd naar OpenWebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Vermindert de kans op het genereren van onzin. Een hogere waarde (bijv. 100) zal meer diverse antwoorden geven, terwijl een lagere waarde (bijv. 10) conservatiever zal zijn.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refereer naar jezelf als \"user\" (bv. \"User is Spaans aan het leren\")", "Reference Chats": "Referentiechats", "Refresh": "Verversen", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Geweigerd terwijl dat niet had mogen gebeuren", "Regenerate": "Regenereren", "Regenerate Menu": "Menu opnieuw genereren", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "Markdown renderen in voorvertoningen", "Render Markdown in User Messages": "", "Reorder Models": "Herschik modellen", + "Repeat": "", "Repeats": "Herhalingen", "Reply": "Antwoorden", "Reply in Thread": "Antwoord in draad", "Reply to thread...": "Reageren op draad...", "Replying to {{NAME}}": "Reageren op {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "vereist", "Reranking Batch Size": "Batchgrootte voor herordenen", "Reranking Engine": "Herschikkingsengine", "Reranking Model": "Reranking Model", + "Research Knowledge": "", "Reset": "Herstellen", "Reset All Models": "Herstel alle modellen", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Afbeelding resetten", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Herstel Uploadmap", "Reset Vector Storage/Knowledge": "Herstel Vectoropslag/-kennis", "Reset view": "Herstel zicht", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 bron opgehaald", "Rich Text Input for Chat": "Rijke tekstinvoer voor chatten", "Role": "Rol", + "Roles Claim": "", "RTL": "RNL", "Run": "Uitvoeren", "Run All": "Alles uitvoeren", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Chat logs direct opslaan in de opslag van je browser wordt niet langer ondersteund. Neem even de tijd om je chat logs te downloaden en te verwijderen door op de knop hieronder te klikken. Maak je geen zorgen, je kunt je chat logs eenvoudig opnieuw importeren naar de backend via", "Schedule": "Planning", "Scheduled time must be in the future": "Ingeplande tijd moet in de toekomst liggen", + "Scopes": "", "Scroll On Branch Change": "Scrollen bij wijziging van branch", "Scroll to Top": "", "Search": "Zoeken", "Search a model": "Zoek een model", + "Search actions": "", "Search all emojis": "Alle emoji's zoeken", "Search and manage user memories": "Gebruikersherinneringen zoeken en beheren", "Search and view user chat history": "Gebruikerschatgeschiedenis zoeken en bekijken", @@ -1798,6 +1940,7 @@ "Search Chats": "Chats zoeken", "Search Collection": "Zoek naar verzamelingen", "Search Files": "Bestanden zoeken", + "Search filters": "", "Search Filters": "Zoek naar filters", "search for archived chats": "zoek naar gearchiveerde chats", "search for folders": "zoek naar mappen", @@ -1812,13 +1955,16 @@ "Search Models": "Modellen zoeken", "Search Notes": "Notities zoeken", "Search options": "Opties zoeken", + "Search or add pattern": "", "Search Prompts": "Prompts zoeken", "Search Result Count": "Aantal zoekresultaten", + "Search skills": "", "Search Skills": "Vaardigheden zoeken", - "Search skills...": "", "Search the internet": "Zoek op het internet", "Search the web and fetch URLs": "Doorzoek het web en haal URL's op", + "Search tools": "", "Search Tools": "Zoek gereedschappen", + "Search users or groups": "", "Search, view, and manage user notes": "Gebruikersnotities zoeken, bekijken en beheren", "SearchApi API Key": "SearchApi API-sleutel", "SearchApi Engine": "SearchApi Engine", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Selecteren", "Select {{modelName}} model": "Selecteer {{modelName}}-model", - "Select a base model": "Selecteer een basismodel", "Select a base model (e.g. llama3, gpt-4o)": "Selecteer een basismodel (bijv. llama3, gpt-4o)", "Select a conversation to preview": "Selecteer een gesprek om te bekijken", "Select a engine": "Selecteer een engine", @@ -1872,18 +2017,25 @@ "semantic": "semantisch", "Send": "Verzenden", "Send a Message": "Stuur een bericht", + "Send events for": "", "Send message": "Stuur bericht", "Send now": "Nu verzenden", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Stuurt `stream_options: { include_usage: true }` in het verzoek. \nOndersteunde providers zullen informatie over tokengebruik in het antwoord terugsturen als dit aan staat.", "September": "september", "SerpApi API Key": "SerpApi API-sleutel", "SerpApi Engine": "SerpApi-engine", "Serper API Key": "Serper API-sleutel", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API-sleutel", "Serpstack API Key": "Serpstack API-sleutel", "Server connection failed": "Serververbinding mislukt", "Server connection verified": "Server verbinding geverifieerd", + "Service Account": "", "Session": "Sessie", + "Session expired. Please sign in again.": "", "Set as default": "Stel in als standaard", "Set as Production": "Instellen als productie", "Set embedding model": "Stel embedding-model in", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Deellink gekopieerd naar klembord.", "Share to Open WebUI Community": "Deel naar OpenWebUI-community", "Share your background and interests": "Deel je achtergrond en interesses", + "Shared": "", "Shared Chats": "Gedeelde chats", "Shared with you": "Gedeeld met jou", "Sharing Permissions": "Deeltoestemmingen", "Show": "Toon", - "Show \"What's New\" modal on login": "Toon \"Wat is nieuw\" bij inloggen", + "Show \"What's New\" Modal on Login": "Toon \"Wat is nieuw\" bij inloggen", "Show Admin Details in Account Pending Overlay": "Admin-details weergeven in overlay in afwachting van account", "Show All": "Alles tonen", "Show all ({{COUNT}} characters)": "Alles tonen ({{COUNT}} tekens)", "Show Files": "Bestanden tonen", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Opmaakwerkbalk tonen", "Show image preview": "Afbeeldingsvoorvertoning tonen", "Show Model": "Toon model", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Bron", + "Specific users or groups": "", "Speech Playback Speed": "Afspeelsnelheid spraak", "Speech recognition error: {{error}}": "Spraakherkenning fout: {{error}}", "Speech-to-Text": "Spraak-naar-tekst", @@ -1999,6 +2154,7 @@ "STT Settings": "STT Instellingen", "Stylized PDF Export": "Gestileerde PDF-export", "Su_day_of_week": "zo", + "Sub Claim": "", "Submit question": "Vraag indienen", "Submit suggestion": "Suggestie indienen", "Subtitle": "Ondertitel", @@ -2023,8 +2179,10 @@ "Syncing...": "Synchroniseren...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synchroniseert alleen chats met wijzigingen na je laatste synchronisatietijdstip. Schakel dit uit om alle chats opnieuw te synchroniseren.", "System": "Systeem", + "System events only": "", "System Instructions": "Systeem instructies", "System Prompt": "Systeem prompt", + "Table": "", "Tag": "Tag", "Tags": "Tags", "Tags Generation": "Taggeneratie", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Tijdelijke chat standaard", "Terminal": "Terminal", "Terminal servers saved": "Terminalservers opgeslagen", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Tekst splitser", "Text-to-Speech": "Tekst-naar-spraak", "Text-to-Speech Engine": "Tekst-naar-Spraak Engine", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "De taal van de invoeraudio. Het opgeven van de invoertaal in ISO-639-1-indeling (bijv. en) verbetert de nauwkeurigheid en latentie. Laat leeg om de taal automatisch te detecteren.", "The LDAP attribute that maps to the mail that users use to sign in.": "Het LDAP-attribuut dat verwijst naar de e-mail waarmee gebruikers zich aanmelden.", "The LDAP attribute that maps to the username that users use to sign in.": "Het LDAP-attribuut dat verwijst naar de gebruikersnaam die gebruikers gebruiken om in te loggen.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Het leaderboard is momenteel in bèta en we kunnen de ratingberekeningen aanpassen naarmate we het algoritme verfijnen.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "De maximale bestandsgrootte in MB. Als het bestand groter is dan deze limiet, wordt het bestand niet geüpload.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Het maximum aantal bestanden dat in één keer kan worden gebruikt in de chat. Als het aantal bestanden deze limiet overschrijdt, worden de bestanden niet geüpload.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Het uitvoerformaat voor de tekst. Kan 'json', 'markdown' of 'html' zijn. Standaard is 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Deze map is leeg", "This is a default user permission and will remain enabled.": "Dit is een standaardgebruikersrecht en blijft ingeschakeld.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Dit is een experimentele functie, het werkt mogelijk niet zoals verwacht en kan op elk moment worden gewijzigd.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Dit model is niet publiek beschikbaar. Selecteer een ander model.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Deze optie bepaalt hoe lang het model na het verzoek in het geheugen geladen blijft (standaard: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Deze optie bepaalt hoeveel tokens bewaard blijven bij het verversen van de context. Als deze bijvoorbeeld op 2 staat, worden de laatste 2 tekens van de context van het gesprek bewaard. Het behouden van de context kan helpen om de continuïteit van een gesprek te behouden, maar het kan de mogelijkheid om te reageren op nieuwe onderwerpen verminderen.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Om meer over beschikbare endpoints te leren, bezoek onze documentatie.", "To select skills here, add them to the \"Skills\" workspace first.": "Om hier vaardigheden te selecteren, voeg ze eerst toe aan de \"Vaardigheden\"-werkruimte.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Om hier gereedschapssets te selecteren, voeg ze eerst aan de \"Gereedschappen\" Werkplaats toe.", - "Toast notifications for new updates": "Toon notificaties voor nieuwe updates", + "Toast Notifications for New Updates": "Toon notificaties voor nieuwe updates", "Today": "Vandaag", "Today at": "Vandaag om", "Today at {{LOCALIZED_TIME}}": "Vandaag om {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Schakel in of de huidige verbinding actief is.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Tokenaantallen zijn schattingen en komen mogelijk niet overeen met het werkelijke API-gebruik", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Te langdradig", @@ -2184,14 +2350,19 @@ "Unpin": "Losmaken", "Unpin from Sidebar": "Losmaken van zijbalk", "Unravel secrets": "Ontrafel geheimen", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Chat delen opheffen", "Unsupported file type.": "Niet-ondersteund bestandstype.", "Untagged": "Ongemarkeerd", "Untitled": "Zonder titel", "Update": "Bijwerken", "Update and Copy Link": "Bijwerken en kopieer link", + "Update Email": "", "Update for the latest features and improvements.": "Bijwerken voor de nieuwste functies en verbeteringen", + "Update Name": "", "Update password": "Wijzig wachtwoord", + "Update Picture": "", "Update your status": "Werk je status bij", "Updated": "Bijgewerkt", "Updated at": "Bijgewerkt om", @@ -2218,13 +2389,18 @@ "Use": "Gebruiken", "Use '#' in the prompt input to load and include your knowledge.": "Gebruik '#' in de promptinvoer om je kennis te laden en op te nemen.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Gebruik het /v1/chat/completions-endpoint in plaats van /v1/audio/transcriptions voor mogelijk betere nauwkeurigheid.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Gebruik Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Gebruik groepen om je gebruikers te organiseren en machtigingen toe te kennen.", "Use LLM": "LLM gebruiken", "Use no proxy to fetch page contents.": "Gebruik geen proxy om paginainhoud op te halen.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Gebruik de proxy die is opgegeven door de omgevingsvariabelen http_proxy en https_proxy om paginainhoud op te halen.", + "Use Web Search?": "", "user": "gebruiker", "User": "Gebruiker", + "User Access": "", "User Activity": "Gebruikersactiviteit", "User Groups": "Gebruikersgroepen", "User location successfully retrieved.": "Gebruikerslocatie succesvol opgehaald", @@ -2234,6 +2410,7 @@ "User Status": "Gebruikersstatus", "User Webhooks": "Gebruiker-webhooks", "Username": "Gebruikersnaam", + "Username Claim": "", "users": "gebruikers", "Users": "Gebruikers", "Uses DefaultAzureCredential to authenticate": "Gebruikt DefaultAzureCredential voor authenticatie", @@ -2247,6 +2424,7 @@ "Valves updated": "Kleppen bijgewerkt", "Valves updated successfully": "Kleppen succesvol bijgewerkt", "variable": "variabele", + "Vector Field": "", "Verify Connection": "Controleer verbinding", "Verify SSL Certificate": "SSL-certificaat verifiëren", "Version": "Versie", @@ -2276,11 +2454,14 @@ "Web API": "Web-API", "Web Loader Engine": "Webloader-engine", "Web Search": "Zoeken op het web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Zoekmachine op het web", "Web Search in Chat": "Zoekopdracht in chat", "Web Search Query Generation": "Zoekopdracht generatie", + "Webhook deleted": "", "Webhook Name": "Webhooknaam", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "Webpagina-URL's", "WebUI Settings": "WebUI Instellingen", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex Web Search API-sleutel", "Yandex Web Search config": "Yandex Web Search-configuratie", "Yandex Web Search URL": "Yandex Web Search-URL", + "Yearly": "", "Yesterday": "Gisteren", "Yesterday at {{LOCALIZED_TIME}}": "Gisteren om {{LOCALIZED_TIME}}", "You": "Jij", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Je browser ondersteunt de video-tag niet.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Je volledige bijdrage gaat direct naar de ontwikkelaar van de plugin; Open WebUI neemt hier geen deel van. Het gekozen financieringsplatform kan echter wel zijn eigen kosten hebben.", "Your message text or inputs": "Je berichttekst of invoer", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Je gebruiksstatistieken zijn succesvol gesynchroniseerd.", "YouTube": "Youtube", "Youtube Language": "Youtube-taal", diff --git a/src/lib/i18n/locales/pa-IN/translation.json b/src/lib/i18n/locales/pa-IN/translation.json index ac0a80061f..9812ab378d 100644 --- a/src/lib/i18n/locales/pa-IN/translation.json +++ b/src/lib/i18n/locales/pa-IN/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} ਦੀਆਂ ਗੱਲਾਂ", "{{webUIName}} Backend Required": "{{webUIName}} ਬੈਕਐਂਡ ਲੋੜੀਂਦਾ ਹੈ", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "ਖਾਤਾ", @@ -72,6 +83,7 @@ "Activity": "", "Add": "ਸ਼ਾਮਲ ਕਰੋ", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "ਇਸ ਬਾਰੇ ਇੱਕ ਸੰਖੇਪ ਵੇਰਵਾ ਸ਼ਾਮਲ ਕਰੋ ਕਿ ਇਹ ਮਾਡਲ ਕੀ ਕਰਦਾ ਹੈ", "Add a tag": "ਇੱਕ ਟੈਗ ਸ਼ਾਮਲ ਕਰੋ", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "ਫਾਈਲਾਂ ਸ਼ਾਮਲ ਕਰੋ", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "ਉਪਭੋਗਤਾ ਸ਼ਾਮਲ ਕਰੋ", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "ਪ੍ਰਬੰਧਕ ਪੈਨਲ", + "Admin Roles": "", "Admin Settings": "ਪ੍ਰਬੰਧਕ ਸੈਟਿੰਗਾਂ", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "ਉੱਚ ਸਤਰ ਦੇ ਪੈਰਾਮੀਟਰ", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "ਪਹਿਲਾਂ ਹੀ ਖਾਤਾ ਹੈ?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API ਬੇਸ URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API ਕੁੰਜੀ", + "API Key / Token": "", "API Key created.": "API ਕੁੰਜੀ ਬਣਾਈ ਗਈ।", "API Key Endpoint Restrictions": "", "API keys": "API ਕੁੰਜੀਆਂ", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "ਆਡੀਓ", "August": "ਅਗਸਤ", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "ਜਵਾਬ ਆਟੋ ਕਾਪੀ ਕਲਿੱਪਬੋਰਡ 'ਤੇ", - "Auto-playback response": "ਆਟੋ-ਪਲੇਬੈਕ ਜਵਾਬ", + "Auto-Create Groups": "", + "Auto-Playback Response": "ਆਟੋ-ਪਲੇਬੈਕ ਜਵਾਬ", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 ਬੇਸ URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "ਉਪਲਬਧ ਯੂਜ਼ਰ", + "Available variables": "", "available!": "ਉਪਲਬਧ ਹੈ!", "Away": "ਗੈਰਹਾਜ਼ਿਰ", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "ਖਰਾਬ ਜਵਾਬ", "Banners": "ਬੈਨਰ", "Base Model (From)": "ਬੇਸ ਮਾਡਲ (ਤੋਂ)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "ਪਹਿਲਾਂ", "Being lazy": "ਆਲਸੀ ਹੋਣਾ", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "ਗੱਲਬਾਤ ਡਿਰੈਕਟਨ", + "Chat Direction": "ਗੱਲਬਾਤ ਡਿਰੈਕਟਨ", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "ਸੰਗ੍ਰਹਿ", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ਕੰਫੀਯੂਆਈ", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "ਕਮਾਂਡ", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "ਸਮੱਗਰੀ", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ਜਵਾਬ ਜਾਰੀ ਰੱਖੋ", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "ਨਵੀਂ ਗੁਪਤ ਕੁੰਜੀ ਬਣਾਓ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "ਤੇ ਬਣਾਇਆ ਗਿਆ", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "ਡਿਫਾਲਟ ਮਾਡਲ", "Default model updated": "ਮੂਲ ਮਾਡਲ ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "ਮੂਲ ਉਪਭੋਗਤਾ ਭੂਮਿਕਾ", + "Default webhook": "", "Defaults": "", "Delete": "ਮਿਟਾਓ", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "ਬੰਦ", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "ਮਾਡਲ ਪ੍ਰੀਸੈਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "ਗੱਲਬਾਤ 'ਚ ਤੁਹਾਡੇ ਸਥਾਨ 'ਤੇ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਓ", + "Display the Username Instead of You in the Chat": "ਗੱਲਬਾਤ 'ਚ ਤੁਹਾਡੇ ਸਥਾਨ 'ਤੇ ਉਪਭੋਗਤਾ ਨਾਮ ਦਿਖਾਓ", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "ਡਾਕੂਮੈਂਟ", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ਉਪਭੋਗਤਾ ਸੰਪਾਦਨ ਕਰੋ", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "ਈਮੇਲ", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "ਐਮਬੈੱਡਿੰਗ ਮਾਡਲ ਇੰਜਣ", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "ਕਮਿਊਨਿਟੀ ਸ਼ੇਅਰਿੰਗ ਨੂੰ ਸਮਰੱਥ ਕਰੋ", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "ਨਵੇਂ ਸਾਈਨ ਅਪ ਯੋਗ ਕਰੋ", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "ਚਾਲੂ", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ਸੁਨਿਸ਼ਚਿਤ ਕਰੋ ਕਿ ਤੁਹਾਡੀ CSV ਫਾਈਲ ਵਿੱਚ ਇਸ ਕ੍ਰਮ ਵਿੱਚ 4 ਕਾਲਮ ਹਨ: ਨਾਮ, ਈਮੇਲ, ਪਾਸਵਰਡ, ਭੂਮਿਕਾ।", "Enter {{role}} message here": "{{role}} ਸੁਨੇਹਾ ਇੱਥੇ ਦਰਜ ਕਰੋ", - "Enter a detail about yourself for your LLMs to recall": "ਤੁਹਾਡੇ LLMs ਨੂੰ ਸੁਨੇਹਾ ਕਰਨ ਲਈ ਸੁਨੇਹਾ ਇੱਥੇ ਦਰਜ ਕਰੋ", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "ਚੰਕ ਓਵਰਲੈਪ ਦਰਜ ਕਰੋ", "Enter Chunk Size": "ਚੰਕ ਆਕਾਰ ਦਰਜ ਕਰੋ", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "ਭਾਸ਼ਾ ਕੋਡ ਦਰਜ ਕਰੋ", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "ਸਕੋਰ ਦਰਜ ਕਰੋ", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Serper API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "Serpstack API ਕੁੰਜੀ ਦਾਖਲ ਕਰੋ", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "ਸਿਖਰ K ਦਰਜ ਕਰੋ", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL ਦਰਜ ਕਰੋ (ਉਦਾਹਰਣ ਲਈ http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API ਕੁੰਜੀ ਬਣਾਉਣ ਵਿੱਚ ਅਸਫਲ।", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ਕਲਿੱਪਬੋਰਡ ਸਮੱਗਰੀ ਪੜ੍ਹਣ ਵਿੱਚ ਅਸਫਲ", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "ਮਹੱਤਵਪੂਰਨ ਅੱਪਡੇਟ", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "ਕੀਬੋਰਡ ਸ਼ਾਰਟਕਟ", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "ਹਲਕਾ", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਦੁਆਰਾ ਬਣਾਇਆ ਗਿਆ", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "ਪਾਈਪਲਾਈਨਾਂ ਦਾ ਪ੍ਰਬੰਧਨ ਕਰੋ", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "ਮਾਰਚ", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "ਮਿਲਾਇਆ ਗਿਆ ਜਵਾਬ", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ਤੁਹਾਡਾ ਲਿੰਕ ਬਣਾਉਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡੇ ਵੱਲੋਂ ਭੇਜੇ ਗਏ ਸੁਨੇਹੇ ਸਾਂਝੇ ਨਹੀਂ ਕੀਤੇ ਜਾਣਗੇ। URL ਵਾਲੇ ਉਪਭੋਗਤਾ ਸਾਂਝੀ ਚੈਟ ਨੂੰ ਵੇਖ ਸਕਣਗੇ।", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "ਹੋਰ", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਮਿਲੇ", "No results found": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਮਿਲੇ", "No search query generated": "ਕੋਈ ਖੋਜ ਪੁੱਛਗਿੱਛ ਤਿਆਰ ਨਹੀਂ ਕੀਤੀ ਗਈ", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "ਕੋਈ ਨਹੀਂ", + "Not configured": "", "Not factually correct": "ਤੱਥਕ ਰੂਪ ਵਿੱਚ ਸਹੀ ਨਹੀਂ", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "ਸੂਚਨਾਵਾਂ", "November": "ਨਵੰਬਰ", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "ਅਕਤੂਬਰ", "Off": "ਬੰਦ", "Okay, Let's Go!": "ਠੀਕ ਹੈ, ਚੱਲੋ ਚੱਲੀਏ!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED ਗੂੜ੍ਹਾ", "Ollama": "ਓਲਾਮਾ", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "ਓਲਾਮਾ ਵਰਜਨ", + "Omit": "", "On": "ਚਾਲੂ", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "ਪਾਸਵਰਡ", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ਡਾਕੂਮੈਂਟ (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "ਬਕਾਇਆ", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚਣ ਸਮੇਂ ਆਗਿਆ ਰੱਦ ਕੀਤੀ ਗਈ: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "ਪਰਸੋਨਲਿਸ਼ਮ", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "ਸਕਾਰਾਤਮਕ ਰਵੱਈਆ", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "ਓਲਾਮਾ.ਕਾਮ ਤੋਂ \"{{searchValue}}\" ਖਿੱਚੋ", "Pull a model from Ollama.com": "ਓਲਾਮਾ.ਕਾਮ ਤੋਂ ਇੱਕ ਮਾਡਲ ਖਿੱਚੋ", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "ਜੋਰ ਨਾਲ ਪੜ੍ਹੋ", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "ਆਵਾਜ਼ ਰਿਕਾਰਡ ਕਰੋ", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "ਤੁਹਾਨੂੰ ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਵੱਲ ਰੀਡਾਇਰੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "ਜਦੋਂ ਇਹ ਨਹੀਂ ਹੋਣਾ ਚਾਹੀਦਾ ਸੀ ਤਾਂ ਇਨਕਾਰ ਕੀਤਾ", "Regenerate": "ਮੁੜ ਬਣਾਓ", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "ਮਾਡਲ ਮੁੜ ਰੈਂਕਿੰਗ", + "Research Knowledge": "", "Reset": "", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "ਚਿੱਤਰ ਰੀਸੈਟ ਕਰੋ", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "ਭੂਮਿਕਾ", + "Roles Claim": "", "RTL": "RTL", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "ਤੁਹਾਡੇ ਬ੍ਰਾਊਜ਼ਰ ਦੇ ਸਟੋਰੇਜ ਵਿੱਚ ਸਿੱਧੇ ਗੱਲਬਾਤ ਲੌਗ ਸੰਭਾਲਣਾ ਹੁਣ ਸਮਰਥਿਤ ਨਹੀਂ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਦਿੱਤੇ ਬਟਨ 'ਤੇ ਕਲਿੱਕ ਕਰਕੇ ਆਪਣੇ ਗੱਲਬਾਤ ਲੌਗ ਡਾਊਨਲੋਡ ਅਤੇ ਮਿਟਾਉਣ ਲਈ ਕੁਝ ਸਮਾਂ ਲਓ। ਚਿੰਤਾ ਨਾ ਕਰੋ, ਤੁਸੀਂ ਆਪਣੇ ਗੱਲਬਾਤ ਲੌਗ ਨੂੰ ਬੈਕਐਂਡ ਵਿੱਚ ਆਸਾਨੀ ਨਾਲ ਮੁੜ ਆਯਾਤ ਕਰ ਸਕਦੇ ਹੋ", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "ਖੋਜ", "Search a model": "ਇੱਕ ਮਾਡਲ ਖੋਜੋ", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "ਖੋਜ ਚੈਟਾਂ", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "ਖੋਜ ਮਾਡਲ", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "ਪ੍ਰੰਪਟ ਖੋਜੋ", "Search Result Count": "ਖੋਜ ਨਤੀਜੇ ਦੀ ਗਿਣਤੀ", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "ਬੀਜ", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "ਆਧਾਰ ਮਾਡਲ ਚੁਣੋ", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "ਭੇਜੋ", "Send a Message": "ਇੱਕ ਸੁਨੇਹਾ ਭੇਜੋ", + "Send events for": "", "Send message": "ਸੁਨੇਹਾ ਭੇਜੋ", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "ਸਤੰਬਰ", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Serper API ਕੁੰਜੀ", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "Serpstack API ਕੁੰਜੀ", "Server connection failed": "", "Server connection verified": "ਸਰਵਰ ਕਨੈਕਸ਼ਨ ਦੀ ਪੁਸ਼ਟੀ ਕੀਤੀ ਗਈ", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "ਮੂਲ ਵਜੋਂ ਸੈੱਟ ਕਰੋ", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "ਓਪਨਵੈਬਯੂਆਈ ਕਮਿਊਨਿਟੀ ਨਾਲ ਸਾਂਝਾ ਕਰੋ", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "ਦਿਖਾਓ", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "ਸਰੋਤ", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "ਬੋਲ ਪਛਾਣ ਗਲਤੀ: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT ਸੈਟਿੰਗਾਂ", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "ਸਿਸਟਮ", + "System events only": "", "System Instructions": "", "System Prompt": "ਸਿਸਟਮ ਪ੍ਰੰਪਟ", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "ਪਾਠ-ਤੋਂ-ਬੋਲ ਇੰਜਣ", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "ਅੱਜ", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "", "Update and Copy Link": "ਅੱਪਡੇਟ ਕਰੋ ਅਤੇ ਲਿੰਕ ਕਾਪੀ ਕਰੋ", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "ਪਾਸਵਰਡ ਅੱਪਡੇਟ ਕਰੋ", + "Update Picture": "", "Update your status": "", "Updated": "", "Updated at": "", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "ਉਪਭੋਗਤਾ", "User": "", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "ਉਪਭੋਗਤਾ", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "ਵੈਰੀਏਬਲ", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "ਵਰਜਨ", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "ਵੈੱਬ ਖੋਜ", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "ਵੈੱਬ ਖੋਜ ਇੰਜਣ", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "ਵੈਬਹੁੱਕ URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "ਵੈਬਯੂਆਈ ਸੈਟਿੰਗਾਂ", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "ਕੱਲ੍ਹ", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "ਤੁਸੀਂ", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "ਯੂਟਿਊਬ", "Youtube Language": "", diff --git a/src/lib/i18n/locales/pl-PL/translation.json b/src/lib/i18n/locales/pl-PL/translation.json index 061a53f5a3..54d662cc12 100644 --- a/src/lib/i18n/locales/pl-PL/translation.json +++ b/src/lib/i18n/locales/pl-PL/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} ukrytych linii", "{{COUNT}} members": "{{COUNT}} członków", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "{{count}} zaznaczonych", "{{count}} selected_other": "{{count}} zaznaczonych", "{{COUNT}} Sources": "{{COUNT}} źródeł", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} słów", "{{COUNT}}d_time_ago": "{{COUNT}} dn. temu", "{{COUNT}}h_time_ago": "{{COUNT}} godz. temu", "{{COUNT}}m_time_ago": "{{COUNT}} min temu", "{{COUNT}}w_time_ago": "{{COUNT}} tyg. temu", "{{COUNT}}y_time_ago": "{{COUNT}} l. temu", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} o {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Pobieranie modelu {{model}} zostało anulowane", "{{modelName}} profile image": "Zdjęcie profilowe {{modelName}}", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "Czaty użytkownika {{user}}", "{{webUIName}} Backend Required": "Wymagany backend {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*Do generowania obrazów wymagane jest ID węzła promptu", + "1 group": "", "1 hour before": "1 godzinę przed", "1 Source": "1 źródło", + "1 user": "", "10 minutes before": "10 minut przed", "15 minutes before": "15 minut przed", "1m_time_ago": "1 min temu", @@ -63,6 +79,7 @@ "Access Control": "Kontrola dostępu", "Access Grants": "Przyznane dostępy", "Access List": "Lista dostępu", + "Access prohibited": "", "Access updated": "Dostęp zaktualizowany", "Accessible to all users": "Dostępny dla wszystkich użytkowników", "Account": "Konto", @@ -78,6 +95,7 @@ "Activity": "Aktywność", "Add": "Dodaj", "Add a model ID": "Dodaj identyfikator modelu", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Dodaj krótki opis działania tego modelu", "Add a tag": "Dodaj tag", "Add a tag...": "Dodaj tag...", @@ -90,8 +108,10 @@ "Add Custom Prompt": "Dodaj niestandardowy prompt", "Add description": "Dodaj opis", "Add Details": "Dodaj szczegóły", + "Add durable context for future chats": "", "Add Files": "Dodaj pliki", "Add Image": "Dodaj obraz", + "Add Knowledge Connection": "", "Add location": "Dodaj lokalizację", "Add Member": "Dodaj członka", "Add Members": "Dodaj członków", @@ -106,6 +126,7 @@ "Add to favorites": "Dodaj do ulubionych", "Add User": "Dodaj użytkownika", "Add User Group": "Dodaj grupę użytkowników", + "Add webhook": "", "Add webpage": "Dodaj stronę WWW", "Add your Open Terminal URL and API key in Settings → Integrations.": "Dodaj adres URL Open Terminal i klucz API w Ustawienia → Integracje.", "Additional Config": "Dodatkowa konfiguracja", @@ -118,7 +139,9 @@ "Admin": "Administrator", "Admin Contact Email": "Adres e-mail administratora", "Admin Panel": "Panel administracyjny", + "Admin Roles": "", "Admin Settings": "Ustawienia administratora", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorzy mają zawsze dostęp do wszystkich narzędzi; użytkownicy muszą mieć przypisane narzędzia do modelu w obszarze roboczym.", "Advanced": "Zaawansowane", "Advanced Parameters": "Zaawansowane parametry", @@ -129,16 +152,21 @@ "All": "Wszystkie", "All chats have been unarchived.": "Wszystkie czaty zostały przywrócone.", "All day": "Cały dzień", + "All events": "", "All models are now hidden": "Wszystkie modele są teraz ukryte", "All models are now visible": "Wszystkie modele są teraz widoczne", "All models deleted successfully": "Wszystkie modele zostały pomyślnie usunięte.", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Cały okres", "All Users": "Wszyscy użytkownicy", + "All users and system events": "", "Allow Call": "Zezwól na rozmowy głosowe", "Allow Chat Controls": "Zezwól na ustawienia czatu", "Allow Chat Delete": "Zezwól na usuwanie czatu", "Allow Chat Edit": "Zezwól na edycję czatu", "Allow Chat Export": "Zezwól na eksport czatu", + "Allow Chat Import": "", "Allow Chat Params": "Zezwól na parametry czatu", "Allow Chat Share": "Zezwól na udostępnianie czatu", "Allow Chat System Prompt": "Zezwól na prompt systemowy czatu", @@ -158,9 +186,11 @@ "Allow User Location": "Zezwól na lokalizację użytkownika", "Allow Voice Interruption in Call": "Zezwól na przerywanie w trakcie rozmowy", "Allow Web Upload": "Zezwalaj na przesyłanie z sieci", + "Allowed Domains": "", "Allowed Endpoints": "Dozwolone punkty końcowe", "Allowed File Extensions": "Dozwolone rozszerzenia plików", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Dozwolone rozszerzenia plików. Oddziel przecinkami. Pozostaw puste dla wszystkich typów.", + "Allowed Roles": "", "Already have an account?": "Posiadasz już konto?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternatywa dla top_p, zapewniająca balans między jakością a różnorodnością. Parametr p to minimalne prawdopodobieństwo tokena względem najbardziej prawdopodobnego tokena. Np. przy p=0.05 i max prawdopodobieństwie 0.9, wartości poniżej 0.045 są odrzucane.", "Always": "Zawsze", @@ -179,6 +209,7 @@ "API Base URL": "Bazowy adres URL API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Bazowy adres URL API dla usługi Datalab Marker. Domyślnie: https://www.datalab.to/api/v1/marker", "API Key": "Klucz API", + "API Key / Token": "", "API Key created.": "Utworzono klucz API.", "API Key Endpoint Restrictions": "Ograniczenia punktów końcowych klucza API", "API keys": "Klucze API", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Czy na pewno chcesz usunąć to wspomnienie? Tej operacji nie można cofnąć.", "Are you sure you want to delete this message?": "Czy na pewno chcesz usunąć tę wiadomość?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Czy na pewno chcesz usunąć tę wersję? Wersje podrzędne zostaną przypisane do wersji nadrzędnej.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Czy na pewno chcesz to usunąć?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Czy na pewno chcesz przywrócić wszystkie czaty?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modele Arena", "Artifacts": "Artefakty", "Asc": "Rosnąco", "Ask": "Zapytaj", "Ask a question": "Zadaj pytanie", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asystent", "Async Embedding Processing": "Asynchroniczne przetwarzanie embeddingów", "At time of event": "W momencie wydarzenia", @@ -229,14 +265,20 @@ "Audio": "Dźwięk", "August": "Sierpień", "Auth": "Autoryzacja", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Uwierzytelnij", "Authentication": "Uwierzytelnianie", "Auto": "Auto", "Auto (Random)": "Auto (Losowo)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatycznie kopiuj odpowiedź do schowka", - "Auto-playback response": "Automatyczne odtwarzanie odpowiedzi", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatyczne odtwarzanie odpowiedzi", "Autocomplete Generation": "Generowanie autouzupełniania", "Autocomplete Generation Input Max Length": "Maks. długość wejścia autouzupełniania", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Ciąg autoryzacji API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Bazowy adres URL AUTOMATIC1111", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "Dostępne narzędzia", "available users": "dostępni użytkownicy", + "Available variables": "", "available!": "dostępne!", "Away": "Nieobecny", "Awful": "Okropne", @@ -264,16 +307,17 @@ "Bad Response": "Zła odpowiedź", "Banners": "Banery", "Base Model (From)": "Model bazowy (Z)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Cache listy modeli bazowych przyspiesza dostęp, pobierając je tylko przy starcie lub zapisie ustawień – szybciej, ale może nie pokazać ostatnich zmian w modelach.", "Bearer": "Bearer", "before": "przed", "Being lazy": "Zbyt ogólnikowy", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Punkt końcowy Bing Search V7", "Bing Search V7 Subscription Key": "Klucz subskrypcji Bing Search V7", "Bio": "Bio", "Birth Date": "Data urodzenia", + "Blocked Groups": "", "BM25 Weight": "Waga BM25", "Bocha Search API Key": "Klucz API Bocha Search", "Bold": "Pogrubienie", @@ -330,7 +374,7 @@ "Chat Completions": "Uzupełnianie czatu", "Chat Conversation": "Rozmowa", "Chat deleted.": "Czat usunięty.", - "Chat direction": "Kierunek czatu", + "Chat Direction": "Kierunek czatu", "Chat exported successfully": "Czat wyeksportowany pomyślnie", "Chat History": "Historia czatu", "Chat ID": "ID czatu", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "Kanał współpracy dostępny dla członków", "Collapse": "Zwiń", "Collection": "Kolekcja", + "Collection Field": "", "Collections": "Kolekcje", "Color": "Kolor", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "Workflow ComfyUI", "ComfyUI Workflow Nodes": "Węzły Workflow ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID węzłów oddzielone przecinkami (np. 1 lub 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "polecenie", "Command": "Komenda", "Comment": "Komentarz", "Commit Message": "Wiadomość commita", "Community Reviews": "Recenzje społeczności", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Completions (Uzupełnianie)", "Compress Images in Channels": "Kompresuj obrazy w kanałach", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Połącz się z instancjami Open Terminal. Wszyscy użytkownicy będą mieli dostęp do przeglądania plików i narzędzi terminalowych przez te serwery.", "Connect to your own OpenAI compatible API endpoints.": "Połącz z własnymi punktami końcowymi API zgodnymi z OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Połącz z własnymi serwerami narzędzi zgodnymi z OpenAPI.", + "Connected": "", "Connected ({{type}})": "Połączono ({{type}})", "Connection failed": "Połączenie nieudane", "Connection lost. Reconnecting...": "Utracono połączenie. Ponowne łączenie...", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Skontaktuj się z administratorem, aby uzyskać dostęp.", "Content": "Treść", "Content Extraction Engine": "Silnik ekstrakcji treści", + "Content Field": "", "Content lengths (character counts only)": "Długość treści (liczba znaków)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Tokeny kontekstu", + "Continue": "", "Continue Response": "Kontynuuj odpowiedź", "Continue with {{provider}}": "Kontynuuj przez {{provider}}", "Continue with Email": "Kontynuuj przez Email", @@ -501,6 +557,7 @@ "Create new secret key": "Utwórz nowy tajny klucz", "Create note": "Utwórz notatkę", "Create Note": "Utwórz notatkę", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Twórz zaplanowane prompty, które uruchamiają się automatycznie w ustalonych odstępach czasu.", "Create your first note by clicking on the plus button below.": "Utwórz pierwszą notatkę klikając plus poniżej.", "Created at": "Utworzono", @@ -518,6 +575,7 @@ "Custom Gender": "Niestandardowa płeć", "Custom Parameter Name": "Nazwa parametru niestandardowego", "Custom Parameter Value": "Wartość parametru niestandardowego", + "Custom range": "", "Daily": "Codziennie", "Daily Messages": "Wiadomości dzienne", "Danger Zone": "Strefa krytyczna", @@ -540,7 +598,6 @@ "Default Features": "Domyślne funkcje", "Default Filters": "Domyślne filtry", "Default Group": "Domyślna grupa", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Tryb domyślny działa z większą liczbą modeli. Tryb natywny używa wbudowanych funkcji modelu (function calling), ale wymaga wsparcia ze strony modelu.", "Default Model": "Model domyślny", "Default model updated": "Zaktualizowano model domyślny", "Default permissions": "Domyślne uprawnienia", @@ -550,6 +607,7 @@ "Default to ALL": "Domyślnie WSZYSTKIE", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Domyślnie używa segmented retrieval dla lepszej precyzji. Zalecane w większości przypadków.", "Default User Role": "Domyślna rola użytkownika", + "Default webhook": "", "Defaults": "Domyślne", "Delete": "Usuń", "Delete {{name}}": "Usuń {{name}}", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "Wyłącz interpreter kodu", "Disable Image Extraction": "Wyłącz ekstrakcję obrazów", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Wyłącz wyciąganie obrazów z PDF. Jeśli używasz LLM, obrazy będą automatycznie opisywane. Domyślnie Wyłączone.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Wyłączone", "Disconnect OAuth": "Rozłącz OAuth", "Discover a function": "Odkryj funkcję", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Odkrywaj, pobieraj i eksploruj ustawienia modeli", "Discussion channel where access is based on groups and permissions": "Kanał dyskusyjny z dostępem opartym na grupach", "Display": "Wyświetlanie", - "Display chat title in tab": "Pokaż tytuł czatu w karcie", + "Display Chat Title in Tab": "Pokaż tytuł czatu w karcie", "Display Emoji in Call": "Pokaż emoji w wywołaniu", "Display Multi-model Responses in Tabs": "Pokaż odpowiedzi multimodalne w kartach", - "Display the username instead of You in the Chat": "Pokaż nazwę użytkownika zamiast 'Ty' w czacie", + "Display the Username Instead of You in the Chat": "Pokaż nazwę użytkownika zamiast 'Ty' w czacie", "Displays citations in the response": "Wyświetla cytaty w odpowiedzi", "Displays status updates (e.g., web search progress) in the response": "Wyświetla statusy (np. postęp wyszukiwania) w odpowiedzi", "Dive into knowledge": "Zanurz się w wiedzy", @@ -638,6 +698,7 @@ "Docling Parameters": "Parametry Docling", "Docling Server URL required.": "Wymagany URL serwera Docling.", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Wymagany endpoint Document Intelligence.", "Document Intelligence Model": "Model Document Intelligence", @@ -693,12 +754,14 @@ "Edit Default Permissions": "Edytuj domyślne uprawnienia", "Edit Folder": "Edytuj folder", "Edit Image": "Edytuj obraz", + "Edit Knowledge Connection": "", "Edit Last Message": "Edytuj ostatnią wiadomość", "Edit Memory": "Edytuj pamięć", "Edit Prompt": "Edytuj prompt", "Edit Terminal Connection": "Edytuj połączenie z terminalem", "Edit User": "Edytuj profil użytkownika", "Edit User Group": "Edytuj grupę użytkowników", + "Edit webhook": "", "Edit workflow.json content": "Edytuj treść workflow.json", "edited": "edytowano", "Edited": "Edytowano", @@ -707,6 +770,7 @@ "Eject model": "Odłącz model", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Wyrusz na przygodę", "Embedding": "Embedding", "Embedding Batch Size": "Embedding Batch Size", @@ -715,6 +779,7 @@ "Embedding Model Engine": "Silnik modelu embeddingów", "Emoji": "", "Emojis": "Emoji", + "Empty": "", "Empty message": "Pusta wiadomość", "Enable All": "Włącz wszystkie", "Enable API Keys": "Włącz klucze API", @@ -722,22 +787,27 @@ "Enable Code Execution": "Włącz wykonywanie kodu", "Enable Code Interpreter": "Włącz interpreter kodu", "Enable Community Sharing": "Włącz udostępnianie społecznościowe", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Włącz mlock (blokowanie pamięci), aby trzymać model w RAM. Zapobiega to używaniu dysku (swap) i zwiększa wydajność.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Włącz mmap (mapowanie pamięci). Pozwala używać dysku jako rozszerzenia RAM. Może przyspieszyć ładowanie, ale zużywa dużo miejsca na dysku.", "Enable Message Queue": "Włącz kolejkę wiadomości", "Enable Message Rating": "Włącz ocenianie wiadomości", "Enable Mirostat sampling for controlling perplexity.": "Włącz próbkowanie Mirostat do kontroli perplexity.", "Enable New Sign Ups": "Zezwól na nowe rejestracje", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Włącz, wyłącz lub dostosuj tagi reasoning (rozumowania). \"Włączone\" używa domyślnych, \"Wyłączone\" usuwa je, \"Własne\" pozwala zdefiniować tagi start/koniec.", "Enabled": "Włączone", "End Tag": "Tag końcowy", + "Endpoint": "", "Endpoint URL": "URL punktu końcowego", "Enforce Temporary Chat": "Wymuś czat tymczasowy", "Enhance": "Ulepsz", "Enrich Hybrid Search Text": "Wzbogać tekst wyszukiwania hybrydowego", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Upewnij się, że plik CSV ma 4 kolumny: Nazwa, Email, Hasło, Rola.", "Enter {{role}} message here": "Wpisz wiadomość roli {{role}} tutaj", - "Enter a detail about yourself for your LLMs to recall": "Wpisz szczegóły o sobie, aby LLM je zapamiętał", "Enter a title for the pending user info overlay. Leave empty for default.": "Wpisz tytuł nakładki informacyjnej dla użytkownika oczekującego na aktywację. Zostaw puste dla domyślnego.", "Enter a watermark for the response. Leave empty for none.": "Wpisz znak wodny odpowiedzi. Zostaw puste dla braku.", "Enter additional headers in JSON format": "Wprowadź dodatkowe nagłówki w formacie JSON", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "Docelowy min. rozmiar chunka", "Enter Chunk Overlap": "Wprowadź Chunk Overlap", "Enter Chunk Size": "Wprowadź Chunk Size", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Wprowadź pary \"token:bias\" po przecinku (np. 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Wpisz treść nakładki informacyjnej. Zostaw puste dla domyślnej.", "Enter coordinates (e.g. 51.505, -0.09)": "Wprowadź współrzędne (np. 51.505, -0.09)", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "Wprowadź URL Jupyter", "Enter Kagi Search API Key": "Wprowadź klucz API Kagi Search", "Enter Key Behavior": "Zachowanie klawisza Enter", + "Enter language": "", "Enter language codes": "Wprowadź kody języków", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Wprowadź klucz MinerU API", "Enter Mistral API Base URL": "Wprowadź Base URL Mistral API", "Enter Mistral API Key": "Wprowadź klucz API Mistral", @@ -812,6 +887,7 @@ "Enter prompt here.": "Wprowadź prompt tutaj.", "Enter proxy URL (e.g. https://user:password@host:port)": "Wprowadź URL proxy (np. https://user:pass@host:port)", "Enter reasoning effort": "Wprowadź Reasoning Effort", + "Enter Redirect URI": "", "Enter Score": "Wprowadź wynik (Score)", "Enter SearchApi API Key": "Wprowadź klucz API SearchApi", "Enter SearchApi Engine": "Wprowadź silnik SearchApi", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "Wprowadź klucz API SerpApi", "Enter SerpApi Engine": "Wprowadź silnik SerpApi", "Enter Serper API Key": "Wprowadź klucz API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Wprowadź klucz API Serply", "Enter Serpstack API Key": "Wprowadź klucz API Serpstack", "Enter server host": "Wprowadź host serwera", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Wprowadź URL serwera Tika", "Enter timeout in seconds": "Wprowadź limit czasu w sekundach", "Enter to Send": "Enter wysyła", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Wprowadź Top K", "Enter Top K Reranker": "Wprowadź Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Wprowadź URL (np. http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Błąd: Model o ID '{{modelId}}' już istnieje. Wybierz inne ID.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Błąd: ID modelu nie może być puste. Wprowadź poprawne ID.", "Evaluations": "Ewaluacje", + "Event": "", "Event created": "Wydarzenie utworzone", "Event deleted": "Wydarzenie usunięte", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Tytuł wydarzenia", "Event updated": "Wydarzenie zaktualizowane", + "Events": "", "Exa API Key": "Klucz API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Przykład: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Przykład: ALL", "Example: mail": "Przykład: mail", @@ -913,12 +996,18 @@ "Export Config": "Eksportuj konfigurację", "Export Models": "Eksportuj modele", "Export Prompts": "Eksportuj prompty", + "Export Skills": "", "Export to CSV": "Eksportuj do CSV", "Export Tools": "Eksportuj narzędzia", "Export Users": "Eksportuj użytkowników", "External": "Zewnętrzny", + "External connection not found.": "", "External Document Loader URL required.": "Wymagany URL External Document Loader.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Zewnętrzny Model Zadaniowy", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Klucz API External Web Loader", "External Web Loader URL": "URL External Web Loader", "External Web Search API Key": "Klucz API External Web Search", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Nie udało się utworzyć klucza API.", "Failed to delete calendar": "Nie udało się usunąć kalendarza", "Failed to delete note": "Nie udało się usunąć notatki", + "Failed to delete webhook": "", "Failed to disconnect": "Nie udało się rozłączyć", "Failed to download image": "Nie udało się pobrać obrazu", "Failed to extract content from the file: {{error}}": "Nie udało się wyodrębnić treści z pliku: {{error}}", @@ -943,6 +1033,7 @@ "Failed to fetch models": "Nie udało się pobrać modeli", "Failed to generate title": "Nie udało się wygenerować tytułu", "Failed to import models": "Nie udało się zaimportować modeli", + "Failed to load chat": "", "Failed to load chat preview": "Nie udało się załadować podglądu czatu", "Failed to load DOCX file. Please try downloading it instead.": "Nie udało się załadować pliku DOCX. Spróbuj go pobrać.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Nie udało się załadować pliku Excel/CSV. Spróbuj go pobrać.", @@ -952,6 +1043,7 @@ "Failed to move chat": "Nie udało się przenieść czatu", "Failed to process URL: {{url}}": "Nie udało się przetworzyć URL: {{url}}", "Failed to read clipboard contents": "Nie udało się odczytać schowka", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Nie udało się usunąć członka", "Failed to render diagram": "Nie udało się wyrenderować diagramu", "Failed to render visualization": "Nie udało się wyrenderować wizualizacji", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "Nie udało się zapisać konfiguracji modeli", "Failed to save policy: {{error}}": "Nie udało się zapisać polityki: {{error}}", "Failed to save terminal servers": "Nie udało się zapisać serwerów terminalowych", + "Failed to save webhook": "", "Failed to unshare chat.": "Nie udało się cofnąć udostępniania czatu.", "Failed to update settings": "Nie udało się zaktualizować ustawień", "Failed to update status": "Nie udało się zaktualizować statusu", + "Failed to update webhook": "", "Failed to upload file.": "Nie udało się przesłać pliku.", "Features": "Funkcje", "Features Permissions": "Uprawnienia funkcji", @@ -995,6 +1089,8 @@ "File uploaded successfully": "Plik przesłany pomyślnie", "Filename": "Nazwa pliku", "Files": "Pliki", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtr", "Filter is now globally disabled": "Filtr jest teraz globalnie wyłączony", "Filter is now globally enabled": "Filtr jest teraz globalnie włączony", @@ -1017,6 +1113,7 @@ "Folder options": "Opcje folderu", "Folder updated successfully": "Folder zaktualizowany pomyślnie", "Folders": "Foldery", + "Folders Sharing": "", "Follow up": "Pytania nawiązujące", "Follow Up Generation": "Generowanie pytań nawiązujących", "Follow Up Generation Prompt": "Prompt generowania pytań nawiązujących", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Funkcja jest teraz globalnie włączona", "Function Name": "Nazwa funkcji", "Function Name Filter List": "Lista filtrów nazw funkcji", + "Function starter": "", "Function updated successfully": "Funkcja zaktualizowana pomyślnie", "Functions": "Funkcje", "Functions allow arbitrary code execution.": "Funkcje pozwalają na wykonywanie dowolnego kodu.", @@ -1079,7 +1177,10 @@ "Gravatar": "Gravatar", "Grid": "Siatka", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Kanał grupowy", + "Group Claim": "", "Group created successfully": "Grupa utworzona pomyślnie", "Group deleted successfully": "Grupa usunięta pomyślnie", "Group Description": "Opis grupy", @@ -1091,6 +1192,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Wibracje (Haptic)", + "Header variables": "", "Headers": "Nagłówki", "Headers must be a valid JSON object": "Nagłówki muszą być poprawnym obiektem JSON", "Height": "Wysokość", @@ -1121,6 +1223,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID nie może zawierać \":\" ani \"|\"", "ID copied to clipboard": "ID skopiowane do schowka", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Limit czasu bezczynności", "iframe Sandbox Allow Forms": "Zezwól na formularze w iframe", "iframe Sandbox Allow Same Origin": "Zezwól na 'Same Origin' w iframe", @@ -1146,6 +1250,7 @@ "Import From Link": "Importuj z linku", "Import Models": "Importuj modele", "Import Prompts": "Importuj prompty", + "Import Skills": "", "Import successful": "Import udany", "Import Tools": "Importuj narzędzia", "Important Update": "Ważna aktualizacja", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "Zachowaj w pasku bocznym", "Key": "Klucz", "Key is required": "Klucz jest wymagany", - "Keyboard shortcuts": "Skróty klawiszowe", "Keyboard Shortcuts": "Skróty klawiszowe", "Knowledge": "Baza wiedzy", "Knowledge Access": "Dostęp do bazy wiedzy", @@ -1216,6 +1320,8 @@ "Knowledge Name": "Nazwa wiedzy", "Knowledge Public Sharing": "Publiczne udostępnianie wiedzy", "Knowledge Sharing": "Udostępnianie wiedzy", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Wiedza zaktualizowana pomyślnie", "Kokoro.js (Browser)": "Kokoro.js (Przeglądarka)", "Kokoro.js Dtype": "Typ danych Kokoro.js", @@ -1232,7 +1338,6 @@ "Last ran": "Ostatnie uruchomienie", "Last reply": "Ostatnia odpowiedź", "LDAP": "LDAP", - "LDAP server updated": "Serwer LDAP zaktualizowany", "Leaderboard": "Tablica wyników", "Learn more": "Dowiedz się więcej", "Learn More": "Dowiedz się więcej", @@ -1254,6 +1359,7 @@ "Legacy": "Przestarzałe (Legacy)", "lexical": "leksykalny", "License": "Licencja", + "Lifecycle JSON": "", "Lift List": "Lift List", "Light": "Jasny", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limit jednoczesnych zapytań. 0 = brak (domyślnie). Ustaw 1 dla sekwencyjnego wykonywania (zalecane dla darmowych API np. Brave).", @@ -1277,6 +1383,7 @@ "Location access not allowed": "Brak dostępu do lokalizacji", "Lost": "Przegrano", "Low": "Niski", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR (Od lewej)", "Made by Open WebUI Community": "Stworzone przez społeczność Open WebUI", "Make password visible in the user interface": "Pokaż hasło w interfejsie", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Zarządzaj Pipeline'ami", "Manage Tool Servers": "Zarządzaj serwerami narzędzi", "Manage your account information.": "Zarządzaj informacjami o koncie.", + "Mapped Source": "", "March": "Marzec", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown Header Text Splitter", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Pamięć wyczyszczona pomyślnie", "Memory deleted successfully": "Wpis pamięci usunięty pomyślnie", "Memory updated successfully": "Wpis pamięci zaktualizowany pomyślnie", + "Merge Accounts by Email": "", "Merge Responses": "Połącz odpowiedzi", "Merged Response": "Połączona odpowiedź", "Message": "Wiadomość", @@ -1330,9 +1439,12 @@ "messages": "wiadomości", "Messages": "Wiadomości", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Wiadomości wysłane po utworzeniu linku nie będą udostępniane. Użytkownicy z linkiem zobaczą udostępniony czat.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (osobisty)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (praca/szkoła)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Klucz API MinerU wymagany dla trybu Cloud API.", @@ -1385,6 +1497,7 @@ "Models Sharing": "Udostępnianie modeli", "Mojeek": "Mojeek", "Mojeek Search API Key": "Klucz API Mojeek Search", + "Monday – Friday": "", "Month": "Miesiąc", "Monthly": "Miesięcznie", "More": "Więcej", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "Nazwij bazę wiedzy", "Name, prompt, and model are required": "Nazwa, prompt i model są wymagane", "Native": "Natywny", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Nigdy", "New": "Nowy", "New Automation": "Nowa automatyzacja", @@ -1431,6 +1545,7 @@ "Next run": "Następne uruchomienie", "No access grants. Private to you.": "Brak przyznanych dostępów. Prywatne tylko dla Ciebie.", "No activity data": "Brak danych aktywności", + "No additional headers are sent unless configured.": "", "No authentication": "Brak autoryzacji", "No automations found": "Nie znaleziono automatyzacji", "No chats found": "Nie znaleziono czatów", @@ -1443,8 +1558,10 @@ "No data": "Brak danych", "No data found": "Nie znaleziono danych", "No distance available": "Brak wyniku dopasowania", + "No event webhooks configured.": "", "No execution logs available yet": "Brak dostępnych logów wykonania", "No expiration can pose security risks.": "Brak wygasania może stanowić ryzyko bezpieczeństwa.", + "No external knowledge sources configured.": "", "No feedback found": "Nie znaleziono informacji zwrotnej", "No file selected": "Nie wybrano pliku", "No files found": "Nie znaleziono plików", @@ -1472,6 +1589,7 @@ "No output items": "Brak elementów wyjściowych", "No pinned messages": "Brak przypiętych wiadomości", "No prompts found": "Nie znaleziono promptów", + "No Repeat": "", "No results": "Brak wyników", "No results found": "Brak wyników", "No search query generated": "Nie wygenerowano zapytania wyszukiwania", @@ -1491,6 +1609,7 @@ "No webhooks yet": "Brak webhooków", "Node Ids": "ID węzłów", "None": "Brak", + "Not configured": "", "Not factually correct": "Merytorycznie niepoprawne", "Not helpful": "Niepomocne", "Not Registered": "Niezarejestrowany", @@ -1506,20 +1625,25 @@ "Notifications": "Powiadomienia", "November": "Listopad", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (statyczny)", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL serwera OAuth", "OAuth session disconnected": "Sesja OAuth rozłączona", "October": "Październik", "Off": "Wył.", "Okay, Let's Go!": "OK, Jedziemy!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Ciemny (OLED)", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Zaktualizowano ustawienia API Ollama", "Ollama Cloud API Key": "Klucz API Ollama Cloud", "Ollama Version": "Wersja Ollama", + "Omit": "", "On": "Wł.", "Once": "Jednorazowo", "OneDrive": "OneDrive", @@ -1590,6 +1714,7 @@ "Password": "Hasło", "Passwords do not match.": "Hasła nie pasują do siebie.", "Paste Large Text as File": "Wklej duży tekst jako plik", + "Path": "", "Path copied": "Ścieżka skopiowana", "Paused": "Wstrzymany", "PDF document (.pdf)": "Dokument PDF (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "oczekuje", "Pending": "Oczekujące", + "Pending Accounts": "", "Pending User Overlay Content": "Treść nakładki dla oczekującego użytkownika", "Pending User Overlay Title": "Tytuł nakładki dla oczekującego użytkownika", "Permission denied when accessing media devices": "Odmowa dostępu do urządzeń multimedialnych", "Permission denied when accessing microphone": "Odmowa dostępu do mikrofonu", "Permission denied when accessing microphone: {{error}}": "Odmowa dostępu do mikrofonu: {{error}}", "Permissions": "Uprawnienia", + "Permissions reset to defaults": "", "Perplexity API Key": "Klucz API Perplexity", "Perplexity Model": "Model Perplexity", "Perplexity Search API URL": "URL API Perplexity Search", "Perplexity Search Context Usage": "Użycie kontekstu Perplexity Search", "Persistent": "Trwały", "Personalization": "Personalizacja", + "Picture Claim": "", "Pin": "Przypnij", "Pin to Sidebar": "Przypnij do paska bocznego", "Pinned": "Przypięte", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "Wypełnij wszystkie pola.", "Please register the OAuth client": "Zarejestruj klienta OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Zapisz połączenie aby zachować dane klienta OAuth i nie zmieniaj ID", - "Please select a model first.": "Najpierw wybierz model.", "Please select a model.": "Wybierz model.", "Please select a reason": "Wybierz powód", "Please select a valid JSON file": "Wybierz poprawny plik JSON", "Please select at least one user for Direct Message channel.": "Wybierz co najmniej jednego użytkownika do czatu prywatnego.", "Please wait until all files are uploaded.": "Poczekaj na przesłanie wszystkich plików.", "Policy ID": "ID polityki", + "Policy ID is required": "", "Port": "Port", "Ports": "Porty", "Positive attitude": "Pozytywne nastawienie", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "Publiczne udostępnianie promptów", "Prompts Sharing": "Udostępnianie promptów", "Provider": "Dostawca", + "Provider Name": "", + "Provider URL": "", "Public": "Publiczny", "Pull \"{{searchValue}}\" from Ollama.com": "Pobierz \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Pobierz model z Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "Czytaj", "Read Aloud": "Czytaj na głos", "Read more →": "Czytaj więcej →", + "Read only": "", "Read Only": "Tylko do odczytu", "Read-Only Access": "Dostęp tylko do odczytu", "Reason": "Powód", "Reasoning Effort": "Reasoning Effort", "Reasoning Tags": "Reasoning Tags", "Reasoning text...": "Tekst rozumowania...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Ostatnio używane", "Reconnected": "Ponownie połączono", "Record": "Nagraj", "Record voice": "Nagraj głos", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Przekierowanie do społeczności Open WebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Redukuje prawdopodobieństwo generowania nonsensu. Wyższa wartość (np. 100) = większa różnorodność, niższa (np. 10) = bardziej zachowawczo.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Mów o sobie \"Użytkownik\" (np. \"Użytkownik uczy się...\")", "Reference Chats": "Czaty referencyjne", "Refresh": "Odśwież", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Odmówił, gdy nie powinien", "Regenerate": "Wygeneruj ponownie", "Regenerate Menu": "Menu regeneracji", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "Renderuj Markdown w podglądach", "Render Markdown in User Messages": "Renderuj Markdown w wiadomościach użytkownika", "Reorder Models": "Zmień kolejność modeli", + "Repeat": "", "Repeats": "Powtarzanie", "Reply": "Odpowiedz", "Reply in Thread": "Odpowiedz w wątku", "Reply to thread...": "Odpowiedz w wątku...", "Replying to {{NAME}}": "Odpowiedź do {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "wymagane", "Reranking Batch Size": "Rozmiar partii reranking", "Reranking Engine": "Silnik Rerankingu", "Reranking Model": "Reranking Model", + "Research Knowledge": "", "Reset": "Resetuj", "Reset All Models": "Resetuj wszystkie modele", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetuj obraz", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Resetuj katalog przesyłania", "Reset Vector Storage/Knowledge": "Resetuj bazę wektorową/wiedzę", "Reset view": "Resetuj widok", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "Pobrano 1 źródło", "Rich Text Input for Chat": "Bogaty tekst w czacie", "Role": "Rola", + "Roles Claim": "", "RTL": "RTL (Od prawej)", "Run": "Uruchom", "Run All": "Uruchom wszystkie", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Zapisywanie historii w przeglądarce nie jest już wspierane. Pobierz i usuń logi poniżej. Możesz je potem zaimportować do backendu przez", "Schedule": "Harmonogram", "Scheduled time must be in the future": "Zaplanowany czas musi być w przyszłości", + "Scopes": "", "Scroll On Branch Change": "Przewiń przy zmianie gałęzi", "Scroll to Top": "Przewiń na górę", "Search": "Szukaj", "Search a model": "Szukaj modelu", + "Search actions": "", "Search all emojis": "Szukaj emoji", "Search and manage user memories": "Wyszukuj i zarządzaj wspomnieniami użytkowników", "Search and view user chat history": "Wyszukuj i przeglądaj historię czatu użytkowników", @@ -1810,6 +1960,7 @@ "Search Chats": "Szukaj czatów", "Search Collection": "Przeszukaj kolekcję", "Search Files": "Szukaj plików", + "Search filters": "", "Search Filters": "Filtry wyszukiwania", "search for archived chats": "szukaj w zarchiwizowanych", "search for folders": "szukaj folderów", @@ -1824,13 +1975,16 @@ "Search Models": "Szukaj modeli", "Search Notes": "Szukaj notatek", "Search options": "Opcje wyszukiwania", + "Search or add pattern": "", "Search Prompts": "Szukaj promptów", "Search Result Count": "Liczba wyników wyszukiwania", + "Search skills": "", "Search Skills": "Szukaj umiejętności", - "Search skills...": "", "Search the internet": "Przeszukaj internet", "Search the web and fetch URLs": "Przeszukuj sieć i pobieraj adresy URL", + "Search tools": "", "Search Tools": "Szukaj narzędzi", + "Search users or groups": "", "Search, view, and manage user notes": "Wyszukuj, przeglądaj i zarządzaj notatkami użytkowników", "SearchApi API Key": "Klucz API SearchApi", "SearchApi Engine": "Silnik SearchApi", @@ -1846,7 +2000,6 @@ "Seed": "Seed", "Select": "Wybierz", "Select {{modelName}} model": "Wybierz model {{modelName}}", - "Select a base model": "Wybierz model bazowy", "Select a base model (e.g. llama3, gpt-4o)": "Wybierz model bazowy (np. llama3, gpt-4o)", "Select a conversation to preview": "Wybierz rozmowę do podglądu", "Select a engine": "Wybierz silnik", @@ -1884,18 +2037,25 @@ "semantic": "semantyczny", "Send": "Wyślij", "Send a Message": "Wyślij wiadomość", + "Send events for": "", "Send message": "Wyślij wiadomość", "Send now": "Wyślij teraz", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Wysyła `stream_options: { include_usage: true }`. Obsługiwani dostawcy zwrócą zużycie tokenów.", "September": "Wrzesień", "SerpApi API Key": "Klucz API SerpApi", "SerpApi Engine": "Silnik SerpApi", "Serper API Key": "Klucz API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Klucz API Serply", "Serpstack API Key": "Klucz API Serpstack", "Server connection failed": "Nie udało się połączyć z serwerem", "Server connection verified": "Połączenie z serwerem zweryfikowane", + "Service Account": "", "Session": "Sesja", + "Session expired. Please sign in again.": "", "Set as default": "Ustaw jako domyślny", "Set as Production": "Ustaw jako produkcyjny", "Set embedding model": "Ustaw model embeddingów", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "Link udostępniania skopiowany do schowka.", "Share to Open WebUI Community": "Udostępnij społeczności Open WebUI", "Share your background and interests": "Udostępnij swoje tło i zainteresowania", + "Shared": "", "Shared Chats": "Udostępnione czaty", "Shared with you": "Udostępnione Tobie", "Sharing Permissions": "Uprawnienia udostępniania", "Show": "Pokaż", - "Show \"What's New\" modal on login": "Pokaż okno \"Co nowego\" przy logowaniu", + "Show \"What's New\" Modal on Login": "Pokaż okno \"Co nowego\" przy logowaniu", "Show Admin Details in Account Pending Overlay": "Pokaż dane admina na ekranie oczekiwania", "Show All": "Pokaż wszystkie", "Show all ({{COUNT}} characters)": "Pokaż wszystko ({{COUNT}} znaków)", "Show Files": "Pokaż pliki", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Pokaż pasek formatowania", "Show image preview": "Pokaż podgląd obrazu", "Show Model": "Pokaż model", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "sID Sougou Search API", "Sougou Search API SK": "SK Sougou Search API", "Source": "Źródło", + "Specific users or groups": "", "Speech Playback Speed": "Prędkość odtwarzania mowy", "Speech recognition error: {{error}}": "Błąd rozpoznawania mowy: {{error}}", "Speech-to-Text": "Silnik zamiany mowy na tekst (STT)", @@ -2013,6 +2176,7 @@ "STT Settings": "Ustawienia STT", "Stylized PDF Export": "Stylizowany eksport PDF", "Su_day_of_week": "Nd", + "Sub Claim": "", "Submit question": "Wyślij pytanie", "Submit suggestion": "Wyślij sugestię", "Subtitle": "Podtytuł", @@ -2037,8 +2201,10 @@ "Syncing...": "Synchronizowanie...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synchronizuje tylko czaty zaktualizowane po ostatniej synchronizacji. Wyłącz, aby zsynchronizować wszystkie.", "System": "System", + "System events only": "", "System Instructions": "Instrukcje systemowe", "System Prompt": "Prompt systemowy", + "Table": "", "Tag": "Tag", "Tags": "Tagi", "Tags Generation": "Generowanie tagów", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "Domyślnie czat tymczasowy", "Terminal": "Terminal", "Terminal servers saved": "Serwery terminalowe zapisane", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Text Splitter", "Text-to-Speech": "Silnik syntezy mowy (TTS)", "Text-to-Speech Engine": "Silnik syntezy mowy (TTS)", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Język audio wejściowego (ISO-639-1, np. pl). Poprawia dokładność. Zostaw puste dla auto-wykrywania.", "The LDAP attribute that maps to the mail that users use to sign in.": "Atrybut LDAP mapowany na email logowania.", "The LDAP attribute that maps to the username that users use to sign in.": "Atrybut LDAP mapowany na nazwę użytkownika.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Ranking jest w wersji beta, obliczenia mogą ulec zmianie.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Maksymalny rozmiar pliku (MB).", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maksymalna liczba plików w czacie.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Format wyjściowy tekstu (json, markdown, html). Domyślnie 'markdown'.", @@ -2096,6 +2267,7 @@ "This folder is empty": "Ten folder jest pusty", "This is a default user permission and will remain enabled.": "To domyślne uprawnienie i pozostanie włączone.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "To funkcja eksperymentalna, może nie działać poprawnie.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Ten model nie jest publicznie dostępny. Wybierz inny.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Kontroluje jak długo model zostaje w pamięci po żądaniu (domyślnie: 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Kontroluje ile tokenów jest zachowywanych przy odświeżaniu kontekstu.", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "Odwiedź dokumentację, aby poznać dostępne endpointy.", "To select skills here, add them to the \"Skills\" workspace first.": "Aby wybrać umiejętności tutaj, najpierw dodaj je do przestrzeni roboczej \"Umiejętności\".", "To select toolkits here, add them to the \"Tools\" workspace first.": "Aby wybrać narzędzia, dodaj je najpierw w obszarze \"Narzędzia\".", - "Toast notifications for new updates": "Powiadomienia o aktualizacjach", + "Toast Notifications for New Updates": "Powiadomienia o aktualizacjach", "Today": "Dzisiaj", "Today at": "Dziś o", "Today at {{LOCALIZED_TIME}}": "Dzisiaj o {{LOCALIZED_TIME}}", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "Przełącz aktywność połączenia.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Liczba tokenów jest szacunkowa i może nie odzwierciedlać faktycznego użycia API", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokeny", "Tokens": "Tokeny", "Too verbose": "Zbyt gadatliwy", @@ -2198,14 +2372,19 @@ "Unpin": "Odepnij", "Unpin from Sidebar": "Odepnij od paska bocznego", "Unravel secrets": "Rozwiązuj zagadki", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Cofnij udostępnianie czatu", "Unsupported file type.": "Nieobsługiwany typ pliku.", "Untagged": "Bez tagów", "Untitled": "Bez tytułu", "Update": "Aktualizuj", "Update and Copy Link": "Aktualizuj i kopiuj link", + "Update Email": "", "Update for the latest features and improvements.": "Zaktualizuj, aby uzyskać nowe funkcje.", + "Update Name": "", "Update password": "Zaktualizuj hasło", + "Update Picture": "", "Update your status": "Zaktualizuj status", "Updated": "Zaktualizowano", "Updated at": "Zaktualizowano", @@ -2232,13 +2411,18 @@ "Use": "Użyj", "Use '#' in the prompt input to load and include your knowledge.": "Użyj '#' w prompcie, aby załadować Bazę wiedzy.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Użyj endpointu /v1/chat/completions zamiast /v1/audio/transcriptions dla lepszej dokładności.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Użyj Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Użyj grup do organizowania użytkowników i przypisywania uprawnień.", "Use LLM": "Użyj LLM", "Use no proxy to fetch page contents.": "Nie używaj proxy do pobierania stron.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Używaj proxy ze zmiennych środowiskowych do pobierania stron.", + "Use Web Search?": "", "user": "użytkownik", "User": "Użytkownik", + "User Access": "", "User Activity": "Aktywność użytkownika", "User Groups": "Grupy użytkowników", "User location successfully retrieved.": "Lokalizacja użytkownika pobrana pomyślnie.", @@ -2248,6 +2432,7 @@ "User Status": "Status użytkownika", "User Webhooks": "Webhooki użytkownika", "Username": "Nazwa użytkownika", + "Username Claim": "", "users": "użytkownicy", "Users": "Użytkownicy", "Uses DefaultAzureCredential to authenticate": "Używa DefaultAzureCredential do autoryzacji", @@ -2261,6 +2446,7 @@ "Valves updated": "Valves zaktualizowane", "Valves updated successfully": "Valves zaktualizowane pomyślnie", "variable": "zmienna", + "Vector Field": "", "Verify Connection": "Sprawdź połączenie", "Verify SSL Certificate": "Weryfikuj certyfikat SSL", "Version": "Wersja", @@ -2290,11 +2476,14 @@ "Web API": "Web API", "Web Loader Engine": "Silnik ładowania stron", "Web Search": "Wyszukiwanie WWW", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Wyszukiwarka", "Web Search in Chat": "Wyszukiwanie w czacie", "Web Search Query Generation": "Generowanie zapytań wyszukiwania", + "Webhook deleted": "", "Webhook Name": "Nazwa webhooka", - "Webhook URL": "URL Webhooka", + "Webhook saved": "", "Webhooks": "Webhooki", "Webpage URLs": "Adresy URL stron", "WebUI Settings": "Ustawienia WebUI", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "Klucz API Yandex Web Search", "Yandex Web Search config": "Konfiguracja Yandex Web Search", "Yandex Web Search URL": "URL Yandex Web Search", + "Yearly": "", "Yesterday": "Wczoraj", "Yesterday at {{LOCALIZED_TIME}}": "Wczoraj o {{LOCALIZED_TIME}}", "You": "Ty", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "Twoja przeglądarka nie obsługuje tagu wideo.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Cała wpłata trafia do twórcy pluginu; Open WebUI nie pobiera prowizji. Wybrana platforma płatnicza może jednak naliczać własne opłaty.", "Your message text or inputs": "Treść wiadomości lub dane wejściowe", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Twoje statystyki użycia zostały pomyślnie zsynchronizowane.", "YouTube": "YouTube", "Youtube Language": "Język YouTube", diff --git a/src/lib/i18n/locales/pt-BR/translation.json b/src/lib/i18n/locales/pt-BR/translation.json index 5c95e94884..1ca6fd0e37 100644 --- a/src/lib/i18n/locales/pt-BR/translation.json +++ b/src/lib/i18n/locales/pt-BR/translation.json @@ -9,31 +9,42 @@ "[Today at] h:mm A": "[Hoje às] h:mm A", "[Yesterday at] h:mm A": "[Ontem às] h:mm A", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Skills": "", + "{{COUNT}} Available Skills": "{{COUNT}} Habilidades disponíveis", "{{COUNT}} Available Tools": "{{COUNT}} Ferramentas disponíveis", "{{COUNT}} characters": "{{COUNT}} caracteres", "{{COUNT}} extracted lines": "{{COUNT}} linhas extraídas", "{{COUNT}} files": "{{COUNT}} arquivos", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", - "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "{{count}} arquivo selecionado. Apenas arquivos novos e modificados serão enviados. Arquivos excluídos serão removidos. A estrutura de pastas será espelhada. Continuar?", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "{{count}} arquivos selecionados. Apenas arquivos novos e modificados serão enviados. Arquivos excluídos serão removidos. A estrutura de pastas será espelhada. Continuar?", + "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "{{count}} arquivos selecionados. Apenas arquivos novos e modificados serão enviados. Arquivos excluídos serão removidos. A estrutura de pastas será espelhada. Continuar?", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} linhas ocultas", "{{COUNT}} members": "{{COUNT}} membros", - "{{count}} of {{total}} accessible_one": "", - "{{count}} of {{total}} accessible_many": "", - "{{count}} of {{total}} accessible_other": "", + "{{count}} of {{total}} accessible_one": "{{count}} de {{total}} acessível", + "{{count}} of {{total}} accessible_many": "{{count}} de {{total}} acessíveis", + "{{count}} of {{total}} accessible_other": "{{count}} de {{total}} acessíveis", "{{COUNT}} Replies": "{{COUNT}} Respostas", "{{COUNT}} Rows": "{{COUNT}} Linhas", "{{count}} selected_one": "{{count}} selecionado", "{{count}} selected_many": "{{count}} selecionados", "{{count}} selected_other": "{{count}} selecionados", "{{COUNT}} Sources": "{{COUNT}} Origens", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} palavras", "{{COUNT}}d_time_ago": "{{COUNT}}d atrás", "{{COUNT}}h_time_ago": "{{COUNT}}h atrás", "{{COUNT}}m_time_ago": "{{COUNT}}m atrás", "{{COUNT}}w_time_ago": "{{COUNT}}sem atrás", "{{COUNT}}y_time_ago": "{{COUNT}}a atrás", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} às {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "O download do {{model}} foi cancelado", "{{modelName}} profile image": "Imagem de perfil de {{modelName}}", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Chats de {{user}}", "{{webUIName}} Backend Required": "Backend {{webUIName}} necessário", "*Prompt node ID(s) are required for image generation": "*Prompt node ID(s) são obrigatórios para gerar imagens", + "1 group": "", "1 hour before": "1 hora antes", "1 Source": "1 Origem", + "1 user": "", "10 minutes before": "10 minutos antes", "15 minutes before": "15 minutos antes", "1m_time_ago": "1m atrás", @@ -60,6 +73,7 @@ "Access Control": "Controle de Acesso", "Access Grants": "Concessões de Acesso", "Access List": "Lista de acesso", + "Access prohibited": "", "Access updated": "Acesso atualizado", "Accessible to all users": "Acessível para todos os usuários", "Account": "Conta", @@ -75,6 +89,7 @@ "Activity": "Atividade", "Add": "Adicionar", "Add a model ID": "Adicione um ID de modelo", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Adicione uma descrição curta sobre o que este modelo faz", "Add a tag": "Adicionar uma tag", "Add a tag...": "Adicione uma tag...", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Adicionar prompt personalizado", "Add description": "Adicionar descrição", "Add Details": "Adicionar detalhes", + "Add durable context for future chats": "", "Add Files": "Adicionar Arquivos", "Add Image": "Adicionar imagem", + "Add Knowledge Connection": "", "Add location": "Adicionar localização", "Add Member": "Adicionar membro", "Add Members": "Adicionar membros", @@ -103,6 +120,7 @@ "Add to favorites": "Adicionar aos favoritos", "Add User": "Adicionar Usuário", "Add User Group": "Adicionar grupo de usuários", + "Add webhook": "", "Add webpage": "Adicionar página web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Adicione a URL do Open Terminal e a chave de API em Configurações → Integrações.", "Additional Config": "Configuração adicional", @@ -115,7 +133,9 @@ "Admin": "Admin", "Admin Contact Email": "E-mail de contato do administrador", "Admin Panel": "Painel do Admin", + "Admin Roles": "", "Admin Settings": "Configurações do Admin", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Os administradores têm acesso a todas as ferramentas o tempo todo; os usuários precisam de ferramentas atribuídas, por modelo, no workspace.", "Advanced": "Avançado", "Advanced Parameters": "Parâmetros Avançados", @@ -126,16 +146,21 @@ "All": "Tudo", "All chats have been unarchived.": "Todos os chats foram desarquivados.", "All day": "O dia todo", + "All events": "", "All models are now hidden": "Todos os modelos estão agora ocultos", "All models are now visible": "Todos os modelos estão agora visíveis", "All models deleted successfully": "Todos os modelos foram excluídos com sucesso", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Todo o período", "All Users": "Todos os usuários", + "All users and system events": "", "Allow Call": "Permitir chamada", "Allow Chat Controls": "Permitir Controles de Chats", "Allow Chat Delete": "Permitir Exclusão de Chats", "Allow Chat Edit": "Permitir Edição de Chats", "Allow Chat Export": "Permitir Exportação de Chat", + "Allow Chat Import": "", "Allow Chat Params": "Permitir Parâmetros de Chat", "Allow Chat Share": "Permitir Compartilhamento de Chat", "Allow Chat System Prompt": "Permitir Prompt do Sistema no Chat", @@ -155,9 +180,11 @@ "Allow User Location": "Permitir Localização do Usuário", "Allow Voice Interruption in Call": "Permitir Interrupção de Voz na Chamada", "Allow Web Upload": "Permitir Upload da Web", + "Allowed Domains": "", "Allowed Endpoints": "Endpoints Permitidos", "Allowed File Extensions": "Extensões de arquivo permitidas", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Extensões de arquivo permitidas para upload. Separe várias extensões com vírgulas. Deixe em branco para todos os tipos de arquivo.", + "Allowed Roles": "", "Already have an account?": "Já possui uma conta?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa ao top_p, visando garantir um equilíbrio entre qualidade e variedade. O parâmetro p representa a probabilidade mínima de um token ser considerado, em relação à probabilidade do token mais provável. Por exemplo, com p = 0,05 e o token mais provável tendo uma probabilidade de 0,9, logits com valor inferior a 0,045 são filtrados.", "Always": "Sempre", @@ -176,6 +203,7 @@ "API Base URL": "URL Base da API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL base da API para o serviço Datalab Marker. O padrão é: https://www.datalab.to/api/v1/marker", "API Key": "Chave API", + "API Key / Token": "", "API Key created.": "Chave API criada.", "API Key Endpoint Restrictions": "Restrições de endpoint de chave de API", "API keys": "Chaves API", @@ -201,17 +229,22 @@ "Are you sure you want to delete all chats? This action cannot be undone.": "Tem certeza de que deseja excluir todas as conversas? Esta ação não pode ser desfeita.", "Are you sure you want to delete this channel?": "Tem certeza de que deseja excluir este canal?", "Are you sure you want to delete this connection? This action cannot be undone.": "Tem certeza de que deseja excluir esta conexão? Esta ação não pode ser desfeita.", - "Are you sure you want to delete this directory?": "", + "Are you sure you want to delete this directory?": "Tem certeza de que deseja excluir este diretório?", "Are you sure you want to delete this memory? This action cannot be undone.": "Tem certeza de que deseja excluir esta memória? Esta ação não pode ser desfeita.", "Are you sure you want to delete this message?": "Tem certeza de que deseja excluir esta mensagem?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Tem certeza de que deseja excluir esta versão? As versões filhas serão vinculadas novamente à versão pai.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Tem certeza de que deseja excluir isto?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Você tem certeza que deseja desarquivar todos os chats arquivados?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena de Modelos", "Artifacts": "Artefatos", "Asc": "Crescente", "Ask": "Perguntar", "Ask a question": "Faça uma pergunta", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistente", "Async Embedding Processing": "Processamento de Embedding assíncrono", "At time of event": "No horário do evento", @@ -226,14 +259,20 @@ "Audio": "Áudio", "August": "Agosto", "Auth": "Autenticação", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autenticar", "Authentication": "Autenticação", "Auto": "Auto", "Auto (Random)": "Automático (Aleatório)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Cópia Automática da Resposta para a Área de Transferência", - "Auto-playback response": "Reprodução automática da resposta", + "Auto-Create Groups": "", + "Auto-Playback Response": "Reprodução automática da resposta", "Autocomplete Generation": "Geração de preenchimento automático", "Autocomplete Generation Input Max Length": "Comprimento máximo de entrada de geração de preenchimento automático", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "String de Autenticação da API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111", @@ -248,9 +287,10 @@ "Automations": "Automações", "Available list": "Lista disponível", "Available models": "Modelos disponíveis", - "Available Skills": "", + "Available Skills": "Habilidades disponíveis", "Available Tools": "Ferramentas disponíveis", "available users": "usuários disponíveis", + "Available variables": "", "available!": "disponível!", "Away": "Ausente", "Awful": "Horrível", @@ -261,16 +301,17 @@ "Bad Response": "Resposta Ruim", "Banners": "Banners", "Base Model (From)": "Modelo Base (De)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "O cache da lista de modelos base acelera o acesso buscando modelos base somente na inicialização ou ao salvar as configurações — mais rápido, mas pode não mostrar alterações recentes no modelo base.", "Bearer": "Bearer", "before": "antes", "Being lazy": "Sendo preguiçoso", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Endpoint do Bing Search V7", "Bing Search V7 Subscription Key": "Chave de assinatura do Bing Search V7", "Bio": "Sobre você", "Birth Date": "Data de nascimento", + "Blocked Groups": "", "BM25 Weight": "Peso BM25", "Bocha Search API Key": "Chave da API de pesquisa Bocha", "Bold": "Negrito", @@ -327,7 +368,7 @@ "Chat Completions": "Gerar Resposta", "Chat Conversation": "Conversa do Chat", "Chat deleted.": "Chat excluído.", - "Chat direction": "Direção do Chat", + "Chat Direction": "Direção do Chat", "Chat exported successfully": "Chat exportado com sucesso", "Chat History": "Histórico de chat", "Chat ID": "ID do Chat", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Canal de colaboração onde as pessoas se juntam como membros.", "Collapse": "Recolher", "Collection": "Coleção", + "Collection Field": "", "Collections": "Coleções", "Color": "Cor", "ComfyUI": "ComfyUI", @@ -408,18 +450,20 @@ "ComfyUI Workflow": "Fluxo de trabalho ComfyUI", "ComfyUI Workflow Nodes": "Nós do fluxo de trabalho ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "IDs de Nodes separados por vírgula (por exemplo, 1 ou 1,2)", - "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", + "Comma-separated group names": "", + "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "Lista de extensões de arquivo separadas por vírgulas que o MinerU processará (por exemplo, pdf, docx, pptx, xlsx)", "command": "comando", "Command": "Comando", "Comment": "Comentário", "Commit Message": "Mensagem de Commit", "Community Reviews": "Avaliações da comunidade", - "Comparing with knowledge base...": "", + "Compacting context": "", + "Comparing with knowledge base...": "Comparando com a base de conhecimento...", "Completions": "Completions", "Compress Images in Channels": "Comprimir imagens em canais", - "Computing checksums ({{count}} files)_one": "", - "Computing checksums ({{count}} files)_many": "", - "Computing checksums ({{count}} files)_other": "", + "Computing checksums ({{count}} files)_one": "Calculando checksums ({{count}} arquivo)", + "Computing checksums ({{count}} files)_many": "Calculando checksums ({{count}} arquivos)", + "Computing checksums ({{count}} files)_other": "Calculando checksums ({{count}} arquivos)", "Concurrent Requests": "Solicitações simultâneas", "Config": "Configuração", "Config imported successfully": "Configuração importada com sucesso", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Conecte-se a instâncias do Open Terminal. Todos os usuários terão acesso à navegação de arquivos e ferramentas de terminal por meio desses servidores.", "Connect to your own OpenAI compatible API endpoints.": "Conecte-se aos seus próprios endpoints de API compatíveis com OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Conecte-se aos seus próprios servidores de ferramentas externas compatíveis com OpenAPI.", + "Connected": "", "Connected ({{type}})": "Conectado ({{type}})", "Connection failed": "Falha na conexão", "Connection lost. Reconnecting...": "Conexão perdida. Reconectando...", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contate o Administrador para verificar seu acesso", "Content": "Conteúdo", "Content Extraction Engine": "Mecanismo de Extração de Conteúdo", + "Content Field": "", "Content lengths (character counts only)": "Extensão do conteúdo (apenas em caracteres)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Tokens de Contexto", + "Continue": "", "Continue Response": "Continuar Resposta", "Continue with {{provider}}": "Continuar com {{provider}}", "Continue with Email": "Continuar com Email", @@ -497,6 +550,7 @@ "Create new secret key": "Criar nova chave secreta", "Create note": "Criar nota", "Create Note": "Criar Nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Crie prompts agendados que sejam executados automaticamente de forma recorrente.", "Create your first note by clicking on the plus button below.": "Crie sua primeira nota clicando no botão de adição abaixo.", "Created at": "Criado em", @@ -514,6 +568,7 @@ "Custom Gender": "Gênero personalizado", "Custom Parameter Name": "Nome do parâmetro personalizado", "Custom Parameter Value": "Valor do parâmetro personalizado", + "Custom range": "", "Daily": "Diário", "Daily Messages": "Mensagens Diárias", "Danger Zone": "Zona de Perigo", @@ -536,7 +591,6 @@ "Default Features": "Recursos padrão", "Default Filters": "Filtros padrão", "Default Group": "Grupo padrão", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "O modo padrão funciona com uma gama mais ampla de modelos, chamando as ferramentas uma vez antes da execução. O modo nativo aproveita os recursos integrados de chamada de ferramentas do modelo, mas exige que o modelo suporte esse recurso inerentemente.", "Default Model": "Modelo Padrão", "Default model updated": "Modelo padrão atualizado", "Default permissions": "Permissões padrão", @@ -546,20 +600,21 @@ "Default to ALL": "Padrão para TODOS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Use a recuperação segmentada como padrão para extração de conteúdo focado e relevante; isso é recomendado para a maioria dos casos.", "Default User Role": "Padrão para novos usuários", + "Default webhook": "", "Defaults": "Padrões", "Delete": "Excluir", "Delete {{name}}": "Excluir {{name}}", "Delete a model": "Excluir um modelo", "Delete All": "Excluir tudo", "Delete All Chats": "Excluir Todos os Chats", - "Delete all contents inside this directory": "", + "Delete all contents inside this directory": "Excluir todo o conteúdo deste diretório", "Delete all contents inside this folder": "Apague todo o conteúdo desta pasta.", "Delete automation?": "Excluir automação?", "Delete calendar": "Excluir calendário", "Delete Calendar": "Excluir Calendário", "Delete Chat": "Excluir Chat", "Delete chat?": "Excluir chat?", - "Delete directory?": "", + "Delete directory?": "Excluir diretório?", "Delete Event": "Excluir Evento", "Delete File": "Excluir arquivo", "Delete folder?": "Excluir pasta?", @@ -596,16 +651,18 @@ "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "As conexões diretas permitem que os usuários se conectem aos seus próprios endpoints de API compatíveis com OpenAI.", "Direct Message": "Mensagem direta", "Direct Tool Servers": "Servidores de ferramentas diretas", - "Directory created.": "", - "Directory deleted.": "", - "Directory moved.": "", - "Directory name": "", - "Directory renamed.": "", + "Directory created.": "Diretório criado.", + "Directory deleted.": "Diretório excluído.", + "Directory moved.": "Diretório movido.", + "Directory name": "Nome do diretório", + "Directory renamed.": "Diretório renomeado.", "Directory selection was cancelled": "A seleção do diretório foi cancelada", "Disable All": "Desativar tudo", "Disable Code Interpreter": "Desativar o interpretador de código", "Disable Image Extraction": "Desativar extração de imagem", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Desabilite a extração de imagens do PDF. Se a opção Usar LLM estiver habilitada, as imagens serão legendadas automaticamente. O padrão é Falso.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Desativado", "Disconnect OAuth": "Desconectar OAuth", "Discover a function": "Descubra uma função", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelos", "Discussion channel where access is based on groups and permissions": "Canal de discussão onde o acesso é baseado em grupos e permissões.", "Display": "Exibir", - "Display chat title in tab": "Exibir título do chat na aba", + "Display Chat Title in Tab": "Exibir título do chat na aba", "Display Emoji in Call": "Exibir Emoji na Chamada", "Display Multi-model Responses in Tabs": "Exibir respostas de vários modelos em guias", - "Display the username instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Chat", + "Display the Username Instead of You in the Chat": "Exibir o nome de usuário em vez de Você no Chat", "Displays citations in the response": "Exibir citações na resposta", "Displays status updates (e.g., web search progress) in the response": "Exibe atualizações de status (por exemplo, progresso da pesquisa na web) na resposta", "Dive into knowledge": "Explorar base de conhecimento", @@ -634,6 +691,7 @@ "Docling Parameters": "Parâmetros Docling", "Docling Server URL required.": "URL do servidor Docling necessária.", "Document": "Documento", + "Document ID Field": "", "Document Intelligence": "Inteligência de documentos", "Document Intelligence endpoint required.": "É necessário o endpoint do Document Intelligence.", "Document Intelligence Model": "Modelo de Inteligência de Documentos", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Editar Permissões Padrão", "Edit Folder": "Editar Pasta", "Edit Image": "Editar imagem", + "Edit Knowledge Connection": "", "Edit Last Message": "Editar última mensagem", "Edit Memory": "Editar Memória", "Edit Prompt": "Editar prompt", "Edit Terminal Connection": "Editar Conexão de Terminal", "Edit User": "Editar Usuário", "Edit User Group": "Editar Grupo de Usuários", + "Edit webhook": "", "Edit workflow.json content": "Editar conteúdo do workflow.json", "edited": "editado", "Edited": "Editado", @@ -703,14 +763,16 @@ "Eject model": "Ejetar modelo", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Embarque em aventuras", "Embedding": "Embedding", "Embedding Batch Size": "Tamanho do Lote de Embedding", "Embedding Concurrent Requests": "Solicitações Simultâneas de Embedding", "Embedding Model": "Modelo de Embedding", "Embedding Model Engine": "Motor do Modelo de Embedding", - "Emoji": "", + "Emoji": "Emoji", "Emojis": "Emojis", + "Empty": "", "Empty message": "Mensagem vazia", "Enable All": "Ativar tudo", "Enable API Keys": "Habilitar Chaves de API", @@ -718,22 +780,27 @@ "Enable Code Execution": "Habilitar execução de código", "Enable Code Interpreter": "Habilitar intérprete de código", "Enable Community Sharing": "Ativar Compartilhamento com a Comunidade", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Habilite o bloqueio de memória (mlock) para evitar que os dados do modelo sejam transferidos da RAM para a área de troca (swap). Essa opção bloqueia o conjunto de páginas em uso pelo modelo na RAM, garantindo que elas não sejam transferidas para o disco. Isso pode ajudar a manter o desempenho, evitando falhas de página e garantindo acesso rápido aos dados.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Habilite o mapeamento de memória (mmap) para carregar dados do modelo. Esta opção permite que o sistema use o armazenamento em disco como uma extensão da RAM, tratando os arquivos do disco como se estivessem na RAM. Isso pode melhorar o desempenho do modelo, permitindo acesso mais rápido aos dados. No entanto, pode não funcionar corretamente com todos os sistemas e consumir uma quantidade significativa de espaço em disco.", "Enable Message Queue": "Habilitar fila de mensagens", "Enable Message Rating": "Ativar Avaliação de Mensagens", "Enable Mirostat sampling for controlling perplexity.": "Habilitar amostragem Mirostat para controlar a perplexidade.", "Enable New Sign Ups": "Ativar Novos Cadastros", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Habilite, desabilite ou personalize as tags de raciocínio usadas pelo modelo. \"Ativado\" usa tags padrão, \"Desativado\" desativa as tags de raciocínio e \"Personalizado\" permite que você especifique suas próprias tags de início e fim.", "Enabled": "Ativado", "End Tag": "Tag final", + "Endpoint": "", "Endpoint URL": "URL do Endpoint", "Enforce Temporary Chat": "Aplicar chat temporário", "Enhance": "Melhorar", "Enrich Hybrid Search Text": "Enriquecer o texto da pesquisa híbrida", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Certifique-se de que seu arquivo CSV inclua 4 colunas nesta ordem: Nome, Email, Senha, Função.", "Enter {{role}} message here": "Digite a mensagem de {{role}} aqui", - "Enter a detail about yourself for your LLMs to recall": "Digite um detalhe sobre você para seus LLMs lembrarem", "Enter a title for the pending user info overlay. Leave empty for default.": "Insira um título para a sobreposição de informações pendentes do usuário. Deixe em branco como padrão.", "Enter a watermark for the response. Leave empty for none.": "Insira uma marca d'água para a resposta. Deixe em branco se não houver nenhuma.", "Enter additional headers in JSON format": "Insira cabeçalhos adicionais no formato JSON", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Insira o tamanho mínimo desejado para cada bloco.", "Enter Chunk Overlap": "Digite a Sobreposição de Chunk", "Enter Chunk Size": "Digite o Tamanho do Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Insira pares \"token:bias_value\" separados por vírgulas (exemplo: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Insira o conteúdo para a sobreposição de informações pendentes do usuário. Deixe em branco para o padrão.", "Enter coordinates (e.g. 51.505, -0.09)": "Insira as coordenadas (por exemplo, 51,505, -0,09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Insira a URL do Jupyter", "Enter Kagi Search API Key": "Insira a chave da API de pesquisa do Kagi", "Enter Key Behavior": "Comportamento da tecla Enter", + "Enter language": "", "Enter language codes": "Digite os códigos de idioma", - "Enter Linkup API Key": "", + "Enter Linkup API Key": "Insira a chave da API Linkup", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Insira a chave da API do MinerU", "Enter Mistral API Base URL": "Insira a URL base da API Mistral", "Enter Mistral API Key": "Insira a chave da API Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "Insira o prompt aqui.", "Enter proxy URL (e.g. https://user:password@host:port)": "Insira a URL do proxy (por exemplo, https://usuário:senha@host:porta)", "Enter reasoning effort": "Insira o esforço de raciocínio", + "Enter Redirect URI": "", "Enter Score": "Digite a Pontuação", "Enter SearchApi API Key": "Digite a Chave API do SearchApi", "Enter SearchApi Engine": "Digite o Motor do SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Insira a chave da API SerpApi", "Enter SerpApi Engine": "Digite o mecanismo/engine SerpApi", "Enter Serper API Key": "Digite a Chave API do Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Digite a Chave API do Serply", "Enter Serpstack API Key": "Digite a Chave API do Serpstack", "Enter server host": "Digite o host do servidor", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Digite a URL do Servidor Tika", "Enter timeout in seconds": "Insira o tempo limite em segundos", "Enter to Send": "Enter para Enviar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Digite o Top K", "Enter Top K Reranker": "Digite o Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Digite a URL (por exemplo, http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Erro: Já existe um modelo com o ID '{{modelId}}'. Selecione um ID diferente para prosseguir.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Erro: O ID do modelo não pode estar vazio. Insira um ID válido para prosseguir.", "Evaluations": "Avaliações", + "Event": "", "Event created": "Evento criado", "Event deleted": "Evento excluído", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Título do evento", "Event updated": "Evento atualizado", + "Events": "", "Exa API Key": "Chave da API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemplo: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemplo: ALL", "Example: mail": "Exemplo: mail", @@ -909,12 +989,18 @@ "Export Config": "Exportar Configuração", "Export Models": "Exportar Modelos", "Export Prompts": "Exportar Prompts", + "Export Skills": "", "Export to CSV": "Exportar para CSV", "Export Tools": "Exportar Ferramentas", "Export Users": "Exportar Usuários", "External": "Externo", + "External connection not found.": "", "External Document Loader URL required.": "URL do carregador de documentos externo necessária.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Modelo de Tarefa Externa", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Chave de API do carregador da Web externo", "External Web Loader URL": "URL do carregador da Web externo", "External Web Search API Key": "Chave de API de pesquisa na Web externa", @@ -925,13 +1011,14 @@ "Failed to archive chat.": "Falha ao arquivar o chat.", "Failed to attach file": "Falha ao anexar arquivo", "Failed to clear status": "Falha ao limpar o status", - "Failed to compare files.": "", + "Failed to compare files.": "Falha ao comparar arquivos.", "Failed to connect to {{URL}} OpenAPI tool server": "Falha ao conectar ao servidor da ferramenta OpenAPI {{URL}}", "Failed to connect to {{URL}} terminal server": "Falha ao conectar ao servidor de terminal {{URL}}", "Failed to copy link": "Falha ao copiar o link", "Failed to create API Key.": "Falha ao criar a Chave API.", "Failed to delete calendar": "Falha ao excluir calendário", "Failed to delete note": "Falha ao excluir a nota", + "Failed to delete webhook": "", "Failed to disconnect": "Falha ao desconectar", "Failed to download image": "Falha ao baixar a imagem", "Failed to extract content from the file: {{error}}": "Falha ao extrair conteúdo do arquivo: {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Falha ao buscar modelos", "Failed to generate title": "Falha ao gerar título", "Failed to import models": "Falha ao importar modelos", + "Failed to load chat": "", "Failed to load chat preview": "Falha ao carregar a pré-visualização do chat", "Failed to load DOCX file. Please try downloading it instead.": "Não foi possível carregar o arquivo DOCX. Tente baixá-lo em vez disso.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Não foi possível carregar o arquivo Excel/CSV. Tente baixá-lo em vez disso.", @@ -948,6 +1036,7 @@ "Failed to move chat": "Falha ao mover o chat", "Failed to process URL: {{url}}": "Falha ao processar URL: {{url}}", "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Falha ao remover membro", "Failed to render diagram": "Falha ao renderizar o diagrama", "Failed to render visualization": "Falha ao renderizar a visualização", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Falha ao salvar a configuração dos modelos", "Failed to save policy: {{error}}": "Falha ao salvar a política: {{error}}", "Failed to save terminal servers": "Falha ao salvar servidores de terminal", + "Failed to save webhook": "", "Failed to unshare chat.": "Falha ao cancelar o compartilhamento da conversa.", "Failed to update settings": "Falha ao atualizar as configurações", "Failed to update status": "Falha ao atualizar o status", + "Failed to update webhook": "", "Failed to upload file.": "Falha ao carregar o arquivo.", "Features": "Funcionalidades", "Features Permissions": "Permissões das Funcionalidades", @@ -979,18 +1070,20 @@ "File content updated successfully.": "Conteúdo do arquivo atualizado com sucesso.", "File Context": "Contexto do arquivo", "File deleted successfully.": "Arquivo excluído com sucesso.", - "File Extensions": "", + "File Extensions": "Extensões de arquivo", "File Mode": "Modo de Arquivo", - "File moved.": "", + "File moved.": "Arquivo movido.", "File name": "Nome do arquivo", "File not found.": "Arquivo não encontrado.", "File removed successfully.": "Arquivo removido com sucesso.", - "File renamed.": "", + "File renamed.": "Arquivo renomeado.", "File size should not exceed {{maxSize}} MB.": "Arquivo não pode exceder {{maxSize}} MB.", "File Upload": "Upload de arquivo", "File uploaded successfully": "Arquivo carregado com sucesso", "Filename": "Nome do arquivo", "Files": "Arquivos", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtro", "Filter is now globally disabled": "O filtro está agora desativado globalmente", "Filter is now globally enabled": "O filtro está agora ativado globalmente", @@ -1013,6 +1106,7 @@ "Folder options": "Opções da pasta", "Folder updated successfully": "Pasta atualizada com sucesso", "Folders": "Pastas", + "Folders Sharing": "", "Follow up": "Acompanhamento", "Follow Up Generation": "Geração de Acompanhamento", "Follow Up Generation Prompt": "Prompt para Geração dos Acompanhamentos", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "A função está agora ativada globalmente", "Function Name": "Nome da Função", "Function Name Filter List": "Lista de filtros de nomes de funções", + "Function starter": "", "Function updated successfully": "Função atualizada com sucesso", "Functions": "Funções", "Functions allow arbitrary code execution.": "Funções permitem a execução arbitrária de código.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Grade", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Canal do grupo", + "Group Claim": "", "Group created successfully": "Grupo criado com sucesso", "Group deleted successfully": "Grupo excluído com sucesso", "Group Description": "Descrição do Grupo", @@ -1087,6 +1185,7 @@ "H2": "Subtítulo", "H3": "Sub-subtítulo", "Haptic Feedback": "Feedback Tátil", + "Header variables": "", "Headers": "Cabeçalhos", "Headers must be a valid JSON object": "Os cabeçalhos devem ser um objeto JSON válido", "Height": "Altura", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "O ID não pode conter caracteres \":\" ou \"|\"", "ID copied to clipboard": "ID copiado para a área de transferência", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Tempo Limite de Inatividade", "iframe Sandbox Allow Forms": "Permitir formulários no sandbox do iframe", "iframe Sandbox Allow Same Origin": "Permitir mesma origem no sandbox do iframe", @@ -1142,6 +1243,7 @@ "Import From Link": "Importar do link", "Import Models": "Importar Modelos", "Import Prompts": "Importar Prompts", + "Import Skills": "", "Import successful": "Importação bem-sucedida", "Import Tools": "Importar Ferramentas", "Important Update": "Atualização importante", @@ -1199,12 +1301,11 @@ "Keep in Sidebar": "Manter na barra lateral", "Key": "Chave", "Key is required": "Chave é obrigatória", - "Keyboard shortcuts": "Atalhos de Teclado", "Keyboard Shortcuts": "Atalhos de teclado", "Knowledge": "Conhecimento", "Knowledge Access": "Acesso ao Conhecimento", "Knowledge Base": "Base de Conhecimento", - "Knowledge base has been reset": "", + "Knowledge base has been reset": "A base de conhecimento foi redefinida", "Knowledge created successfully.": "Conhecimento criado com sucesso.", "Knowledge deleted successfully.": "Conhecimento excluído com sucesso.", "Knowledge Description": "Descrição da Base de Conhecimento", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Nome da Base de Conhecimento", "Knowledge Public Sharing": "Compartilhamento Público da Base de Conhecimento", "Knowledge Sharing": "Compartilhamento da Base de Conhecimento", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Conhecimento atualizado com sucesso", "Kokoro.js (Browser)": "Kokoro.js (Navegador)", "Kokoro.js Dtype": "Dtype do Kokoro.js", @@ -1228,7 +1331,6 @@ "Last ran": "Última execução", "Last reply": "Última resposta", "LDAP": "LDAP", - "LDAP server updated": "Servidor LDAP atualizado", "Leaderboard": "Tabela de classificação", "Learn more": "Saiba mais", "Learn More": "Saiba Mais", @@ -1250,11 +1352,12 @@ "Legacy": "Legado", "lexical": "lexical", "License": "Licença", + "Lifecycle JSON": "", "Lift List": "Lista de elevação", "Light": "Claro", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limitar consultas de pesquisa simultâneas. 0 = ilimitado (padrão). Defina como 1 para execução sequencial (recomendado para APIs com limites de taxa rígidos, como o nível gratuito do Brave).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "Limita o número de solicitações simultâneas de embedding. Defina como 0 para ilimitado.", - "Linkup API Key": "", + "Linkup API Key": "Chave da API Linkup", "List": "Lista", "List calendars, search, create, update, and delete calendar events": "Listar calendários, pesquisar, criar, atualizar e excluir eventos do calendário", "Listening...": "Escutando...", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Acesso ao local não permitido", "Lost": "Perdeu", "Low": "Baixo", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "Esquerda para Direita", "Made by Open WebUI Community": "Feito pela Comunidade OpenWebUI", "Make password visible in the user interface": "Tornar a senha visível na interface do usuário", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gerenciar Pipelines", "Manage Tool Servers": "Gerenciar servidores de ferramentas", "Manage your account information.": "Gerencie as informações da sua conta.", + "Mapped Source": "", "March": "Março", "Markdown": "Markdown", "Markdown Header Text Splitter": "Separador de texto de cabeçalho Markdown", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memória limpa com sucesso", "Memory deleted successfully": "Memória excluída com sucesso", "Memory updated successfully": "Memória atualizada com sucesso", + "Merge Accounts by Email": "", "Merge Responses": "Mesclar respostas", "Merged Response": "Resposta Mesclada", "Message": "Mensagem", @@ -1326,9 +1432,12 @@ "messages": "mensagens", "Messages": "Mensagens", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens enviadas após criar seu link não serão compartilhadas. Usuários com o URL poderão visualizar o chat compartilhado.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (pessoal)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (trabalho/escola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Chave de API MinerU necessária para o modo Cloud API.", @@ -1381,6 +1490,7 @@ "Models Sharing": "Compartilhamento de Modelos", "Mojeek": "Mojeek", "Mojeek Search API Key": "Chave de API Mojeek Search", + "Monday – Friday": "", "Month": "Mês", "Monthly": "Mensal", "More": "Mais", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nome da sua base de conhecimento", "Name, prompt, and model are required": "Nome, prompt e modelo são obrigatórios.", "Native": "Nativo", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Nunca", "New": "Novo", "New Automation": "Nova Automação", @@ -1405,8 +1516,8 @@ "New calendar": "Novo calendário", "New Calendar": "Novo Calendário", "New Chat": "Novo Chat", - "New directory": "", - "New Directory": "", + "New directory": "Novo diretório", + "New Directory": "Novo Diretório", "New Event": "Novo Evento", "New File": "Novo Arquivo", "New Folder": "Nova Pasta", @@ -1427,6 +1538,7 @@ "Next run": "Próxima execução", "No access grants. Private to you.": "Sem permissões de acesso. Privacidade exclusiva para você.", "No activity data": "Sem dados de atividade", + "No additional headers are sent unless configured.": "", "No authentication": "Sem autenticação", "No automations found": "Nenhuma automação encontrada", "No chats found": "Nenhum chat encontrado", @@ -1439,8 +1551,10 @@ "No data": "Sem dados", "No data found": "Nenhum dado encontrado", "No distance available": "Sem distância disponível", + "No event webhooks configured.": "", "No execution logs available yet": "Ainda não há registros de execução disponíveis.", "No expiration can pose security risks.": "A ausência de expiração pode representar riscos de segurança.", + "No external knowledge sources configured.": "", "No feedback found": "Nenhum feedback encontrado", "No file selected": "Nenhum arquivo selecionado", "No files found": "Nenhum arquivo encontrado", @@ -1452,13 +1566,13 @@ "No HTML, CSS, or JavaScript content found.": "Nenhum conteúdo HTML, CSS ou JavaScript encontrado.", "No inference engine with management support found": "Nenhum mecanismo de inferência com suporte de gerenciamento encontrado", "No kernel": "Sem kernel", - "No knowledge bases accessible": "", + "No knowledge bases accessible": "Nenhuma base de conhecimento acessível", "No knowledge bases found.": "Nenhuma base de conhecimento encontrada.", "No knowledge found": "Nenhum conhecimento encontrado", "No limit": "Sem limite", "No memories to clear": "Nenhuma memória para limpar", "No model IDs": "Nenhum ID de modelo", - "No models accessible": "", + "No models accessible": "Nenhum modelo acessível", "No models available": "Nenhum modelo disponível", "No models found": "Nenhum modelo encontrado", "No models selected": "Nenhum modelo selecionado", @@ -1468,6 +1582,7 @@ "No output items": "Nenhum item de saída", "No pinned messages": "Nenhuma mensagem fixada", "No prompts found": "Nenhum prompt encontrado", + "No Repeat": "", "No results": "Nenhum resultado encontrado", "No results found": "Nenhum resultado encontrado", "No search query generated": "Nenhuma consulta de pesquisa gerada", @@ -1479,7 +1594,7 @@ "No Terminal connection configured.": "Nenhuma conexão de Terminal configurada.", "No terminal connections configured.": "Nenhuma conexão de terminal configurada.", "No tool server connections configured.": "Nenhuma conexão de servidor de ferramentas configurada.", - "No tools accessible": "", + "No tools accessible": "Nenhuma ferramenta acessível", "No tools found": "Nenhuma ferramenta encontrada", "No users were found.": "Nenhum usuário foi encontrado.", "No valves": "Sem configurações", @@ -1487,6 +1602,7 @@ "No webhooks yet": "Ainda não há webhooks", "Node Ids": "IDs dos nós", "None": "Nenhum", + "Not configured": "", "Not factually correct": "Não está factualmente correto", "Not helpful": "Não é útil", "Not Registered": "Não registrado", @@ -1502,24 +1618,29 @@ "Notifications": "Notificações", "November": "Novembro", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Estático)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL do Servidor OAuth", "OAuth session disconnected": "Sessão OAuth desconectada", "October": "Outubro", "Off": "Desligado", "Okay, Let's Go!": "Ok, Vamos Lá!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Escuro", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Configurações da API Ollama atualizadas", "Ollama Cloud API Key": "Chave da API Ollama Cloud", "Ollama Version": "Versão Ollama", + "Omit": "", "On": "Ligado", "Once": "Uma vez", "OneDrive": "OneDrive", - "Only active during Voice Mode.": "", + "Only active during Voice Mode.": "Ativo somente durante o Modo de Voz.", "Only active when \"Paste Large Text as File\" setting is toggled on.": "Ativo somente quando a configuração \"Colar texto grande como arquivo\" estiver ativada.", "Only active when the chat input is in focus and an LLM is generating a response.": "Ativo somente quando o campo de entrada do chat está em foco e um LLM está gerando uma resposta.", "Only active when the chat input is in focus.": "Ativo somente quando o campo de entrada do chat estiver em foco.", @@ -1586,26 +1707,30 @@ "Password": "Senha", "Passwords do not match.": "As senhas não coincidem.", "Paste Large Text as File": "Cole Textos Longos como Arquivo", + "Path": "", "Path copied": "Caminho copiado", "Paused": "Em pausa", "PDF document (.pdf)": "Documento PDF (.pdf)", "PDF Extract Images (OCR)": "Extrair Imagens do PDF (OCR)", "PDF Loader Mode": "Modo de carregamento de PDF", - "pdf, docx, pptx, xlsx": "", + "pdf, docx, pptx, xlsx": "pdf, docx, pptx, xlsx", "pending": "pendente", "Pending": "Pendente", + "Pending Accounts": "", "Pending User Overlay Content": "Conteúdo de sobreposição de usuário pendente", "Pending User Overlay Title": "Título de sobreposição de usuário pendente", "Permission denied when accessing media devices": "Permissão negada ao acessar dispositivos de mídia", "Permission denied when accessing microphone": "Permissão negada ao acessar o microfone", "Permission denied when accessing microphone: {{error}}": "Permissão negada ao acessar o microfone: {{error}}", "Permissions": "Permissões", + "Permissions reset to defaults": "", "Perplexity API Key": "Chave API da Perplexity", "Perplexity Model": "Modelo Perplexity", "Perplexity Search API URL": "URL da API de pesquisa Perplexity", "Perplexity Search Context Usage": "Uso do contexto de pesquisa do Perplexity", "Persistent": "Persistente", "Personalization": "Personalização", + "Picture Claim": "", "Pin": "Fixar", "Pin to Sidebar": "Fixar na barra lateral", "Pinned": "Fixado", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Por favor, preencha todos os campos.", "Please register the OAuth client": "Por favor, registre o cliente OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Salve a conexão para persistir as informações do cliente OAuth e não altere o ID", - "Please select a model first.": "Selecione um modelo primeiro.", "Please select a model.": "Selecione um modelo.", "Please select a reason": "Por favor, selecione um motivo", "Please select a valid JSON file": "Selecione um arquivo JSON válido", "Please select at least one user for Direct Message channel.": "Por favor, selecione pelo menos um usuário para o canal de Mensagens Diretas.", "Please wait until all files are uploaded.": "Aguarde até que todos os arquivos sejam enviados.", "Policy ID": "ID da Política", + "Policy ID is required": "", "Port": "Porta", "Ports": "Portas", "Positive attitude": "Atitude positiva", @@ -1653,7 +1778,7 @@ "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "O ID de prefixo é utilizado para evitar conflitos com outras conexões, adicionando um prefixo aos IDs dos modelos - deixe em branco para desativar.", "Prevent File Creation": "Impedir a criação de arquivos", "Preview": "Visualização", - "Preview Access": "", + "Preview Access": "Acesso de Visualização", "Previous 30 days": "Últimos 30 dias", "Previous 7 days": "Últimos 7 dias", "Previous message": "Mensagem anterior", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Compartilhamento Público dos Prompts", "Prompts Sharing": "Compartilhamento de Prompts", "Provider": "Provedor", + "Provider Name": "", + "Provider URL": "", "Public": "Público", "Pull \"{{searchValue}}\" from Ollama.com": "Obter \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obter um modelo de Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Ler", "Read Aloud": "Ler em Voz Alta", "Read more →": "Leia mais →", + "Read only": "", "Read Only": "Somente leitura", "Read-Only Access": "Acesso somente leitura", "Reason": "Razão", "Reasoning Effort": "Esforço de raciocínio", "Reasoning Tags": "Tags de raciocínio", "Reasoning text...": "Texto de raciocínio...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Usado recentemente", "Reconnected": "Reconectado", "Record": "Gravar", "Record voice": "Gravar voz", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirecionando você para a Comunidade OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Reduz a probabilidade de gerar respostas sem sentido. Um valor mais alto (por exemplo, 100) resultará em respostas mais diversas, enquanto um valor mais baixo (por exemplo, 10) será mais conservador.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refira-se como \"Usuário\" (por exemplo, \"Usuário está aprendendo espanhol\")", "Reference Chats": "Chats de Referência", "Refresh": "Atualizar", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Recusado quando não deveria", "Regenerate": "Gerar novamente", "Regenerate Menu": "Regenerar Menu", @@ -1731,28 +1867,35 @@ "Remove from favorites": "Remover dos favoritos", "Remove image": "Remover imagem", "Remove Model": "Remover Modelo", - "Removing {{count}} stale files..._one": "", - "Removing {{count}} stale files..._many": "", - "Removing {{count}} stale files..._other": "", + "Removing {{count}} stale files..._one": "Removendo {{count}} arquivo obsoleto...", + "Removing {{count}} stale files..._many": "Removendo {{count}} arquivos obsoletos...", + "Removing {{count}} stale files..._other": "Removendo {{count}} arquivos obsoletos...", "Rename": "Renomear", "Renamed to {{name}}": "Renomeado para {{name}}", - "Render Markdown in Assistant Messages": "", + "Render Markdown in Assistant Messages": "Renderizar Markdown nas Mensagens do Assistente", "Render Markdown in Previews": "Renderizar Markdown nas Pré-visualizações", - "Render Markdown in User Messages": "", + "Render Markdown in User Messages": "Renderizar Markdown nas Mensagens do Usuário", "Reorder Models": "Reordenar modelos", + "Repeat": "", "Repeats": "Repetições", "Reply": "Responder", "Reply in Thread": "Responder no tópico", "Reply to thread...": "Responder ao tópico...", "Replying to {{NAME}}": "Respondendo para {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "obrigatório", "Reranking Batch Size": "Tamanho do lote de reclassificação", "Reranking Engine": "Motor de Reclassificação", "Reranking Model": "Modelo de Reclassificação", + "Research Knowledge": "", "Reset": "Redefinir", "Reset All Models": "Redefinir todos os modelos", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Redefinir imagem", - "Reset knowledge base?": "", + "Reset knowledge base?": "Redefinir base de conhecimento?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Redefinir Diretório de Upload", "Reset Vector Storage/Knowledge": "Redefinir Armazenamento de Vetores/Conhecimento", "Reset view": "Redefinir visualização", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "1 fonte recuperada", "Rich Text Input for Chat": "Entrada de rich text para o chat", "Role": "Função", + "Roles Claim": "", "RTL": "Direita para Esquerda", "Run": "Executar", "Run All": "Executar Tudo", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvar registros de chat diretamente no armazenamento do seu navegador não é mais suportado. Por favor, reserve um momento para baixar e excluir seus registros de chat clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar seus registros de chat para o backend através de", "Schedule": "Agendar", "Scheduled time must be in the future": "O horário agendado deve ser no futuro.", + "Scopes": "", "Scroll On Branch Change": "Rolar na mudança de ramo", "Scroll to Top": "Rolar para o topo", "Search": "Pesquisar", "Search a model": "Pesquisar um modelo", + "Search actions": "", "Search all emojis": "Pesquisar todos os emojis", "Search and manage user memories": "Pesquisar e gerenciar memórias de usuários", "Search and view user chat history": "Pesquise e visualize o histórico de chat do usuário", @@ -1804,6 +1950,7 @@ "Search Chats": "Pesquisar Chats", "Search Collection": "Pesquisar Coleção", "Search Files": "Pesquisar arquivos", + "Search filters": "", "Search Filters": "Pesquisar Filtros", "search for archived chats": "pesquisar por chats arquivados", "search for folders": "procurar pastas", @@ -1818,13 +1965,16 @@ "Search Models": "Pesquisar Modelos", "Search Notes": "Pesquisar Notas", "Search options": "Opções de pesquisa", + "Search or add pattern": "", "Search Prompts": "Pesquisar Prompts", "Search Result Count": "Contagem de Resultados da Pesquisa", + "Search skills": "", "Search Skills": "Pesquisar Skills", - "Search skills...": "", "Search the internet": "Pesquisar na Internet", "Search the web and fetch URLs": "Pesquise na web e obtenha URLs", + "Search tools": "", "Search Tools": "Pesquisar Ferramentas", + "Search users or groups": "", "Search, view, and manage user notes": "Pesquise, visualize e gerencie notas do usuário.", "SearchApi API Key": "Chave API SearchApi", "SearchApi Engine": "Motor SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Seed", "Select": "Selecionar", "Select {{modelName}} model": "Selecionar modelo {{modelName}}", - "Select a base model": "Selecione um modelo base", "Select a base model (e.g. llama3, gpt-4o)": "Selecione um modelo base (por exemplo, llama3, gpt-4o)", "Select a conversation to preview": "Selecione uma conversa para visualizar", "Select a engine": "Selecione um motor", @@ -1878,18 +2027,25 @@ "semantic": "semântica", "Send": "Enviar", "Send a Message": "Enviar uma Mensagem", + "Send events for": "", "Send message": "Enviar mensagem", "Send now": "Enviar agora", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envia `stream_options: { include_usage: true }` na solicitação. Provedores compatíveis retornarão informações sobre o uso de tokens na resposta quando configurado.", "September": "Setembro", "SerpApi API Key": "Chave da API SerpApi", "SerpApi Engine": "Motor SerpApi", "Serper API Key": "Chave da API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Chave da API Serply", "Serpstack API Key": "Chave da API Serpstack", "Server connection failed": "Falha na conexão com o servidor", "Server connection verified": "Conexão com o servidor verificada", + "Service Account": "", "Session": "Sessão", + "Session expired. Please sign in again.": "", "Set as default": "Definir como padrão", "Set as Production": "Definir como Produção", "Set embedding model": "Definir modelo de embedding", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "Link de compartilhamento copiado para a área de transferência.", "Share to Open WebUI Community": "Compartilhar com a Comunidade OpenWebUI", "Share your background and interests": "Fale sobre você e seus interesses", + "Shared": "", "Shared Chats": "Chats compartilhados", "Shared with you": "Compartilhado com você", "Sharing Permissions": "Permissões de compartilhamento", "Show": "Mostrar", - "Show \"What's New\" modal on login": "Mostrar \"O que há de Novo\" no login", + "Show \"What's New\" Modal on Login": "Mostrar \"O que há de Novo\" no login", "Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na Sobreposição de Conta Pendentes", "Show All": "Mostrar Tudo", "Show all ({{COUNT}} characters)": "Mostrar todos os ({{COUNT}} caracteres)", "Show Files": "Mostrar arquivos", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Mostrar barra de ferramentas de formatação", "Show image preview": "Mostrar pré-visualização da imagem", "Show Model": "Mostrar modelo", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "sID da API de pesquisa Sougou", "Sougou Search API SK": "SK da API de pesquisa Sougou", "Source": "Fonte", + "Specific users or groups": "", "Speech Playback Speed": "Velocidade de reprodução de fala", "Speech recognition error: {{error}}": "Erro de reconhecimento de fala: {{error}}", "Speech-to-Text": "Fala-para-Texto", @@ -2006,6 +2165,7 @@ "STT Settings": "Configurações STT", "Stylized PDF Export": "Exportação de PDF estilizado", "Su_day_of_week": "Dom", + "Sub Claim": "", "Submit question": "Enviar pergunta", "Submit suggestion": "Enviar sugestão", "Subtitle": "Subtítulo", @@ -2020,8 +2180,8 @@ "Switch to JSON editor": "Mudar para editor JSON", "Switch to visual editor": "Mudar para editor visual", "Sync": "Sincronizar", - "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "", - "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "", + "Sync a local directory with this knowledge base. Only new and modified files will be uploaded. The directory structure will be mirrored.": "Sincronizar um diretório local com esta base de conhecimento. Apenas arquivos novos e modificados serão enviados. A estrutura de diretórios será espelhada.", + "Sync complete: {{added}} added, {{modified}} modified, {{deleted}} deleted, {{unmodified}} unmodified": "Sincronização concluída: {{added}} adicionados, {{modified}} modificados, {{deleted}} excluídos, {{unmodified}} não modificados", "Sync Complete!": "Sincronização concluída!", "Sync directory": "Sincronizar Diretório", "Sync Failed": "Falha na sincronização", @@ -2030,8 +2190,10 @@ "Syncing...": "Sincronizando...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sincroniza apenas as conversas com atualizações posteriores à sua última sincronização. Desative para sincronizar todas as conversas novamente.", "System": "Sistema", + "System events only": "", "System Instructions": "Instruções do sistema", "System Prompt": "Prompt do Sistema", + "Table": "", "Tag": "Tag", "Tags": "Tags", "Tags Generation": "Geração de tags", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Chat temporário por padrão", "Terminal": "Terminal", "Terminal servers saved": "Servidores de terminal salvos", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divisor de Texto", "Text-to-Speech": "Texto-para-Fala", "Text-to-Speech Engine": "Motor de Texto para Fala", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "O idioma do áudio de entrada. Fornecer o idioma de entrada no formato ISO-639-1 (por exemplo, en) aumentará a precisão e a latência. Deixe em branco para detectar o idioma automaticamente.", "The LDAP attribute that maps to the mail that users use to sign in.": "O atributo LDAP que mapeia o e-mail que os usuários usam para fazer login.", "The LDAP attribute that maps to the username that users use to sign in.": "O atributo LDAP que mapeia para o nome de usuário que os usuários usam para fazer login.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "A tabela de classificação está atualmente em beta, e podemos ajustar os cálculos de avaliação conforme refinamos o algoritmo.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Tamanho máximo do arquivo em MB. Se o tamanho do arquivo exceder este limite, o arquivo não será enviado.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "O número máximo de arquivos que podem ser utilizados de cada vez no chat. Se o número de arquivos exceder este limite, os arquivos não serão enviados.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Formato de saída para o texto. Pode ser 'json', 'markdown' ou 'html'. O padrão é 'markdown'.", @@ -2089,6 +2256,7 @@ "This folder is empty": "Esta pasta está vazia", "This is a default user permission and will remain enabled.": "Esta é uma permissão de usuário padrão e permanecerá ativada.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Esta é uma funcionalidade experimental, pode não funcionar como esperado e está sujeita a alterações a qualquer momento.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Este modelo não está disponível publicamente. Selecione outro modelo.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Esta opção controla por quanto tempo o modelo permanecerá carregado na memória após a solicitação (padrão: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Esta opção controla quantos tokens são preservados ao atualizar o contexto. Por exemplo, se definido como 2, os últimos 2 tokens do contexto da conversa serão mantidos. Preservar o contexto pode ajudar a manter a continuidade de uma conversa, mas pode reduzir a capacidade de responder a novos tópicos.", @@ -2101,7 +2269,7 @@ "This will delete all models including custom models": "Isto vai excluir todos os modelos, incluindo personalizados", "This will delete all models including custom models and cannot be undone.": "Isto vai excluir todos os modelos, incluindo personalizados e não pode ser desfeito.", "This will permanently delete the calendar \"{{name}}\" and all its events. This action cannot be undone.": "Esta ação excluirá permanentemente o calendário \"{{name}}\" e todos os seus eventos. Esta ação não pode ser desfeita.", - "This will remove all files and directories from this knowledge base. This action cannot be undone.": "", + "This will remove all files and directories from this knowledge base. This action cannot be undone.": "Isso removerá todos os arquivos e diretórios desta base de conhecimento. Esta ação não pode ser desfeita.", "Thorough explanation": "Explicação detalhada", "Thought": "Pensamento", "Thought for {{DURATION}}": "Pensado por {{DURATION}}", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Para saber mais sobre os endpoints disponíveis, visite nossa documentação.", "To select skills here, add them to the \"Skills\" workspace first.": "Para selecionar skills aqui, adicione-as primeiro ao espaço de trabalho \"Skills\".", "To select toolkits here, add them to the \"Tools\" workspace first.": "Para selecionar kits de ferramentas aqui, adicione-os ao espaço de trabalho \"Ferramentas\" primeiro.", - "Toast notifications for new updates": "Notificações de alerta para novas atualizações", + "Toast Notifications for New Updates": "Notificações de alerta para novas atualizações", "Today": "Hoje", "Today at": "Hoje em", "Today at {{LOCALIZED_TIME}}": "Hoje às {{LOCALIZED_TIME}}", @@ -2137,12 +2305,14 @@ "Toggle 1 source": "Alternar 1 origem", "Toggle details": "Alternar detalhes", "Toggle Dictation": "Alternar Ditado", - "Toggle Mute": "", + "Toggle Mute": "Alternar Mudo", "Toggle Sidebar": "Alternar barra lateral", "Toggle status history": "Alternar histórico de status", "Toggle whether current connection is active.": "Alterna se a conexão atual está ativa.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "A contagem de tokens é uma estimativa e pode não refletir o uso real da API.", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Muito detalhado", @@ -2191,14 +2361,19 @@ "Unpin": "Desfixar", "Unpin from Sidebar": "Desfixar da barra lateral", "Unravel secrets": "Desvendar segredos", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Cancelar compartilhamento do chat", "Unsupported file type.": "Tipo de arquivo não suportado.", "Untagged": "Sem tag", "Untitled": "Sem título", "Update": "Atualizar", "Update and Copy Link": "Atualizar e Copiar Link", + "Update Email": "", "Update for the latest features and improvements.": "Atualizar para as novas funcionalidades e melhorias.", + "Update Name": "", "Update password": "Atualizar senha", + "Update Picture": "", "Update your status": "Atualize seu status", "Updated": "Atualizado", "Updated at": "Atualizado em", @@ -2216,7 +2391,7 @@ "Upload Progress": "Progresso do Upload", "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progresso do upload: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Arquivos ou imagens carregados", - "Uploading {{current}}/{{total}}: {{file}}": "", + "Uploading {{current}}/{{total}}: {{file}}": "Enviando {{current}}/{{total}}: {{file}}", "Uploading...": "Enviando...", "URL": "URL", "URL is required": "URL é obrigatória", @@ -2225,22 +2400,28 @@ "Use": "Usar", "Use '#' in the prompt input to load and include your knowledge.": "Usar '#' no prompt para carregar e incluir seus conhecimentos.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Use o endpoint /v1/chat/completions em vez de /v1/audio/transcriptions para obter uma precisão potencialmente melhor.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Usar API de Chat Completions", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Use grupos para organizar seus usuários e atribuir permissões.", "Use LLM": "Usar LLM", "Use no proxy to fetch page contents.": "Não utilize proxy para buscar o conteúdo da página.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Use o proxy designado pelas variáveis de ambiente http_proxy e https_proxy para buscar o conteúdo da página.", + "Use Web Search?": "", "user": "usuário", "User": "Usuário", + "User Access": "", "User Activity": "Atividade do usuário", "User Groups": "Grupos de usuários", "User location successfully retrieved.": "Localização do usuário recuperada com sucesso.", "User menu": "Menu do usuário", - "User Preview": "", + "User Preview": "Visualização do Usuário", "User ratings (thumbs up/down)": "Avaliações dos usuários (polegar para cima/polegar para baixo)", "User Status": "Status do usuário", "User Webhooks": "Webhooks do usuário", "Username": "Nome do Usuário", + "Username Claim": "", "users": "usuários", "Users": "Usuários", "Uses DefaultAzureCredential to authenticate": "Usa DefaultAzureCredential para autenticar", @@ -2254,6 +2435,7 @@ "Valves updated": "Configurações atualizadas", "Valves updated successfully": "Configurações atualizadas com sucesso", "variable": "variável", + "Vector Field": "", "Verify Connection": "Verificar conexão", "Verify SSL Certificate": "Verificar certificado SSL", "Version": "Versão", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "Motor de carregamento da Web", "Web Search": "Pesquisa na Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Mecanismo de Busca na Web", "Web Search in Chat": "Pesquisa na Web no Chat", "Web Search Query Generation": "Geração de consulta de pesquisa na Web", + "Webhook deleted": "", "Webhook Name": "Nome do Webhook", - "Webhook URL": "URL do Webhook", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URLs de páginas da web", "WebUI Settings": "Configurações da WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "Chave da API de pesquisa Yandex", "Yandex Web Search config": "Configuração de pesquisa Yandex", "Yandex Web Search URL": "URL de pesquisa Yandex", + "Yearly": "", "Yesterday": "Ontem", "Yesterday at {{LOCALIZED_TIME}}": "Ontem às {{LOCALIZED_TIME}}", "You": "Você", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "Seu navegador não suporta a tag de vídeo.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Toda a sua contribuição irá diretamente para o desenvolvedor do plugin; o Open WebUI não retém nenhuma porcentagem. No entanto, a plataforma de financiamento escolhida pode ter suas próprias taxas.", "Your message text or inputs": "Seu texto de mensagem ou entradas", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Suas estatísticas de uso foram sincronizadas com sucesso.", "YouTube": "YouTube", "Youtube Language": "Idioma do YouTube", diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index 691b2c4dbb..d3c0d17d1b 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} linhas ocultas", "{{COUNT}} members": "{{COUNT}} membros", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} Fontes", + "{{count}} users_one": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} palavras", "{{COUNT}}d_time_ago": "há {{COUNT}} dias", "{{COUNT}}h_time_ago": "há {{COUNT}} horas", "{{COUNT}}m_time_ago": "há {{COUNT}} minutos", "{{COUNT}}w_time_ago": "há {{COUNT}} semanas", "{{COUNT}}y_time_ago": "há {{COUNT}} anos", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} às {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "A transferência de {{model}} foi cancelada", "{{modelName}} profile image": "Imagem de perfil de {{modelName}}", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Chats de {{user}}", "{{webUIName}} Backend Required": "Backend {{webUIName}} Necessário", "*Prompt node ID(s) are required for image generation": "*ID(s) do nó de prompt são necessários para a geração de imagem", + "1 group": "", "1 hour before": "", "1 Source": "Uma Fonte", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "há 1 minuto", @@ -60,6 +73,7 @@ "Access Control": "Controlo de Acesso", "Access Grants": "Concessões de Acesso", "Access List": "Lista de Acesso", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Acessível a todos os utilizadores", "Account": "Conta", @@ -75,6 +89,7 @@ "Activity": "Atividade", "Add": "Adicionar", "Add a model ID": "Adicionar um ID de modelo", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Adicione uma breve descrição sobre o que este modelo faz", "Add a tag": "Adicionar uma tag", "Add a tag...": "Adicionar uma tag...", @@ -87,8 +102,10 @@ "Add Custom Prompt": "Adicionar Prompt Personalizado", "Add description": "", "Add Details": "Adicionar Detalhes", + "Add durable context for future chats": "", "Add Files": "Adicionar Ficheiros", "Add Image": "Adicionar Imagem", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "Adicionar Membro", "Add Members": "Adicionar Membros", @@ -103,6 +120,7 @@ "Add to favorites": "Adicionar aos favoritos", "Add User": "Adicionar Utilizador", "Add User Group": "Adicionar Grupo de Utilizadores", + "Add webhook": "", "Add webpage": "Adicionar página web", "Add your Open Terminal URL and API key in Settings → Integrations.": "Adicione o URL do Open Terminal e a chave API em Configurações → Integrações.", "Additional Config": "Configuração Adicional", @@ -115,7 +133,9 @@ "Admin": "Admin", "Admin Contact Email": "Email de Contacto do Administrador", "Admin Panel": "Painel do Administrador", + "Admin Roles": "", "Admin Settings": "Configurações do Administrador", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Os administradores têm acesso a todas as ferramentas em todos os momentos; os utilizadores precisam de ferramentas atribuídas por modelo no espaço de trabalho.", "Advanced": "Avançado", "Advanced Parameters": "Parâmetros Avançados", @@ -126,16 +146,21 @@ "All": "Todos", "All chats have been unarchived.": "Todos as conversas foram desarquivadas.", "All day": "", + "All events": "", "All models are now hidden": "Todos os modelos estão agora ocultos", "All models are now visible": "Todos os modelos estão agora visíveis", "All models deleted successfully": "Todos os modelos foram eliminados com sucesso", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Todo o tempo", "All Users": "Todos os Utilizadores", + "All users and system events": "", "Allow Call": "Permitir Chamada", "Allow Chat Controls": "Permitir Controlos de Conversa", "Allow Chat Delete": "Permitir Eliminação de Conversa", "Allow Chat Edit": "Permitir Edição de Conversa", "Allow Chat Export": "Permitir Exportação de Conversa", + "Allow Chat Import": "", "Allow Chat Params": "Permitir Parâmetros de Conversa", "Allow Chat Share": "Permitir Partilha de Conversa", "Allow Chat System Prompt": "Permitir Prompt do Sistema de Conversa", @@ -155,9 +180,11 @@ "Allow User Location": "Permitir Localização do Utilizador", "Allow Voice Interruption in Call": "Permitir Interrupção de Voz na Chamada", "Allow Web Upload": "Permitir Upload Web", + "Allowed Domains": "", "Allowed Endpoints": "Endpoints Permitidos", "Allowed File Extensions": "Extensões de Ficheiro Permitidas", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Extensões de ficheiro permitidas para upload. Separe múltiplas extensões com vírgulas. Deixe vazio para todos os tipos de ficheiro.", + "Allowed Roles": "", "Already have an account?": "Já tem uma conta?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativa ao top_p, e visa garantir um equilíbrio entre qualidade e variedade. O parâmetro p representa a probabilidade mínima para um token ser considerado, em relação à probabilidade do token mais provável. Por exemplo, com p=0,05 e o token mais provável tendo uma probabilidade de 0,9, os logits com um valor inferior a 0,045 são filtrados.", "Always": "Sempre", @@ -176,6 +203,7 @@ "API Base URL": "URL Base da API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL Base da API para o serviço Datalab Marker. Padrão: https://www.datalab.to/api/v1/marker", "API Key": "Chave da API", + "API Key / Token": "", "API Key created.": "Chave da API criada.", "API Key Endpoint Restrictions": "Restrições de Endpoint da Chave da API", "API keys": "Chaves da API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Tem a certeza de que deseja eliminar esta mensagem?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Tem a certeza de que deseja eliminar esta versão? As versões filhas serão relinkadas ao pai desta versão.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Tem a certeza de que deseja eliminar isto?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Tem a certeza de que deseja desarquivar todas as conversas arquivadas?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Modelos Arena", "Artifacts": "Artefatos", "Asc": "Asc", "Ask": "Perguntar", "Ask a question": "Fazer uma pergunta", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistente", "Async Embedding Processing": "Incorporação de Processamento Assíncrono", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Áudio", "August": "Agosto", "Auth": "Autenticação", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autenticar", "Authentication": "Autenticação", "Auto": "Automático", "Auto (Random)": "Automático (Aleatório)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Cópia Automática da Resposta para a Área de Transferência", - "Auto-playback response": "Reprodução automática da resposta", + "Auto-Create Groups": "", + "Auto-Playback Response": "Reprodução automática da resposta", "Autocomplete Generation": "Geração de Preenchimento Automático", "Autocomplete Generation Input Max Length": "Comprimento Máximo de Entrada para Geração de Preenchimento Automático", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "String de Autenticação da API do AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL Base do AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Ferramentas disponíveis", "available users": "utilizadores disponíveis", + "Available variables": "", "available!": "disponível!", "Away": "Ausente", "Awful": "Péssimo", @@ -261,16 +301,17 @@ "Bad Response": "Resposta má", "Banners": "Estandartes", "Base Model (From)": "Modelo Base (De)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "O cache da lista de modelos base acelera o acesso ao buscar apenas os modelos base na inicialização ou ao salvar as configurações—mais rápido, mas pode não mostrar alterações recentes nos modelos base.", "Bearer": "Bearer", "before": "antes", "Being lazy": "Ser preguiçoso", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Endpoint de Pesquisa V7 do Bing", "Bing Search V7 Subscription Key": "Chave de Subscrição do Bing Search V7", "Bio": "Biografia", "Birth Date": "Data de Nascimento", + "Blocked Groups": "", "BM25 Weight": "Peso BM25", "Bocha Search API Key": "Chave da API de Pesquisa Bocha", "Bold": "Negrito", @@ -327,7 +368,7 @@ "Chat Completions": "Conclusões da Conversa", "Chat Conversation": "Conversa", "Chat deleted.": "", - "Chat direction": "Direção da Conversa", + "Chat Direction": "Direção da Conversa", "Chat exported successfully": "Exportação da conversa realizada com sucesso", "Chat History": "Histórico da Conversa", "Chat ID": "ID da Conversa", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "Canal de colaboração onde as pessoas entram como membros", "Collapse": "Colapsar", "Collection": "Coleção", + "Collection Field": "", "Collections": "Coleções", "Color": "Cor", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "Fluxo de Trabalho do ComfyUI", "ComfyUI Workflow Nodes": "Nodos do Fluxo de Trabalho do ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "IDs de Nodos separados por vírgula (ex. 1 ou 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "comando", "Command": "Comando", "Comment": "Comentário", "Commit Message": "Mensagem de Commit", "Community Reviews": "Avaliações da Comunidade", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Conclusões", "Compress Images in Channels": "Comprimir Imagens nos Canais", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Ligar às instançias do Open Terminal. Todos os utilizadores terão acesso à pesquisa de ficheiros e ferramentas de terminais pelos servidores.", "Connect to your own OpenAI compatible API endpoints.": "Ligar ao seu próprio endpoint compatível com a OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Ligar ao seu próprio servidor de ferramentas externo compatível com a OpenAI.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Ligação falhou", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contactar o Admin para acesso ao WebUI", "Content": "Conteúdo", "Content Extraction Engine": "Motor de Extração de Conteúdo", + "Content Field": "", "Content lengths (character counts only)": "Tamanhos do Conteúdo (conta apenas os caracteres)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Continuar resposta", "Continue with {{provider}}": "Continuar com {{provider}}", "Continue with Email": "Continuar com Email", @@ -497,6 +550,7 @@ "Create new secret key": "Criar nova chave secreta", "Create note": "Criar nota", "Create Note": "Criar Nota", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Cria a tua primeira nota ao clicar no botão + abaixo.", "Created at": "Criado em", @@ -514,6 +568,7 @@ "Custom Gender": "Género Personalizado", "Custom Parameter Name": "Nome do Parâmetro Personalizado", "Custom Parameter Value": "Valor do Parâmetro Personalizado", + "Custom range": "", "Daily": "", "Daily Messages": "Mensagens Diárias", "Danger Zone": "Zona de Perigo", @@ -536,7 +591,6 @@ "Default Features": "Funcionalidades Predefinidas", "Default Filters": "Filtros Predefinidos", "Default Group": "Grupo Predefinido", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "O modo predefinido funciona com uma ampla gama de modelos, chamando ferramentas uma vez antes da execução. O modo nativo aproveita as capacidades integradas de chamada de ferramentas do modelo, mas requer que o modelo suporte essa funcionalidade de forma inerente.", "Default Model": "Modelo padrão", "Default model updated": "Modelo padrão atualizado", "Default permissions": "Permissões predefinidas", @@ -546,6 +600,7 @@ "Default to ALL": "Predefinir para TODOS", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Predefinir para recuperação segmentada para extração de conteúdo focada e relevante, isso é recomendado para a maioria dos casos.", "Default User Role": "Função de Utilizador Padrão", + "Default webhook": "", "Defaults": "Predefinições", "Delete": "Apagar", "Delete {{name}}": "Apagar {{name}}", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "Desativar Interpretador de Código", "Disable Image Extraction": "Desativar Extração de Imagens", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Desabilitar a extração de imgem do PDF. Se a utilização de LLM estiver ativa, as imagens irão ser automaticamente legendadas. Predefenido para Falso.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Desativado", "Disconnect OAuth": "", "Discover a function": "Descobrir uma função", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Descubra, descarregue e explore predefinições de modelo", "Discussion channel where access is based on groups and permissions": "Canais de discussão onde o acesso é baseado em grupos e permissões", "Display": "Mostrar", - "Display chat title in tab": "Mostrar título da conversa no separador", + "Display Chat Title in Tab": "Mostrar título da conversa no separador", "Display Emoji in Call": "Mostar Emoji em Chamada", "Display Multi-model Responses in Tabs": "Mostrar Respostas Multi-modelo nos Separadores", - "Display the username instead of You in the Chat": "Exibir o nome de utilizador em vez de Você na Conversa", + "Display the Username Instead of You in the Chat": "Exibir o nome de utilizador em vez de Você na Conversa", "Displays citations in the response": "Mostrar citações na resposta", "Displays status updates (e.g., web search progress) in the response": "Mostrar atualizações de estado (por exemplo, progresso de procura na web) na resposta", "Dive into knowledge": "Aprofunde os seus conhecimentos", @@ -634,6 +691,7 @@ "Docling Parameters": "Pârametros Docling", "Docling Server URL required.": "URL do Servidor Docling necessário.", "Document": "Documento", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Editar Permissões Predefinidas", "Edit Folder": "Editar Pasta", "Edit Image": "Editar Imagem", + "Edit Knowledge Connection": "", "Edit Last Message": "Edita Última Mensagem", "Edit Memory": "Editar Memória", "Edit Prompt": "Editar Prompt", "Edit Terminal Connection": "Editar Ligação ao Terminal", "Edit User": "Editar Utilizador", "Edit User Group": "Editar Grupo de Utilizadores", + "Edit webhook": "", "Edit workflow.json content": "Editar o conteúdo workflow.json", "edited": "editado", "Edited": "Editado", @@ -703,6 +763,7 @@ "Eject model": "Ejetar modelo", "ElevenLabs": "", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "Embarcar em aventuras", "Embedding": "Incorporação", "Embedding Batch Size": "Tamanho do Lote da Incorporação", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Motor de Modelo de Incorporação", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "Mensagem vazia", "Enable All": "Ativar Todos", "Enable API Keys": "Ativar Chaves API", @@ -718,22 +780,27 @@ "Enable Code Execution": "Ativar Execução de Código", "Enable Code Interpreter": "Ativar Interpretador de Código", "Enable Community Sharing": "Ative a Partilha da Comunidade", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "Ativar Mensagens em Fila", "Enable Message Rating": "Ativar a Classificação de Mensagens", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Ativar Novas Inscrições", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Ativar, desativar, ou customizar as etiquetas de raciocínio utilizadas pelo modelo. \"Ativado\" utiliza as etiquetas predefinidas, \"Desativado\" desliga as etiquetas de raciocínio, e \"Personalizado\" permite a espeficicação das etiquetas de começo e fim. ", "Enabled": "Ativado", "End Tag": "Etiqueta de Fim", + "Endpoint": "", "Endpoint URL": "URL do Endpoint", "Enforce Temporary Chat": "Forçar o Chat Temporário", "Enhance": "Melhorar", "Enrich Hybrid Search Text": "Enriquecer o Texto de Pesquisa Híbrida", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Confirme que o seu ficheiro CSV inclui 4 colunas nesta ordem: Nome, E-mail, Palavra-passe, Função.", "Enter {{role}} message here": "Escreva a mensagem de {{role}} aqui", - "Enter a detail about yourself for your LLMs to recall": "Escreva um detalhe sobre você para que os seus LLMs possam lembrar-se", "Enter a title for the pending user info overlay. Leave empty for default.": "Introduza um título para o overlay do utilizador pendente. Deixe em branco para o predefinido.", "Enter a watermark for the response. Leave empty for none.": "Introduza uma marca de água para a resposta. Deixe em branco para nenhuma.", "Enter additional headers in JSON format": "Introduzir cabeçalhos adicionais em formato JSON", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "Introduzir Tamanho Mínimo do Fragmento", "Enter Chunk Overlap": "Introduzir a Sobreposição de Fragmento", "Enter Chunk Size": "Introduzir o Tamanho do Fragmento", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Introduzir pares separados por vírgula \"token:valor_de_viés\" (exemplo: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Introduzir o conteúdo para o overlay do utilizador pendente. Deixe em branco para o predefinido.", "Enter coordinates (e.g. 51.505, -0.09)": "Introduzir coordenadas (por exempolo, 51.505, -0.09)", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "Introduzir URL do Jupyter", "Enter Kagi Search API Key": "Introduzir a Chave da API do Kagi Search", "Enter Key Behavior": "Introduzir Comportamento da Chave", + "Enter language": "", "Enter language codes": "Introduzir os códigos de idioma", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Introduzir a Chave de API do MinerU", "Enter Mistral API Base URL": "Introduzir o URL Base da API do Mistral", "Enter Mistral API Key": "Introduzir a Chave API do Mistral", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Introduzir URL da proxy (por exemplo, https://user:password@host.port)", "Enter reasoning effort": "Introduzir esforço do raciocínio", + "Enter Redirect URI": "", "Enter Score": "Introduzir a Pontuação", "Enter SearchApi API Key": "Introduzir Chave API do SearchApi", "Enter SearchApi Engine": "Introduzir Motor do SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "Introduzir Chave API do SerpApi", "Enter SerpApi Engine": "Introduzir Motor do SerpApi", "Enter Serper API Key": "Introduzir a chave da API do Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Introduzir a chave da API do Serply", "Enter Serpstack API Key": "Introduzir a chave da API do Serpstack", "Enter server host": "Introduzir anfitrião do servidor", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Introduzir URL do Tika Server", "Enter timeout in seconds": "Introduzir tempo limite em segundos", "Enter to Send": "Enter para enviar", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Introduzir o Top K", "Enter Top K Reranker": "Introduzir o Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Introduzir o URL (por exemplo, http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Erro: Um modelo com o ID '{{modelId}}' já existe. Por favor, selecione um ID diferente para continuar.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Erro: O ID do modelo não pode estar vazio. Por favor insira o ID válido para continuar.", "Evaluations": "Avaliações", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Chave da API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemplo: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "Exportar Configuração", "Export Models": "Exportar Modelos", "Export Prompts": "Exportar Prompts", + "Export Skills": "", "Export to CSV": "Exportar para CSV", "Export Tools": "Exportar Ferramentas", "Export Users": "Exportar Utililizadores", "External": "Externo", + "External connection not found.": "", "External Document Loader URL required.": "URL do Carregador de Documentos Externo é necessário.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Modelo de Tarefa Externo", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Chave de API do Carregador Web Externo", "External Web Loader URL": "URL do Carregador Web Externo", "External Web Search API Key": "Chave API do Carregador de Pesquisa Web Externo", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Falha ao criar a Chave da API.", "Failed to delete calendar": "", "Failed to delete note": "Falha ao apagar a nota", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "Falha ao transferir a imagem", "Failed to extract content from the file: {{error}}": "Falha ao extrair conteúdo do ficheiro: {{error}}", @@ -939,6 +1026,7 @@ "Failed to fetch models": "Falha ao obter modelos", "Failed to generate title": "Falha ao gerar título", "Failed to import models": "Falha ao importar modelos", + "Failed to load chat": "", "Failed to load chat preview": "Falha ao carregar a pré-visualização da conversa", "Failed to load DOCX file. Please try downloading it instead.": "Falha ao carregar ficheiro DOCX. Por favor, tente transferir em vez disso.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Falha ao carregar ficheiro Excel/CSV. Por favor, tente transferir em vez disso.", @@ -948,6 +1036,7 @@ "Failed to move chat": "Falha ao mover conversa", "Failed to process URL: {{url}}": "Falha ao processar URL: {{url}}", "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Falha ao remover membro", "Failed to render diagram": "Falha ao renderizar diagrama", "Failed to render visualization": "Falha ao renderizar visualização", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "Falha ao guardar configuração de modelos", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "Falha ao guardar servidores de terminais", + "Failed to save webhook": "", "Failed to unshare chat.": "Falha ao parar partilha de conversa.", "Failed to update settings": "Falha ao atualizar as definições", "Failed to update status": "Falha ao atualizar estado", + "Failed to update webhook": "", "Failed to upload file.": "Falha ao enviar ficheiro.", "Features": "Funcionalidades", "Features Permissions": "Permissões de Funcionalidades", @@ -991,6 +1082,8 @@ "File uploaded successfully": "Ficheiro enviado com sucesso", "Filename": "Nome do Ficheiro", "Files": "Ficheiros", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtro", "Filter is now globally disabled": "Filtro está agora globalmente desativado", "Filter is now globally enabled": "Filtro está agora globalmente ativado", @@ -1013,6 +1106,7 @@ "Folder options": "Opções da Pasta", "Folder updated successfully": "Pasta atualizada com sucesso", "Folders": "Pastas", + "Folders Sharing": "", "Follow up": "Acompanhamento", "Follow Up Generation": "Geração de Acompanhamento", "Follow Up Generation Prompt": "Prompt de Geração de Acompanhamento", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "Função agora está globalmente ativada", "Function Name": "Nome da Função", "Function Name Filter List": "Lista de Filtros de Nome da Função", + "Function starter": "", "Function updated successfully": "Função atualizada com sucesso", "Functions": "Funções", "Functions allow arbitrary code execution.": "Funções permitem a execução de código arbitrário.", @@ -1075,7 +1170,10 @@ "Gravatar": "Gravatar", "Grid": "Grelha", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Canal de Grupo", + "Group Claim": "", "Group created successfully": "Grupo criado com sucesso", "Group deleted successfully": "Grupo apagado com sucesso", "Group Description": "Descrição do Grupo", @@ -1087,6 +1185,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Feedback Háptico", + "Header variables": "", "Headers": "Cabeçalhos", "Headers must be a valid JSON object": "Os cabeçalhos devem ser um objeto JSON válido", "Height": "Altura", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID não pode conter os caracteres \":\" ou \"|\"", "ID copied to clipboard": "ID copiado para a área de transferência", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox Permitir Formulários", "iframe Sandbox Allow Same Origin": "iframe Sandbox Permitir Mesma Origem", @@ -1142,6 +1243,7 @@ "Import From Link": "Importar de Link", "Import Models": "Importar Modelos", "Import Prompts": "Importar Prompts", + "Import Skills": "", "Import successful": "Importação bem-sucedida", "Import Tools": "Importar Ferramentas", "Important Update": "Atualização importante", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "Manter na Barra Lateral", "Key": "Chave", "Key is required": "Chave é obrigatória", - "Keyboard shortcuts": "Atalhos de teclado", "Keyboard Shortcuts": "Atalhos de Teclado", "Knowledge": "Conhecimento", "Knowledge Access": "Acesso ao Conhecimento", @@ -1212,6 +1313,8 @@ "Knowledge Name": "Nome do Conhecimento", "Knowledge Public Sharing": "Partilha Pública do Conhecimento", "Knowledge Sharing": "Partilha do Conhecimento", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Conhecimento atualizado com sucesso.", "Kokoro.js (Browser)": "Kokoro.js (Navegador)", "Kokoro.js Dtype": "Tipo de Dados do Kokoro.js", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Última resposta", "LDAP": "LDAP", - "LDAP server updated": "Servidor LDAP atualizado", "Leaderboard": "Quadro de Líderes", "Learn more": "Saiba mais", "Learn More": "Saiba Mais", @@ -1250,6 +1352,7 @@ "Legacy": "Legado", "lexical": "Lexical", "License": "Licença", + "Lifecycle JSON": "", "Lift List": "", "Light": "Claro", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Limitar consultas de pesquisa simultâneas. 0 = ilimitado (padrão). Defina como 1 para execução sequencial (recomendado para APIs com limites de taxa rigorosos, como o nível gratuito do Brave).", @@ -1273,6 +1376,7 @@ "Location access not allowed": "Acesso à localização não permitido", "Lost": "Perdido", "Low": "Baixo", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Feito pela Comunidade OpenWebUI", "Make password visible in the user interface": "Tornar a palavra-passe visível na interface do utilizador", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gerir pipelines", "Manage Tool Servers": "Gerir Servidores de Ferramentas", "Manage your account information.": "Gerir as informações da sua conta.", + "Mapped Source": "", "March": "Março", "Markdown": "Markdown", "Markdown Header Text Splitter": "Divisor de Texto de Cabeçalho Markdown", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memória limpa com sucesso", "Memory deleted successfully": "Memória eliminada com sucesso", "Memory updated successfully": "Memória atualizada com sucesso", + "Merge Accounts by Email": "", "Merge Responses": "Fundir Respostas", "Merged Response": "Resposta Fundida", "Message": "Mensagem", @@ -1326,9 +1432,12 @@ "messages": "mensagens", "Messages": "Mensagens", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mensagens que você enviar após criar o seu link não serão partilhadas. Os utilizadores com o URL poderão visualizar a conversa partilhada.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (pessoal)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (trabalho/escola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Chave API do MinerU necessária para o modo Cloud API.", @@ -1381,6 +1490,7 @@ "Models Sharing": "Partilha de Modelos", "Mojeek": "Mojeek", "Mojeek Search API Key": "Chave API de Pesquisa Mojeek", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Mais", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "Nomeie sua base de conhecimento", "Name, prompt, and model are required": "", "Native": "Nativo", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "Novo", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "Sem concessões de acesso. Privado para você.", "No activity data": "Sem dados de atividade", + "No additional headers are sent unless configured.": "", "No authentication": "Sem autenticação", "No automations found": "", "No chats found": "Nenhuma conversa encontrada", @@ -1439,8 +1551,10 @@ "No data": "Sem dados", "No data found": "Nenhum dado encontrado", "No distance available": "Nenhuma distância disponível", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "A ausência de expiração pode representar riscos de segurança.", + "No external knowledge sources configured.": "", "No feedback found": "Nenhum feedback encontrado", "No file selected": "Nenhum ficheiro selecionado", "No files found": "Nenhum ficheiro encontrado", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "Nenhuma mensagem fixada", "No prompts found": "Nenhum prompt encontrado", + "No Repeat": "", "No results": "Não foram encontrados resultados", "No results found": "Não foram encontrados resultados", "No search query generated": "Não foi gerada nenhuma consulta de pesquisa", @@ -1487,6 +1602,7 @@ "No webhooks yet": "Nenhum webhook ainda", "Node Ids": "Ids do Node", "None": "Nenhum", + "Not configured": "", "Not factually correct": "Não é correto em termos factuais", "Not helpful": "Não é útil", "Not Registered": "Não registrado", @@ -1502,20 +1618,25 @@ "Notifications": "Notificações da Área de Trabalho", "November": "Novembro", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "ID do OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Outubro", "Off": "Desligado", "Okay, Let's Go!": "Ok, Vamos Lá!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Escuro", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Configurações da API Ollama atualizadas", "Ollama Cloud API Key": "Chave da API Ollama Cloud", "Ollama Version": "Versão do Ollama", + "Omit": "", "On": "Ligado", "Once": "", "OneDrive": "OneDrive", @@ -1586,6 +1707,7 @@ "Password": "Senha", "Passwords do not match.": "As palavras-passe não coincidem.", "Paste Large Text as File": "Colar Texto Grande como Arquivo", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Documento PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "pendente", "Pending": "Pendente", + "Pending Accounts": "", "Pending User Overlay Content": "Conteúdo de Sobreposição de Usuário Pendente", "Pending User Overlay Title": "Título de Sobreposição de Usuário Pendente", "Permission denied when accessing media devices": "A permissão foi negada ao aceder aos dispositivos de media", "Permission denied when accessing microphone": "A permissão foi negada ao aceder ao microfone", "Permission denied when accessing microphone: {{error}}": "A permissão foi negada ao aceder o microfone: {{error}}", "Permissions": "Permissões", + "Permissions reset to defaults": "", "Perplexity API Key": "Chave API do Perplexity", "Perplexity Model": "Modelo Perplexity", "Perplexity Search API URL": "URL da API de Pesquisa Perplexity", "Perplexity Search Context Usage": "Uso do Contexto de Pesquisa Perplexity", "Persistent": "", "Personalization": "Personalização", + "Picture Claim": "", "Pin": "Fixar", "Pin to Sidebar": "", "Pinned": "Fixado", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Por favor, preencha todos os campos.", "Please register the OAuth client": "Por favor, registe o cliente OAuth", "Please save the connection to persist the OAuth client information and do not change the ID": "Por favor, guarde a ligação para persistir as informações do cliente OAuth e não altere o ID", - "Please select a model first.": "Por favor, selecione um modelo primeiro.", "Please select a model.": "Por favor, selecione um modelo.", "Please select a reason": "Por favor, selecione uma razão", "Please select a valid JSON file": "Por favor, selecione um ficheiro JSON válido", "Please select at least one user for Direct Message channel.": "Por favor, selecione pelo menos um utilizador para o canal de Mensagem Direta.", "Please wait until all files are uploaded.": "Por favor, aguarde até que todos os ficheiros sejam carregados.", "Policy ID": "", + "Policy ID is required": "", "Port": "Porta", "Ports": "Portas", "Positive attitude": "Atitude Positiva", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "Partilha Pública de Prompts", "Prompts Sharing": "Partilha de Prompts", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Público", "Pull \"{{searchValue}}\" from Ollama.com": "Puxar \"{{searchValue}}\" do Ollama.com", "Pull a model from Ollama.com": "Puxar um modelo do Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Ler", "Read Aloud": "Ler em Voz Alta", "Read more →": "Ler mais →", + "Read only": "", "Read Only": "Somente Leitura", "Read-Only Access": "Acesso Somente Leitura", "Reason": "Razão", "Reasoning Effort": "Esforço de Raciocínio", "Reasoning Tags": "Etiquetas de Raciocínio", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Gravar", "Record voice": "Gravar voz", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Redirecionando-o para a Comunidade OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Reduz a probabilidade de gerar o absurdo. Um valor mais alto (por exemplo, 100) dará respostas mais diversificadas, enquanto um valor mais baixo (por exemplo, 10) será mais conservador.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Refera-se a si próprio como \"User\" (por exemplo, \"User está a aprender Espanhol\")", "Reference Chats": "Chats de Referência", "Refresh": "Atualizar", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Recusado quando não deveria", "Regenerate": "Regenerar", "Regenerate Menu": "Regenerar Menu", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "Renderizar Markdown em Pré-visualizações", "Render Markdown in User Messages": "", "Reorder Models": "Reordenar Modelos", + "Repeat": "", "Repeats": "", "Reply": "Responder", "Reply in Thread": "Responder no Tópico", "Reply to thread...": "Responder ao tópico...", "Replying to {{NAME}}": "A responder a {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "obrigatório", "Reranking Batch Size": "", "Reranking Engine": "Motor de Reclassificação", "Reranking Model": "Modelo de Reclassificação", + "Research Knowledge": "", "Reset": "Repor", "Reset All Models": "Repor Todos os Modelos", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Repor imagem", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Limpar Pasta de Carregamento", "Reset Vector Storage/Knowledge": "Repor Armazenamento de Vetores/Conhecimento", "Reset view": "Repor vista", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "Recuperada 1 fonte", "Rich Text Input for Chat": "Entrada de Texto Rico para Chat", "Role": "Função", + "Roles Claim": "", "RTL": "RTL", "Run": "Executar", "Run All": "Executar Tudo", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Guardar o registo das conversas diretamente no armazenamento do seu navegador já não é suportado. Reserve um momento para descarregar e eliminar os seus registos de conversas clicando no botão abaixo. Não se preocupe, você pode facilmente reimportar os seus registos de conversas para o backend através de", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Scroll na Mudança de Ramo", "Scroll to Top": "", "Search": "Pesquisar", "Search a model": "Pesquisar um modelo", + "Search actions": "", "Search all emojis": "Pesquisar todos os emojis", "Search and manage user memories": "Pesquisar e gerir memórias do utilizador", "Search and view user chat history": "Pesquisar e visualizar o histórico de conversas do utilizador", @@ -1804,6 +1950,7 @@ "Search Chats": "Pesquisar Conversas", "Search Collection": "Pesquisar Coleção", "Search Files": "Pesquisar Ficheiros", + "Search filters": "", "Search Filters": "Pesquisar Filtros", "search for archived chats": "pesquisar conversas arquivadas", "search for folders": "pesquisar pastas", @@ -1818,13 +1965,16 @@ "Search Models": "Modelos de pesquisa", "Search Notes": "Pesquisar Notas", "Search options": "Opções de Pesquisa", + "Search or add pattern": "", "Search Prompts": "Pesquisar Prompts", "Search Result Count": "Contagem de resultados da pesquisa", + "Search skills": "", "Search Skills": "Pesquisar Habilidades", - "Search skills...": "", "Search the internet": "Pesquisar na internet", "Search the web and fetch URLs": "Pesquisar na web e obter URLs", + "Search tools": "", "Search Tools": "Pesquisar Ferramentas", + "Search users or groups": "", "Search, view, and manage user notes": "Pesquisar, visualizar e gerir notas do utilizador", "SearchApi API Key": "Chave API do SearchApi", "SearchApi Engine": "Motor do SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "Semente", "Select": "Selecionar", "Select {{modelName}} model": "Selecionar modelo {{modelName}}", - "Select a base model": "Selecione um modelo base", "Select a base model (e.g. llama3, gpt-4o)": "Selecione um modelo base (ex.: llama3, gpt-4o)", "Select a conversation to preview": "Selecione uma conversa para pré-visualizar", "Select a engine": "Selecione um motor", @@ -1878,18 +2027,25 @@ "semantic": "semântico", "Send": "Enviar", "Send a Message": "Enviar uma Mensagem", + "Send events for": "", "Send message": "Enviar mensagem", "Send now": "Enviar agora", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envia `stream_options: { include_usage: true }` na solicitação.\nOs provedores suportados retornarão informações de uso de tokens na resposta quando definido.", "September": "Setembro", "SerpApi API Key": "Chave API do SerpApi", "SerpApi Engine": "Motor do SerpApi", "Serper API Key": "Chave API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Chave API Serply", "Serpstack API Key": "Chave da API Serpstack", "Server connection failed": "", "Server connection verified": "Ligação com o servidor verificada", + "Service Account": "", "Session": "Sessão", + "Session expired. Please sign in again.": "", "Set as default": "Definir como padrão", "Set as Production": "Definir como Produção", "Set embedding model": "Definir modelo de incorporação", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "Partilhar link copiado para a área de transferência.", "Share to Open WebUI Community": "Partilhar com a Comunidade OpenWebUI", "Share your background and interests": "Partilhar seu histórico e interesses", + "Shared": "", "Shared Chats": "Conversas Partilhadas", "Shared with you": "Partilhado consigo", "Sharing Permissions": "Permissões de Partilha", "Show": "Mostrar", - "Show \"What's New\" modal on login": "Mostrar janela \"O que há de novo\" no login", + "Show \"What's New\" Modal on Login": "Mostrar janela \"O que há de novo\" no login", "Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na sobreposição de Conta Pendente", "Show All": "Mostrar Tudo", "Show all ({{COUNT}} characters)": "Mostrar tudo ({{COUNT}} caracteres)", "Show Files": "Mostrar Ficheiros", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Mostrar Barra de Formatação", "Show image preview": "Mostrar pré-visualização de imagem", "Show Model": "Mostrar Modelo", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "ID da API de Pesquisa Sougou", "Sougou Search API SK": "Chave da API de Pesquisa Sougou", "Source": "Fonte", + "Specific users or groups": "", "Speech Playback Speed": "Velocidade de Reprodução de Fala", "Speech recognition error: {{error}}": "Erro de reconhecimento de fala: {{error}}", "Speech-to-Text": "Fala para Texto", @@ -2006,6 +2165,7 @@ "STT Settings": "Configurações STT", "Stylized PDF Export": "Exportação de PDF Estilizado", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "Enviar pergunta", "Submit suggestion": "Enviar sugestão", "Subtitle": "Legenda", @@ -2030,8 +2190,10 @@ "Syncing...": "A sincronizar...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sincroniza apenas chats com atualizações após o seu último carimbo de data/hora de sincronização. Desative para re-sincronizar todos os chats.", "System": "Sistema", + "System events only": "", "System Instructions": "Instruções do Sistema", "System Prompt": "Prompt do Sistema", + "Table": "", "Tag": "Etiqueta", "Tags": "Etiquetas", "Tags Generation": "Geração de Etiquetas", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "Conversa Temporária por Defeito", "Terminal": "Terminal", "Terminal servers saved": "Servidores de Terminal Guardados", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divisor de Texto", "Text-to-Speech": "Texto para Fala", "Text-to-Speech Engine": "Motor de Texto para Fala", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "O idioma do áudio de entrada. Fornecer o idioma de entrada no formato ISO-639-1 (por exemplo, en) melhorará a precisão e a latência. Deixe em branco para detectar automaticamente o idioma.", "The LDAP attribute that maps to the mail that users use to sign in.": "O atributo LDAP que mapeia para o e-mail que os utilizadores usam para iniciar sessão.", "The LDAP attribute that maps to the username that users use to sign in.": "O atributo LDAP que mapeia para o nome de utilizador que os utilizadores usam para iniciar sessão.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "O quadro de líderes está atualmente em beta, e podemos ajustar os cálculos de classificação à medida que refinamos o algoritmo.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "O tamanho máximo do ficheiro em MB. Se o tamanho do ficheiro exceder este limite, o ficheiro não será carregado.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "O número máximo de ficheiros que podem ser usados de uma vez na conversa. Se o número de ficheiros exceder este limite, os ficheiros não serão carregados.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "O formato de saída para o texto. Pode ser 'json', 'markdown' ou 'html'. O padrão é 'markdown'.", @@ -2089,6 +2256,7 @@ "This folder is empty": "Esta pasta está vazia", "This is a default user permission and will remain enabled.": "Esta é uma permissão de utilizador padrão e permanecerá ativada.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Isto é um recurso experimental, pode não funcionar conforme o esperado e está sujeito a alterações a qualquer momento.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Este modelo não está disponível publicamente. Por favor, selecione outro modelo.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Esta opção controla quanto tempo o modelo permanecerá carregado na memória após a solicitação (padrão: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Esta opção controla quantos tokens são preservados ao atualizar o contexto. Por exemplo, se definido para 2, os últimos 2 tokens do contexto da conversa serão retidos. Preservar o contexto pode ajudar a manter a continuidade de uma conversa, mas pode reduzir a capacidade de responder a novos tópicos.", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "Para saber mais sobre os endpoints disponíveis, visite a nossa documentação.", "To select skills here, add them to the \"Skills\" workspace first.": "Para selecionar habilidades aqui, adicione-as primeiro ao espaço de trabalho \"Habilidades\".", "To select toolkits here, add them to the \"Tools\" workspace first.": "Para selecionar conjuntos de ferramentas aqui, adicione-os primeiro ao espaço de trabalho \"Ferramentas\".", - "Toast notifications for new updates": "Notificações de toast para novas atualizações", + "Toast Notifications for New Updates": "Notificações de toast para novas atualizações", "Today": "Hoje", "Today at": "", "Today at {{LOCALIZED_TIME}}": "Hoje às {{LOCALIZED_TIME}}", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "Alternar se a conexão atual está ativa.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Contagem de tokens são estimativas e podem não refletir o uso real da API", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "Demasiado verboso", @@ -2191,14 +2361,19 @@ "Unpin": "Desafixar", "Unpin from Sidebar": "", "Unravel secrets": "Desvendar segredos", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Parar partilha de conversa", "Unsupported file type.": "Tipo de ficheiro não suportado", "Untagged": "Desafixado", "Untitled": "Sem título", "Update": "Atualizar", "Update and Copy Link": "Atualizar e Copiar Link", + "Update Email": "", "Update for the latest features and improvements.": "Atualize para os recursos e melhorias mais recentes.", + "Update Name": "", "Update password": "Atualizar senha", + "Update Picture": "", "Update your status": "Atualize seu status", "Updated": "Atualizado", "Updated at": "Atualizado em", @@ -2225,13 +2400,18 @@ "Use": "Usar", "Use '#' in the prompt input to load and include your knowledge.": "Use '#' na entrada do prompt para carregar e incluir seu conhecimento.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Use o endpoint /v1/chat/completions em vez de /v1/audio/transcriptions para uma precisão potencialmente melhor.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Usar API de Conclusões de Chat", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Use grupos para organizar seus utilizadores e atribuir permissões.", "Use LLM": "Usar LLM", "Use no proxy to fetch page contents.": "Não utilizar proxy para buscar conteúdos da página.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Usar proxy designado pelas variáveis de ambiente http_proxy e https_proxy para buscar conteúdos da página.", + "Use Web Search?": "", "user": "utilizador", "User": "Utilizador", + "User Access": "", "User Activity": "Atividade do Utilizador", "User Groups": "Grupos de Utilizadores", "User location successfully retrieved.": "Localização do utilizador recuperada com sucesso.", @@ -2241,6 +2421,7 @@ "User Status": "Estado do Utilizador", "User Webhooks": "Webhooks do Utilizador", "Username": "Nome de Utilizador", + "Username Claim": "", "users": "utilizadores", "Users": "Utilizadores", "Uses DefaultAzureCredential to authenticate": "Usa DefaultAzureCredential para autenticar", @@ -2254,6 +2435,7 @@ "Valves updated": "Válvulas atualizadas", "Valves updated successfully": "Válvulas atualizadas com sucesso", "variable": "variável", + "Vector Field": "", "Verify Connection": "Verificar Ligação", "Verify SSL Certificate": "Verificar Certificado SSL", "Version": "Versão", @@ -2283,11 +2465,14 @@ "Web API": "Web API", "Web Loader Engine": "Motor de Carregamento Web", "Web Search": "Pesquisa na Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motor de Pesquisa Web", "Web Search in Chat": "Pesquisa na Web no Chat", "Web Search Query Generation": "Geração de Consultas de Pesquisa na Web", + "Webhook deleted": "", "Webhook Name": "Nome do Webhook", - "Webhook URL": "URL do Webhook", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URLs de Páginas Web", "WebUI Settings": "Configurações WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "Chave API de Pesquisa Web Yandex", "Yandex Web Search config": "Configuração de Pesquisa Web Yandex", "Yandex Web Search URL": "URL de Pesquisa Web Yandex", + "Yearly": "", "Yesterday": "Ontem", "Yesterday at {{LOCALIZED_TIME}}": "Ontem às {{LOCALIZED_TIME}}", "You": "Você", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "O seu navegador não suporta a tag de vídeo.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "A sua contribuição irá diretamente para o desenvolvedor do plugin; o Open WebUI não recebe nenhuma percentagem. No entanto, a plataforma de financiamento escolhida pode ter as suas próprias taxas.", "Your message text or inputs": "O texto da sua mensagem ou entradas", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "As suas estatísticas de uso foram sincronizadas com sucesso.", "YouTube": "Youtube", "Youtube Language": "Idioma do Youtube", diff --git a/src/lib/i18n/locales/ro-RO/translation.json b/src/lib/i18n/locales/ro-RO/translation.json index 0e0f669fc8..43305713de 100644 --- a/src/lib/i18n/locales/ro-RO/translation.json +++ b/src/lib/i18n/locales/ro-RO/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_few": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Conversațiile lui {{user}}", "{{webUIName}} Backend Required": "Este necesar backend-ul {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*Sunt necesare ID-urile nodurilor de solicitare pentru generarea imaginii*", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "Controlul accesului", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Accesibil pentru toți utilizatorii", "Account": "Cont", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Adaugă", "Add a model ID": "Adaugă un ID de model", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Adaugă o scurtă descriere despre ce face acest model", "Add a tag": "Adaugă o etichetă", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Adaugă fișiere", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Adaugă utilizator", "Add User Group": "Adaugă grup de utilizatori", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Administrator", "Admin Contact Email": "", "Admin Panel": "Panoul de administrare", + "Admin Roles": "", "Admin Settings": "Setări pentru administrator", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorii au acces la toate instrumentele în orice moment; utilizatorii au nevoie de instrumente asignate pe model în spațiul de lucru.", "Advanced": "", "Advanced Parameters": "Parametri avansați", @@ -126,16 +146,21 @@ "All": "Toate", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Toate modelele au fost șterse cu succes", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Permite apelarea", "Allow Chat Controls": "Permite controalele chat-ului", "Allow Chat Delete": "Permite ștergerea chat-ului", "Allow Chat Edit": "Permite editarea chat-ului", "Allow Chat Export": "Permite exportul conversației", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -155,9 +180,11 @@ "Allow User Location": "Permite localizarea utilizatorului", "Allow Voice Interruption in Call": "Permite intreruperea vocii în apel", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Deja ai un cont?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Întotdeauna", @@ -176,6 +203,7 @@ "API Base URL": "URL Bază API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Cheie API", + "API Key / Token": "", "API Key created.": "Cheie API creată.", "API Key Endpoint Restrictions": "", "API keys": "Chei API", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Ești sigur că vrei să ștergi acest mesaj?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Ești sigur că vrei să dezarhivezi toate conversațiile arhivate?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena Models", "Artifacts": "Artefacte", "Asc": "", "Ask": "Întreabă", "Ask a question": "Pune o întrebare", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistent", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Audio", "August": "August", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentifică", "Authentication": "Autentificare", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Copiere Automată a Răspunsului în Clipboard", - "Auto-playback response": "Redare automată a răspunsului", + "Auto-Create Groups": "", + "Auto-Playback Response": "Redare automată a răspunsului", "Autocomplete Generation": "Generare automată a completării", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111 este un proiect popular pentru interfața grafică a utilizatorului a modelelor de difuzie stabilă. Aceasta oferă o interfață web pentru a genera imagini folosind AI și este utilizată pe scară largă pentru a experimenta cu generarea de artă AI.", "AUTOMATIC1111 Api Auth String": "Șir de Autentificare API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL Bază AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "Instrumente disponibile", "available users": "utilizatori disponibili", + "Available variables": "", "available!": "disponibil!", "Away": "Plecat", "Awful": "", @@ -261,16 +301,17 @@ "Bad Response": "Răspuns Greșit", "Banners": "Bannere", "Base Model (From)": "Model de Bază (De la)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "înainte", "Being lazy": "Fiind leneș", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Direcția conversației", + "Chat Direction": "Direcția conversației", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Colecție", + "Collection Field": "", "Collections": "", "Color": "Culoare", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "Flux de lucru ComfyUI", "ComfyUI Workflow Nodes": "Noduri de flux de lucru ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Comandă", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Completări", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Conexiune eșuată", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Contactează administratorul pentru acces WebUI", "Content": "Conținut", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Continuă Răspunsul", "Continue with {{provider}}": "Continuă cu {{provider}}", "Continue with Email": "Continuă cu email", @@ -497,6 +550,7 @@ "Create new secret key": "Creează cheie secretă nouă", "Create note": "", "Create Note": "Creează notiță", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Creat la", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Model Implicit", "Default model updated": "Modelul implicit a fost actualizat", "Default permissions": "Permisiuni implicite", @@ -546,6 +600,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Rolul Implicit al Utilizatorului", + "Default webhook": "", "Defaults": "", "Delete": "Șterge", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Dezactivat", "Disconnect OAuth": "", "Discover a function": "Descoperă o funcție", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Descoperă, descarcă și explorează presetări de model", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Afișează Emoji în Apel", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Afișează numele utilizatorului în loc de Tu în Conversație", + "Display the Username Instead of You in the Chat": "Afișează numele utilizatorului în loc de Tu în Conversație", "Displays citations in the response": "Afișează citațiile în răspuns", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Document", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Editează permisiunile implicite", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Editează Memorie", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Editează Utilizator", "Edit User Group": "Editează grupul de utilizatori", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "Dimensiune Lot de Încapsulare", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Motor de Model de Încapsulare", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "Activează interpretul de cod", "Enable Community Sharing": "Activează Partajarea Comunitară", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "Activează Evaluarea Mesajelor", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Activează Înscrierile Noi", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Activat", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Asigurați-vă că fișierul CSV include 4 coloane în această ordine: Nume, Email, Parolă, Rol.", "Enter {{role}} message here": "Introduceți mesajul pentru {{role}} aici", - "Enter a detail about yourself for your LLMs to recall": "Introduceți un detaliu despre dvs. pe care LLM-urile să-l rețină", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Introduceți Suprapunerea Blocului", "Enter Chunk Size": "Introduceți Dimensiunea Blocului", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Introduceți codurile limbilor", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Introduceți Scorul", "Enter SearchApi API Key": "Introduceți cheia API SearchApi", "Enter SearchApi Engine": "Introduceți motorul SearchApi", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Introduceți Cheia API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Introduceți Cheia API Serply", "Enter Serpstack API Key": "Introduceți Cheia API Serpstack", "Enter server host": "", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "Introduceți URL-ul Serverului Tika", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Introduceți Top K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Introduceți URL-ul (de ex. http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Evaluări", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Crearea cheii API a eșuat.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Citirea conținutului clipboard-ului a eșuat", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Actualizarea setărilor a eșuat", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Încărcarea fișierului a eșuat.", "Features": "", "Features Permissions": "", @@ -991,6 +1082,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Fișiere", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filtrul este acum dezactivat global", "Filter is now globally enabled": "Filtrul este acum activat global", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "Funcția este acum activată global", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funcția a fost actualizată cu succes", "Functions": "Funcții", "Functions allow arbitrary code execution.": "Funcțiile permit executarea arbitrară a codului.", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Feedback haptic", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1142,6 +1243,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Actualizare importantă", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Scurtături de la Tastatură", "Keyboard Shortcuts": "", "Knowledge": "Cunoștințe", "Knowledge Access": "", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Cunoașterea a fost actualizată cu succes", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "Tabel de clasament", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Luminos", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "", "Lost": "Pierdut", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Realizat de Comunitatea OpenWebUI", "Make password visible in the user interface": "", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Gestionează Conductele", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Martie", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Memoria a fost ștearsă cu succes", "Memory deleted successfully": "Memoria a fost ștearsă cu succes", "Memory updated successfully": "Memoria a fost actualizată cu succes", + "Merge Accounts by Email": "", "Merge Responses": "Combină răspunsurile", "Merged Response": "Răspuns Combinat", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Mesajele pe care le trimiteți după crearea link-ului dvs. nu vor fi partajate. Utilizatorii cu URL-ul vor putea vizualiza conversația partajată.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Mai multe", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "Nicio distanță disponibilă", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nu a fost selectat niciun fișier", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Nu au fost găsite rezultate", "No results found": "Nu au fost găsite rezultate", "No search query generated": "Nu a fost generată nicio interogare de căutare", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Niciunul", + "Not configured": "", "Not factually correct": "Nu este corect din punct de vedere factual", "Not helpful": "Nu este de ajutor", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Notificări", "November": "Noiembrie", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Octombrie", "Off": "Dezactivat", "Okay, Let's Go!": "Ok, Să Începem!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Întunecat OLED", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Versiune Ollama", + "Omit": "", "On": "Activat", "Once": "", "OneDrive": "", @@ -1586,6 +1707,7 @@ "Password": "Parolă", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Document PDF (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "în așteptare", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Permisiunea refuzată la accesarea dispozitivelor media", "Permission denied when accessing microphone": "Permisiunea refuzată la accesarea microfonului", "Permission denied when accessing microphone: {{error}}": "Permisiunea refuzată la accesarea microfonului: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalizare", + "Picture Claim": "", "Pin": "Fixează", "Pin to Sidebar": "", "Pinned": "Fixat", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "Vă rugăm să completați toate câmpurile.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "Vă rugăm să selectați un motiv", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Atitudine pozitivă", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Extrage \"{{searchValue}}\" de pe Ollama.com", "Pull a model from Ollama.com": "Extrage un model de pe Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Citește", "Read Aloud": "Citește cu Voce Tare", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Înregistrează vocea", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Vă redirecționăm către Comunitatea OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referiți-vă la dvs. ca \"Utilizator\" (de ex., \"Utilizatorul învață spaniolă\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Refuzat când nu ar fi trebuit", "Regenerate": "Regenerare", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Model de Rearanjare", + "Research Knowledge": "", "Reset": "Resetează", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetați imaginea", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Resetează Directorul de Încărcare", "Reset Vector Storage/Knowledge": "Resetarea Stocării/Vectoului de Cunoștințe", "Reset view": "", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Introducere text îmbogățit pentru chat", "Role": "Rol", + "Roles Claim": "", "RTL": "RTL", "Run": "Execută", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Salvarea jurnalelor de conversație direct în stocarea browserului dvs. nu mai este suportată. Vă rugăm să luați un moment pentru a descărca și a șterge jurnalele de conversație făcând clic pe butonul de mai jos. Nu vă faceți griji, puteți reimporta ușor jurnalele de conversație în backend prin", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Caută", "Search a model": "Caută un model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Caută în Conversații", "Search Collection": "Căutare Colecție", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Caută Modele", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Caută Prompturi", "Search Result Count": "Număr Rezultate Căutare", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Caută Instrumente", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Cheie API pentru SearchApi", "SearchApi Engine": "Motorul SearchApi", @@ -1840,7 +1990,6 @@ "Seed": "", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Selectează un model de bază", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Selectează un motor", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Trimite", "Send a Message": "Trimite un Mesaj", + "Send events for": "", "Send message": "Trimite mesajul", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Trimite `stream_options: { include_usage: true }` în cerere. Furnizorii care suportă această opțiune vor returna informații despre utilizarea token-urilor în răspuns când este setată.", "September": "Septembrie", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Cheie API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Cheie API Serply", "Serpstack API Key": "Cheie API Serpstack", "Server connection failed": "", "Server connection verified": "Conexiunea la server a fost verificată", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Setează ca implicit", "Set as Production": "", "Set embedding model": "", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Partajează cu Comunitatea OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Afișează", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "Afișează Detaliile Administratorului în Suprapunerea Contului În Așteptare", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Sursă", + "Specific users or groups": "", "Speech Playback Speed": "Viteza de redare a vorbirii", "Speech recognition error: {{error}}": "Eroare de recunoaștere vocală: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "Setări STT", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistem", + "System events only": "", "System Instructions": "Instrucțiuni pentru sistem", "System Prompt": "Prompt de Sistem", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Divizor de Text", "Text-to-Speech": "", "Text-to-Speech Engine": "Motor de Conversie a Textului în Vorbire", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Clasamentul este în prezent în versiune beta și este posibil să ajustăm calculul evaluărilor pe măsură ce rafinăm algoritmul.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Dimensiunea maximă a fișierului în MB. Dacă dimensiunea fișierului depășește această limită, fișierul nu va fi încărcat.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Numărul maxim de fișiere care pot fi utilizate simultan în chat. Dacă numărul de fișiere depășește această limită, fișierele nu vor fi încărcate.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Aceasta este o funcție experimentală, poate să nu funcționeze așa cum vă așteptați și este supusă schimbării în orice moment.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Pentru a selecta kiturile de instrumente aici, adăugați-le mai întâi în spațiul de lucru \"Instrumente\".", - "Toast notifications for new updates": "Notificări toast pentru actualizări noi", + "Toast Notifications for New Updates": "Notificări toast pentru actualizări noi", "Today": "Astăzi", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Prea detaliat", @@ -2191,14 +2361,19 @@ "Unpin": "Anulează Fixarea", "Unpin from Sidebar": "", "Unravel secrets": "Dezvăluie secretele", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Netichetat", "Untitled": "", "Update": "Actualizează", "Update and Copy Link": "Actualizează și Copiază Link-ul", + "Update Email": "", "Update for the latest features and improvements.": "Actualizare pentru cele mai recente caracteristici și îmbunătățiri.", + "Update Name": "", "Update password": "Actualizează parola", + "Update Picture": "", "Update your status": "", "Updated": "Actualizat", "Updated at": "Actualizat la", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Folosește '#' în prompt pentru a încărca și include cunoștințele tale.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "utilizator", "User": "Utilizator", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Localizarea utilizatorului a fost preluată cu succes.", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "Utilizatori", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "Valve actualizate", "Valves updated successfully": "Valve actualizate cu succes", "variable": "variabilă", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Versiune", @@ -2283,11 +2465,14 @@ "Web API": "API Web", "Web Loader Engine": "", "Web Search": "Căutare Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Motor de Căutare Web", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL Webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Setări WebUI", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Ieri", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Tu", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Întreaga dvs. contribuție va merge direct la dezvoltatorul plugin-ului; Open WebUI nu ia niciun procent. Cu toate acestea, platforma de finanțare aleasă ar putea avea propriile taxe.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/ru-RU/translation.json b/src/lib/i18n/locales/ru-RU/translation.json index bb87696d90..5b2c64928f 100644 --- a/src/lib/i18n/locales/ru-RU/translation.json +++ b/src/lib/i18n/locales/ru-RU/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} скрытых строк", "{{COUNT}} members": "{{COUNT}} участников", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "{{count}} выбрано", "{{count}} selected_other": "{{count}} выбрано", "{{COUNT}} Sources": "{{COUNT}} Источников", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} слов", "{{COUNT}}d_time_ago": "{{COUNT}} д назад", "{{COUNT}}h_time_ago": "{{COUNT}} ч назад", "{{COUNT}}m_time_ago": "{{COUNT}} мин назад", "{{COUNT}}w_time_ago": "{{COUNT}} нед назад", "{{COUNT}}y_time_ago": "{{COUNT}} г назад", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} в {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} загрузка была отменена", "{{modelName}} profile image": "Изображение профиля {{modelName}}", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "Чаты {{user}}'а", "{{webUIName}} Backend Required": "Необходимо подключение к серверу {{webUIName}}", "*Prompt node ID(s) are required for image generation": "ID узлов промптов обязательны для генерации изображения", + "1 group": "", "1 hour before": "За 1 час", "1 Source": "1 Источник", + "1 user": "", "10 minutes before": "За 10 минут", "15 minutes before": "За 15 минут", "1m_time_ago": "1 мин назад", @@ -63,6 +79,7 @@ "Access Control": "Контроль доступа", "Access Grants": "Права доступа", "Access List": "Список доступов", + "Access prohibited": "", "Access updated": "Доступ обновлен", "Accessible to all users": "Доступно всем пользователям", "Account": "Учетная запись", @@ -78,6 +95,7 @@ "Activity": "Активность", "Add": "Добавить", "Add a model ID": "Добавить ID модели", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Добавьте краткое описание того, что делает эта модель", "Add a tag": "Добавьте тег", "Add a tag...": "Добавить тег...", @@ -90,8 +108,10 @@ "Add Custom Prompt": "Добавить пользовательский запрос", "Add description": "Добавить описание", "Add Details": "Добавить детали", + "Add durable context for future chats": "", "Add Files": "Добавить файлы", "Add Image": "Добавить изображение", + "Add Knowledge Connection": "", "Add location": "Добавить место", "Add Member": "Добавить участника", "Add Members": "Добавить участников", @@ -106,6 +126,7 @@ "Add to favorites": "Добавить в избранное", "Add User": "Добавить пользователя", "Add User Group": "Добавить группу пользователей", + "Add webhook": "", "Add webpage": "Добавить веб-страницу", "Add your Open Terminal URL and API key in Settings → Integrations.": "Добавьте URL и API-ключ Open Terminal в Настройки → Интеграции.", "Additional Config": "Дополнительные настройки", @@ -118,7 +139,9 @@ "Admin": "Админ", "Admin Contact Email": "Адрес электронной почты администратора", "Admin Panel": "Панель администратора", + "Admin Roles": "", "Admin Settings": "Настройки администратора", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Администраторы всегда имеют доступ ко всем инструментам; пользователям нужны инструменты, назначенные для каждой модели в рабочем пространстве.", "Advanced": "Расширенные", "Advanced Parameters": "Расширенные параметры", @@ -129,16 +152,21 @@ "All": "Все", "All chats have been unarchived.": "Все чаты были разархивированы.", "All day": "Весь день", + "All events": "", "All models are now hidden": "Все модели скрыты", "All models are now visible": "Все модели видимы", "All models deleted successfully": "Все модели успешно удалены", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "За всё время", "All Users": "Все пользователи", + "All users and system events": "", "Allow Call": "Разрешить звонки", "Allow Chat Controls": "Разрешить управление чатом", "Allow Chat Delete": "Разрешить удаление чата", "Allow Chat Edit": "Разрешить редактирование чата", "Allow Chat Export": "Разрешить экспорт чата", + "Allow Chat Import": "", "Allow Chat Params": "Разрешить параметры чата", "Allow Chat Share": "Разрешить общий доступ к чату", "Allow Chat System Prompt": "Разрешить системный промпт чата", @@ -158,9 +186,11 @@ "Allow User Location": "Разрешить доступ к местоположению пользователя", "Allow Voice Interruption in Call": "Разрешить прерывание голоса во время вызова", "Allow Web Upload": "Разрешить загрузку из интернета", + "Allowed Domains": "", "Allowed Endpoints": "Разрешенные энд-поинты", "Allowed File Extensions": "Разрешенные расширения файлов", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Разрешенные расширения файлов для загрузки. Разделите несколько расширений запятыми. Оставьте поле пустым для всех типов файлов.", + "Allowed Roles": "", "Already have an account?": "У вас уже есть учетная запись?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Альтернатива top_p и направлена на обеспечение баланса качества и разнообразия. Параметр p представляет минимальную вероятность того, что токен будет рассмотрен, по сравнению с вероятностью наиболее вероятного токена. Например, при p=0,05 и наиболее вероятном значении токена, имеющем вероятность 0,9, логиты со значением менее 0,045 отфильтровываются.", "Always": "Всегда", @@ -179,6 +209,7 @@ "API Base URL": "Базовый адрес API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Базовый URL API для сервиса Datalab Marker. По умолчанию: https://www.datalab.to/api/v1/marker", "API Key": "Ключ API", + "API Key / Token": "", "API Key created.": "Ключ API создан.", "API Key Endpoint Restrictions": "Ограничения на энд-поинт API", "API keys": "Ключи API", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Вы уверены, что хотите удалить это воспоминание? Это действие нельзя отменить.", "Are you sure you want to delete this message?": "Вы уверены, что хотите удалить это сообщение?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Вы уверены, что хотите удалить эту версию? Дочерние версии будут привязаны к родительской.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Вы уверены, что хотите удалить это?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Вы уверены, что хотите разархивировать все заархивированные чаты?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Арена моделей", "Artifacts": "Артефакты", "Asc": "По возрастанию", "Ask": "Спросить", "Ask a question": "Задать вопрос", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Ассистент", "Async Embedding Processing": "Асинхронная обработка эмбеддингов", "At time of event": "В момент события", @@ -229,14 +265,20 @@ "Audio": "Аудио", "August": "Август", "Auth": "Вход", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Аутентификация", "Authentication": "Аутентификация", "Auto": "Автоматически", "Auto (Random)": "Автоматически (случайно)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Автоматическое копирование ответа в буфер обмена", - "Auto-playback response": "Автоматическое воспроизведение ответа", + "Auto-Create Groups": "", + "Auto-Playback Response": "Автоматическое воспроизведение ответа", "Autocomplete Generation": "Генерация автозаполнения", "Autocomplete Generation Input Max Length": "Максимальная длина входных данных автозаполнения", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Строка авторизации API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Базовый URL AUTOMATIC1111", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "Доступные инструменты", "available users": "доступные пользователи", + "Available variables": "", "available!": "доступно!", "Away": "Нет на месте", "Awful": "Ужасно", @@ -264,16 +307,17 @@ "Bad Response": "Плохой ответ", "Banners": "Баннеры", "Base Model (From)": "Базовая модель (от)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Кэш списка базовых моделей ускоряет доступ, загружая базовые модели только при запуске или сохранении настроек — быстрее, но может не показывать новые изменения в базовых моделях.", "Bearer": "Bearer", "before": "до", "Being lazy": "Лениво", - "Beta": "Бета", "Bing": "Bing", "Bing Search V7 Endpoint": "Энд-поинт поиска Bing V7", "Bing Search V7 Subscription Key": "Ключ API Bing Search V7", "Bio": "О себе", "Birth Date": "Дата рождения", + "Blocked Groups": "", "BM25 Weight": "Вес BM25", "Bocha Search API Key": "Ключ API поиска Bocha", "Bold": "Полужирный", @@ -330,7 +374,7 @@ "Chat Completions": "Chat Completions", "Chat Conversation": "Обсуждение в чате", "Chat deleted.": "Чат удален.", - "Chat direction": "Направление чата", + "Chat Direction": "Направление чата", "Chat exported successfully": "Чат успешно экспортирован", "Chat History": "История чата", "Chat ID": "ID чата", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "Канал для совместной работы с присоединением участников", "Collapse": "Свернуть", "Collection": "Коллекция", + "Collection Field": "", "Collections": "Коллекции", "Color": "Цвет", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "Рабочий процесс ComfyUI", "ComfyUI Workflow Nodes": "Узлы рабочего процесса ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID узлов через запятую (напр., 1 или 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "команда", "Command": "Команда", "Comment": "Комментарий", "Commit Message": "Добавить сообщение", "Community Reviews": "Отзывы сообщества", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Завершения", "Compress Images in Channels": "Сжимать изображения в каналах", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Подключение к экземплярам Open Terminal. Все пользователи получат доступ к файлам и терминалу через эти серверы.", "Connect to your own OpenAI compatible API endpoints.": "Подключитесь к своим собственным энд-поинтам API, совместимым с OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Подключитесь к вашим собственным внешним инструментальным серверам, совместимым с OpenAPI.", + "Connected": "", "Connected ({{type}})": "Подключено ({{type}})", "Connection failed": "Подключение не удалось", "Connection lost. Reconnecting...": "Соединение потеряно. Повторное подключение...", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Обратитесь к администратору для получения доступа к WebUI", "Content": "Содержание", "Content Extraction Engine": "Механизм извлечения контента", + "Content Field": "", "Content lengths (character counts only)": "Длина контента (только количество символов)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Токены контекста", + "Continue": "", "Continue Response": "Продолжить ответ", "Continue with {{provider}}": "Продолжить с {{provider}}", "Continue with Email": "Продолжить с Email", @@ -501,6 +557,7 @@ "Create new secret key": "Создать новый секретный ключ", "Create note": "Создать заметку", "Create Note": "Создать заметку", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Создавайте запланированные промпты, которые автоматически запускаются по повторяющемуся расписанию.", "Create your first note by clicking on the plus button below.": "Создайте свою первую заметку, нажав на кнопку плюс ниже.", "Created at": "Создан(а)", @@ -518,6 +575,7 @@ "Custom Gender": "Другой пол", "Custom Parameter Name": "Название пользовательского параметра", "Custom Parameter Value": "Значение пользовательского параметра", + "Custom range": "", "Daily": "Ежедневно", "Daily Messages": "Сообщений в день", "Danger Zone": "Опасная зона", @@ -540,7 +598,6 @@ "Default Features": "Функции по умолчанию", "Default Filters": "Фильтры по умолчанию", "Default Group": "Дефолтная группа", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Режим по умолчанию работает с более широким набором моделей и вызывает инструменты один раз перед выполнением. Нативный режим использует встроенные возможности модели для вызова инструментов и требует поддержки этой функции самой моделью.", "Default Model": "Модель по умолчанию", "Default model updated": "Модель по умолчанию обновлена", "Default permissions": "Разрешения по умолчанию", @@ -550,6 +607,7 @@ "Default to ALL": "По умолчанию ВСЕ", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "По умолчанию используется сегментированный поиск для целенаправленного извлечения релевантного контента, что рекомендуется в большинстве случаев.", "Default User Role": "Роль пользователя по умолчанию", + "Default webhook": "", "Defaults": "По умолчанию", "Delete": "Удалить", "Delete {{name}}": "Удалить {{name}}", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "Отключить интерпретатор кода", "Disable Image Extraction": "Отключить извлечение изображений", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Отключить извлечение изображений из PDF. Если включена параметр Использовать LLM, изображения будут подписаны автоматически. По умолчанию установлено значение Выкл.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Отключено", "Disconnect OAuth": "Отключить OAuth", "Discover a function": "Найти функцию", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Открывайте для себя, загружайте и исследуйте пользовательские предустановки моделей", "Discussion channel where access is based on groups and permissions": "Канал обсуждений с доступом по группам и правам", "Display": "Отображать", - "Display chat title in tab": "Показывать заголовок чата во вкладке", + "Display Chat Title in Tab": "Показывать заголовок чата во вкладке", "Display Emoji in Call": "Отображать эмодзи в вызовах", "Display Multi-model Responses in Tabs": "Отображать ответы нескольких моделей во вкладках", - "Display the username instead of You in the Chat": "Отображать имя пользователя вместо 'Вы' в чате", + "Display the Username Instead of You in the Chat": "Отображать имя пользователя вместо 'Вы' в чате", "Displays citations in the response": "Отображает цитаты в ответе", "Displays status updates (e.g., web search progress) in the response": "Отображает обновления статуса (например, прогресс поиска в сети) в ответе", "Dive into knowledge": "Погрузитесь в знания", @@ -638,6 +698,7 @@ "Docling Parameters": "Параметры Docling", "Docling Server URL required.": "Необходим URL сервера Docling", "Document": "Документ", + "Document ID Field": "", "Document Intelligence": "Интеллектуальный анализ документов", "Document Intelligence endpoint required.": "Требуется конечная точка Document Intelligence.", "Document Intelligence Model": "Модель Document Intelligence", @@ -693,12 +754,14 @@ "Edit Default Permissions": "Изменить разрешения по умолчанию", "Edit Folder": "Редактировать папку", "Edit Image": "Редактировать изображение", + "Edit Knowledge Connection": "", "Edit Last Message": "Редактировать последнее сообщение", "Edit Memory": "Редактировать воспоминание", "Edit Prompt": "Редактировать промпт", "Edit Terminal Connection": "Редактировать подключение к терминалу", "Edit User": "Редактировать пользователя", "Edit User Group": "Редактировать Пользовательскую Группу", + "Edit webhook": "", "Edit workflow.json content": "Редактировать содержимое workflow.json", "edited": "изменено", "Edited": "Отредактировано", @@ -707,6 +770,7 @@ "Eject model": "Выгрузить модель", "ElevenLabs": "ElevenLabs", "Email": "Электронная почта", + "Email Claim": "", "Embark on adventures": "Отправляйтесь в приключения", "Embedding": "Встраивание", "Embedding Batch Size": "Размер пакета для встраивания", @@ -715,6 +779,7 @@ "Embedding Model Engine": "Движок модели встраивания", "Emoji": "", "Emojis": "Эмодзи", + "Empty": "", "Empty message": "Пустое сообщение", "Enable All": "Включить Все", "Enable API Keys": "Включить API-ключи", @@ -722,22 +787,27 @@ "Enable Code Execution": "Включить исполнение кода", "Enable Code Interpreter": "Включить интерпретатор кода", "Enable Community Sharing": "Включить совместное использование", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Включите блокировку памяти (mlock), чтобы предотвратить выгрузку данных модели из ОЗУ. Эта опция блокирует рабочий набор страниц модели в оперативной памяти, гарантируя, что они не будут выгружены на диск. Это может помочь поддерживать производительность, избегая ошибок страниц и обеспечивая быстрый доступ к данным.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Включите отображение памяти (mmap), чтобы загрузить данные модели. Эта опция позволяет системе использовать дисковое хранилище в качестве расширения оперативной памяти, обрабатывая дисковые файлы так, как если бы они находились в оперативной памяти. Это может улучшить производительность модели за счет более быстрого доступа к данным. Однако он может работать некорректно со всеми системами и занимать значительный объем дискового пространства.", "Enable Message Queue": "Включить очередь сообщений", "Enable Message Rating": "Разрешить оценку ответов", "Enable Mirostat sampling for controlling perplexity.": "Включите выборку Mirostat для контроля путаницы.", "Enable New Sign Ups": "Разрешить новые регистрации", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Включить, отключить или настроить теги рассуждения, используемые моделью. \"Включено\" использует теги по умолчанию, \"Отключено\" выключает теги рассуждения, а \"Пользовательские\" позволяет указать собственные начальные и конечные теги.", "Enabled": "Включено", "End Tag": "Конечный тег", + "Endpoint": "", "Endpoint URL": "URL-адрес конечной точки", "Enforce Temporary Chat": "Принудительный временный чат", "Enhance": "Улучшить", "Enrich Hybrid Search Text": "Обогащать текст гибридного поиска", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Убедитесь, что ваш CSV-файл включает в себя 4 столбца в следующем порядке: Имя, Электронная почта, Пароль, Роль.", "Enter {{role}} message here": "Введите сообщение {{role}} здесь", - "Enter a detail about yourself for your LLMs to recall": "Введите детали о себе, чтобы LLMs могли запомнить", "Enter a title for the pending user info overlay. Leave empty for default.": "Введите заголовок информационного оверлея для ожидающего пользователя. Оставьте поле пустым для параметра по умолчанию.", "Enter a watermark for the response. Leave empty for none.": "Укажите водяной знак для ответа. Оставьте пустым чтобы не было никакого.", "Enter additional headers in JSON format": "Введите дополнительные заголовки в формате JSON", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "Введите минимальный размер чанка", "Enter Chunk Overlap": "Введите перекрытие фрагмента", "Enter Chunk Size": "Введите размер фрагмента", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Введите пары \"token:bias_value\", разделенные запятыми (пример: 5432:100, 413:-100).", "Enter content for the pending user info overlay. Leave empty for default.": "Введите содержимое информационного оверлея для ожидающего пользователя. Оставьте поле пустым для параметра по умолчанию.", "Enter coordinates (e.g. 51.505, -0.09)": "Введите координаты (напр. 51.505, -0.09)", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "Введите URL Jupyter", "Enter Kagi Search API Key": "Введите ключ API поиска Kagi", "Enter Key Behavior": "Введите ключ поведения", + "Enter language": "", "Enter language codes": "Введите коды языков", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Введите API-ключ MinerU", "Enter Mistral API Base URL": "Введите базовый URL Mistral API", "Enter Mistral API Key": "Введите ключ API для Mistral", @@ -812,6 +887,7 @@ "Enter prompt here.": "Введите промпт здесь.", "Enter proxy URL (e.g. https://user:password@host:port)": "Введите URL прокси-сервера (например, https://user:password@host:port)", "Enter reasoning effort": "Введите причинность рассудения", + "Enter Redirect URI": "", "Enter Score": "Введите оценку", "Enter SearchApi API Key": "Введите ключ API SearchApi", "Enter SearchApi Engine": "Введите SearchApi движок", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "Введите ключ API SerpApi", "Enter SerpApi Engine": "Введите движок SerpApi", "Enter Serper API Key": "Введите ключ API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Введите ключ API Serply", "Enter Serpstack API Key": "Введите ключ API Serpstack", "Enter server host": "Введите хост сервера", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Введите URL-адрес сервера Tika", "Enter timeout in seconds": "Введите время ожидания в секундах", "Enter to Send": "Enter для отправки", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Введите Top K", "Enter Top K Reranker": "Введите Top K переоценщика", "Enter URL (e.g. http://127.0.0.1:7860/)": "Введите URL-адрес (например, http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Ошибка: Модель с ID '{{modelId}}' уже существует. Пожалуйста, выберите другой ID для продолжения.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Ошибка: ID модели не может быть пустым. Пожалуйста, введите корректный ID для продолжения.", "Evaluations": "Оценки", + "Event": "", "Event created": "Событие создано", "Event deleted": "Событие удалено", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Название события", "Event updated": "Событие обновлено", + "Events": "", "Exa API Key": "Ключ API для Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Например: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Например: ALL", "Example: mail": "Example: mail", @@ -913,12 +996,18 @@ "Export Config": "Экспортировать конфигурации", "Export Models": "Экспортировать модели", "Export Prompts": "Экспортировать промпты", + "Export Skills": "", "Export to CSV": "Экспортировать в CSV", "Export Tools": "Экспортировать инструменты", "Export Users": "Экспортировать пользователей", "External": "Внешнее", + "External connection not found.": "", "External Document Loader URL required.": "Требуется URL-адрес внешнего загрузчика документов.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Модель внешней задачи", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Ключ API внешнего веб-загрузчика", "External Web Loader URL": "URL-адрес внешнего веб-загрузчика", "External Web Search API Key": "Внешний ключ API веб-поиска", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Не удалось создать ключ API.", "Failed to delete calendar": "Не удалось удалить календарь", "Failed to delete note": "Не удалось удалить заметку", + "Failed to delete webhook": "", "Failed to disconnect": "Не удалось отключиться", "Failed to download image": "Не удалось загрузить изображение", "Failed to extract content from the file: {{error}}": "Не удалось извлечь содержимое из файла: {{error}}", @@ -943,6 +1033,7 @@ "Failed to fetch models": "Не удалось получить модели", "Failed to generate title": "Не удалось сгенерировать заголовок", "Failed to import models": "Не удалось импортировать модели", + "Failed to load chat": "", "Failed to load chat preview": "Не удалось загрузить предпросмотр чата", "Failed to load DOCX file. Please try downloading it instead.": "Не удалось загрузить файл DOCX. Попробуйте скачать его.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Не удалось загрузить файл Excel/CSV. Попробуйте скачать его.", @@ -952,6 +1043,7 @@ "Failed to move chat": "Не удалось переместить чат", "Failed to process URL: {{url}}": "Не удалось обработать URL: {{url}}", "Failed to read clipboard contents": "Не удалось прочитать содержимое буфера обмена", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Не удалось удалить участника", "Failed to render diagram": "Не удалось отрисовать диаграмму", "Failed to render visualization": "Не удалось отрисовать визуализацию", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "Не удалось сохранить конфигурацию моделей", "Failed to save policy: {{error}}": "Не удалось сохранить политику: {{error}}", "Failed to save terminal servers": "Не удалось сохранить серверы терминала", + "Failed to save webhook": "", "Failed to unshare chat.": "Не удалось отменить публикацию чата.", "Failed to update settings": "Не удалось обновить настройки", "Failed to update status": "Не удалось обновить статус", + "Failed to update webhook": "", "Failed to upload file.": "Не удалось загрузить файл.", "Features": "Функции", "Features Permissions": "Разрешения для функций", @@ -995,6 +1089,8 @@ "File uploaded successfully": "Файл успешно загружен", "Filename": "Имя файла", "Files": "Файлы", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Фильтр", "Filter is now globally disabled": "Фильтр теперь отключен глобально", "Filter is now globally enabled": "Фильтр теперь включен глобально", @@ -1017,6 +1113,7 @@ "Folder options": "Параметры папки", "Folder updated successfully": "Папка успешно обновлена", "Folders": "Папки", + "Folders Sharing": "", "Follow up": "Продолжить", "Follow Up Generation": "Генерация продолжения", "Follow Up Generation Prompt": "Промпт генерации продолжения", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Функция теперь глобально включена", "Function Name": "Название Функции", "Function Name Filter List": "Фильтр по именам функций", + "Function starter": "", "Function updated successfully": "Функция успешно обновлена", "Functions": "Функции", "Functions allow arbitrary code execution.": "Функции позволяют выполнять произвольный код.", @@ -1079,7 +1177,10 @@ "Gravatar": "Gravatar", "Grid": "Сетка", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Групповой канал", + "Group Claim": "", "Group created successfully": "Группа успешно создана", "Group deleted successfully": "Группа успешно удалена", "Group Description": "Описание группы", @@ -1091,6 +1192,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Тактильная обратная связь", + "Header variables": "", "Headers": "Заголовки", "Headers must be a valid JSON object": "Заголовки должны быть валидным JSON-объектом", "Height": "Высота", @@ -1121,6 +1223,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID не может содержать символы «:» и «|»", "ID copied to clipboard": "ID скопирован в буфер обмена", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Тайм-аут простоя", "iframe Sandbox Allow Forms": "Позволять формы для iframe Sandbox", "iframe Sandbox Allow Same Origin": "Позволять одно и то же происхождение для iframe Sandbox", @@ -1146,6 +1250,7 @@ "Import From Link": "Импортировать по ссылке", "Import Models": "Импортировать модели", "Import Prompts": "Импортировать промпты", + "Import Skills": "", "Import successful": "Импорт выполнен", "Import Tools": "Импортировать инструменты", "Important Update": "Важное обновление", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "Оставить на боковой панели", "Key": "Ключ", "Key is required": "Ключ обязателен", - "Keyboard shortcuts": "Горячие клавиши", "Keyboard Shortcuts": "Горячие клавиши", "Knowledge": "Знания", "Knowledge Access": "Доступ к знаниям", @@ -1216,6 +1320,8 @@ "Knowledge Name": "Название знаний", "Knowledge Public Sharing": "Публичный доступ к базам знаний", "Knowledge Sharing": "Общий доступ к знаниям", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Знания успешно обновлены", "Kokoro.js (Browser)": "Kokoro.js (Браузер)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1232,7 +1338,6 @@ "Last ran": "Последний запуск", "Last reply": "Последний ответ", "LDAP": "LDAP", - "LDAP server updated": "LDAP сервер обновлен", "Leaderboard": "Таблица лидеров", "Learn more": "Подробнее", "Learn More": "Узнать больше", @@ -1254,6 +1359,7 @@ "Legacy": "Устаревшие", "lexical": "лексический", "License": "Лицензия", + "Lifecycle JSON": "", "Lift List": "Поднять список", "Light": "Светлый", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Лимит параллельных поисковых запросов. 0 = без ограничений (по умолчанию). Установите 1 для последовательного выполнения (рекомендуется для API со строгими лимитами, например, бесплатный тариф Brave).", @@ -1277,6 +1383,7 @@ "Location access not allowed": "Доступ к местоположению запрещен", "Lost": "Поражение", "Low": "Низкий", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Сделано сообществом OpenWebUI", "Make password visible in the user interface": "Показать пароль в пользовательском интерфейсе", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Управление конвейерами", "Manage Tool Servers": "Управление серверами инструментов", "Manage your account information.": "Управляйте информацией о своей учетной записи.", + "Mapped Source": "", "March": "Март", "Markdown": "Markdown", "Markdown Header Text Splitter": "Разделение текста по заголовкам Markdown", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Воспоминания успешно очищены", "Memory deleted successfully": "Воспоминание успешно удалено", "Memory updated successfully": "Воспоминание успешно обновлено", + "Merge Accounts by Email": "", "Merge Responses": "Объединить ответы", "Merged Response": "Объединенный ответ", "Message": "Сообщение", @@ -1330,9 +1439,12 @@ "messages": "сообщения", "Messages": "Сообщения", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Сообщения, отправленные вами после создания ссылки, не будут передаваться другим. Пользователи, у которых есть URL, смогут просматривать общий чат.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (личный)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (работа/школа)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "мин", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "API-ключ MinerU необходим для режима Cloud API.", @@ -1385,6 +1497,7 @@ "Models Sharing": "Общий доступ к моделям", "Mojeek": "Mojeek", "Mojeek Search API Key": "Ключ API для поиска Mojeek", + "Monday – Friday": "", "Month": "Месяц", "Monthly": "Ежемесячно", "More": "Больше", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "Назовите свою базу знаний", "Name, prompt, and model are required": "Требуются название, промпт и модель", "Native": "Нативный", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Никогда", "New": "Новый", "New Automation": "Новая автоматизация", @@ -1431,6 +1545,7 @@ "Next run": "Следующий запуск", "No access grants. Private to you.": "Нет прав доступа. Доступно только вам.", "No activity data": "Нет данных об активности", + "No additional headers are sent unless configured.": "", "No authentication": "Без аутентификации", "No automations found": "Автоматизации не найдены", "No chats found": "Чаты не найдены", @@ -1443,8 +1558,10 @@ "No data": "Нет данных", "No data found": "Данные не найдены", "No distance available": "Расстояние недоступно", + "No event webhooks configured.": "", "No execution logs available yet": "Журналы выполнения пока отсутствуют", "No expiration can pose security risks.": "Отсутствие срока действия может представлять угрозу безопасности.", + "No external knowledge sources configured.": "", "No feedback found": "Отзывы не найдены", "No file selected": "Файлы не выбраны", "No files found": "Файлы не найдены", @@ -1472,6 +1589,7 @@ "No output items": "Нет элементов вывода", "No pinned messages": "Нет закреплённых сообщений", "No prompts found": "Промпты не найдены", + "No Repeat": "", "No results": "Результатов не найдено", "No results found": "Результатов не найдено", "No search query generated": "Поисковый запрос не сгенерирован", @@ -1491,6 +1609,7 @@ "No webhooks yet": "Вебхуков пока нет", "Node Ids": "ID узлов", "None": "Нет", + "Not configured": "", "Not factually correct": "Не соответствует действительности", "Not helpful": "Бесполезно", "Not Registered": "Не зарегистрирован", @@ -1506,20 +1625,25 @@ "Notifications": "Уведомления", "November": "Ноябрь", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Static)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "URL сервера OAuth", "OAuth session disconnected": "Сеанс OAuth отключен", "October": "Октябрь", "Off": "Выключено", "Okay, Let's Go!": "Давайте начнём!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED темная", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Параметры Ollama API обновлены", "Ollama Cloud API Key": "API-ключ Ollama Cloud", "Ollama Version": "Версия Ollama", + "Omit": "", "On": "Включено", "Once": "Один раз", "OneDrive": "OneDrive", @@ -1590,6 +1714,7 @@ "Password": "Пароль", "Passwords do not match.": "Пароли не совпадают.", "Paste Large Text as File": "Вставить большой текст как файл", + "Path": "", "Path copied": "Путь скопирован", "Paused": "Приостановлено", "PDF document (.pdf)": "PDF-документ (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "ожидающий", "Pending": "Ожидающий", + "Pending Accounts": "", "Pending User Overlay Content": "Содержимое оверлея ожидающего пользователя", "Pending User Overlay Title": "Заголовк оверлея ожидающего пользователя", "Permission denied when accessing media devices": "Отказано в разрешении на доступ к мультимедийным устройствам", "Permission denied when accessing microphone": "Отказано в разрешении на доступ к микрофону", "Permission denied when accessing microphone: {{error}}": "Отказано в разрешении на доступ к микрофону: {{error}}", "Permissions": "Разрешения", + "Permissions reset to defaults": "", "Perplexity API Key": "Ключ API для Perplexity", "Perplexity Model": "Модель Perplexity", "Perplexity Search API URL": "Perplexity Search API URL", "Perplexity Search Context Usage": "Использование контекста поиска Perplexity", "Persistent": "Постоянный", "Personalization": "Персонализация", + "Picture Claim": "", "Pin": "Закрепить", "Pin to Sidebar": "Закрепить на боковой панели", "Pinned": "Закреплено", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "Пожалуйста, заполните все поля.", "Please register the OAuth client": "Пожалуйста, зарегистрируйте OAuth-клиент", "Please save the connection to persist the OAuth client information and do not change the ID": "Пожалуйста, сохраните подключение для сохранения данных OAuth-клиента и не меняйте ID", - "Please select a model first.": "Пожалуйста, сначала выберите модель.", "Please select a model.": "Пожалуйста, выберите модель.", "Please select a reason": "Пожалуйста, выберите причину", "Please select a valid JSON file": "Пожалуйста, выберите корректный JSON-файл", "Please select at least one user for Direct Message channel.": "Пожалуйста, выберите хотя бы одного пользователя для канала личных сообщений.", "Please wait until all files are uploaded.": "Пожалуйста, подождите, пока все файлы будут загружены.", "Policy ID": "ID политики", + "Policy ID is required": "", "Port": "Порт", "Ports": "Порты", "Positive attitude": "Позитивный настрой", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "Публичный доступ к промптам", "Prompts Sharing": "Общий доступ к промптам", "Provider": "Провайдер", + "Provider Name": "", + "Provider URL": "", "Public": "Публичное", "Pull \"{{searchValue}}\" from Ollama.com": "Загрузить \"{{searchValue}}\" с Ollama.com", "Pull a model from Ollama.com": "Загрузить модель с Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "Прочитать", "Read Aloud": "Прочитать вслух", "Read more →": "Читать далее →", + "Read only": "", "Read Only": "Только чтение", "Read-Only Access": "Доступ только для чтения", "Reason": "Причина", "Reasoning Effort": "Усилия для рассуждения", "Reasoning Tags": "Теги рассуждения", "Reasoning text...": "Текст рассуждения...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Недавно использованные", "Reconnected": "Подключение восстановлено", "Record": "Запись", "Record voice": "Записать голос", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Перенаправляем вас в сообщество OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Снижает вероятность появления бессмыслицы. Большее значение (например, 100) даст более разнообразные ответы, в то время как меньшее значение (например, 10) будет более консервативным.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Называйте себя \"User\" (например, \"User is learning Spanish\").", "Reference Chats": "Чаты для контекста", "Refresh": "Обновить", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Необоснованный отказ", "Regenerate": "Перегенерировать", "Regenerate Menu": "Обновить меню", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "Отображать Markdown в предпросмотре", "Render Markdown in User Messages": "Отображать Markdown в сообщениях пользователя", "Reorder Models": "Изменение порядка моделей", + "Repeat": "", "Repeats": "Повторяется", "Reply": "Ответить", "Reply in Thread": "Ответить в обсуждении", "Reply to thread...": "Ответить в обсуждении...", "Replying to {{NAME}}": "Ответ для {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "обязательно", "Reranking Batch Size": "Размер пакета реранжирования", "Reranking Engine": "Движок реранжирования", "Reranking Model": "Модель реранжирования", + "Research Knowledge": "", "Reset": "Сбросить", "Reset All Models": "Сбросить все модели", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Сбросить изображение", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Сбросить каталог загрузок", "Reset Vector Storage/Knowledge": "Сброс векторного хранилища/знаний", "Reset view": "Сбросить вид", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "Найден 1 источник", "Rich Text Input for Chat": "Ввод обогащённого текста (Rich text) в чат", "Role": "Роль", + "Roles Claim": "", "RTL": "RTL", "Run": "Запустить", "Run All": "Запустить все", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Прямое сохранение журналов чата в хранилище вашего браузера больше не поддерживается. Пожалуйста, потратьте минуту, чтобы скачать и удалить ваши журналы чата, нажав на кнопку ниже. Не волнуйтесь, вы легко сможете повторно импортировать свои журналы чата в бэкенд через", "Schedule": "Расписание", "Scheduled time must be in the future": "Запланированное время должно быть в будущем", + "Scopes": "", "Scroll On Branch Change": "Прокручивать при изменении ветки", "Scroll to Top": "Прокрутить наверх", "Search": "Поиск", "Search a model": "Поиск по моделям", + "Search actions": "", "Search all emojis": "Поиск по всем эмодзи", "Search and manage user memories": "Поиск и управление воспоминаниями пользователя", "Search and view user chat history": "Поиск и просмотр истории чатов пользователя", @@ -1810,6 +1960,7 @@ "Search Chats": "Поиск в чатах", "Search Collection": "Поиск коллекции", "Search Files": "Поиск файлов", + "Search filters": "", "Search Filters": "Поиск фильтров", "search for archived chats": "поиск архивных чатов", "search for folders": "поиск папок", @@ -1824,13 +1975,16 @@ "Search Models": "Поиск моделей", "Search Notes": "Поиск заметок", "Search options": "Параметры поиска", + "Search or add pattern": "", "Search Prompts": "Поиск промптов", "Search Result Count": "Количество результатов поиска", + "Search skills": "", "Search Skills": "Поиск скиллов", - "Search skills...": "", "Search the internet": "Искать в интернете", "Search the web and fetch URLs": "Поиск в интернете и загрузка URL", + "Search tools": "", "Search Tools": "Поиск инструментов", + "Search users or groups": "", "Search, view, and manage user notes": "Поиск, просмотр и управление заметками пользователя", "SearchApi API Key": "Ключ SearchApi API", "SearchApi Engine": "Движок SearchApi", @@ -1846,7 +2000,6 @@ "Seed": "Начальное значение", "Select": "Выбрать", "Select {{modelName}} model": "Выбрать модель {{modelName}}", - "Select a base model": "Выберите базовую модель", "Select a base model (e.g. llama3, gpt-4o)": "Выберите базовую модель (напр. llama3, gpt-4o)", "Select a conversation to preview": "Выберите разговор для предварительного просмотра", "Select a engine": "Выберите движок", @@ -1884,18 +2037,25 @@ "semantic": "семантический", "Send": "Отправить", "Send a Message": "Отправить сообщение", + "Send events for": "", "Send message": "Отправить сообщение", "Send now": "Отправить сейчас", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Отправляет в запросе \"stream_options: { include_usage: true }\".\nПоддерживаемые провайдеры будут возвращать информацию об использовании токена в ответе, когда это будет установлено.", "September": "Сентябрь", "SerpApi API Key": "Ключ API для SerpApi", "SerpApi Engine": "Движок SerpApi", "Serper API Key": "Ключ API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Ключ API Serply", "Serpstack API Key": "Ключ API Serpstack", "Server connection failed": "Ошибка подключения к серверу", "Server connection verified": "Соединение с сервером проверено", + "Service Account": "", "Session": "Сессия", + "Session expired. Please sign in again.": "", "Set as default": "Установить по умолчанию", "Set as Production": "Сделать рабочей", "Set embedding model": "Установить модель эмбеддинга", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "Ссылка скопирована в буфер обмена.", "Share to Open WebUI Community": "Поделиться с сообществом OpenWebUI", "Share your background and interests": "Расскажите о своём опыте и интересах", + "Shared": "", "Shared Chats": "Общие чаты", "Shared with you": "Доступные вам", "Sharing Permissions": "Разрешения на общий доступ", "Show": "Показать", - "Show \"What's New\" modal on login": "Показывать окно «Что нового» при входе в систему", + "Show \"What's New\" Modal on Login": "Показывать окно «Что нового» при входе в систему", "Show Admin Details in Account Pending Overlay": "Показывать данные администратора в оверлее ожидающей учетной записи", "Show All": "Показать все", "Show all ({{COUNT}} characters)": "Показать всё ({{COUNT}} символов)", "Show Files": "Показать файлы", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Показать панель форматирования", "Show image preview": "Показать предварительный просмотр изображения", "Show Model": "Показать модель", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Источник", + "Specific users or groups": "", "Speech Playback Speed": "Скорость воспроизведения речи", "Speech recognition error: {{error}}": "Ошибка распознавания речи: {{error}}", "Speech-to-Text": "Речь в текст", @@ -2013,6 +2176,7 @@ "STT Settings": "Настройки распознавания речи", "Stylized PDF Export": "Стилизованный экспорт в формате PDF", "Su_day_of_week": "Вс", + "Sub Claim": "", "Submit question": "Отправить вопрос", "Submit suggestion": "Отправить предложение", "Subtitle": "Подзаголовок", @@ -2037,8 +2201,10 @@ "Syncing...": "Синхронизация...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Синхронизирует только чаты, обновлённые после последней синхронизации. Отключите для повторной синхронизации всех чатов.", "System": "Система", + "System events only": "", "System Instructions": "Системные инструкции", "System Prompt": "Системный промпт", + "Table": "", "Tag": "Тег", "Tags": "Теги", "Tags Generation": "Генерация тегов", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "Временный чат по умолчанию", "Terminal": "Терминал", "Terminal servers saved": "Серверы терминала сохранены", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Разделитель текста", "Text-to-Speech": "Текст в речь", "Text-to-Speech Engine": "Система синтеза речи", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Язык входного аудиосигнала. Укажите язык ввода в формате ISO-639-1 (например, en), что повысит точность и время ожидания. Оставьте поле пустым для автоматического определения языка.", "The LDAP attribute that maps to the mail that users use to sign in.": "Атрибут LDAP, который сопоставляется с почтой, используемой пользователями для входа в систему.", "The LDAP attribute that maps to the username that users use to sign in.": "Атрибут LDAP, который сопоставляется с именем пользователя, используемым пользователями для входа в систему.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "В настоящее время таблица лидеров находится в стадии бета-тестирования, и мы можем скорректировать расчеты рейтинга по мере доработки алгоритма.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Максимальный размер файла в МБ. Если размер файла превысит это ограничение, файл не будет загружен.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Максимальное количество файлов, которые могут быть использованы одновременно в чате. Если количество файлов превысит это ограничение, файлы не будут загружены.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Формат вывода текста. Может быть 'json', 'markdown', или 'html'. По умолчанию 'markdown'.", @@ -2096,6 +2267,7 @@ "This folder is empty": "Эта папка пуста", "This is a default user permission and will remain enabled.": "Это разрешение по умолчанию, оно остаётся включённым.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Это экспериментальная функция, она может работать не так, как ожидалось, и может быть изменена в любое время.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Эта модель недоступна в открытом доступе. Пожалуйста, выберите другую модель.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Этот параметр определяет, как долго модель будет оставаться загруженной в память после запроса (по умолчанию: 5 месяцев).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Этот параметр определяет, сколько токенов сохраняется при обновлении контекста. Например, если задано значение 2, будут сохранены последние 2 токена контекста беседы. Сохранение контекста может помочь сохранить непрерывность беседы, но может уменьшить возможность отвечать на новые темы.", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "Чтобы узнать больше о доступных энд-поинтах, ознакомьтесь с нашей документацией.", "To select skills here, add them to the \"Skills\" workspace first.": "Чтобы выбрать скиллы здесь, сначала добавьте их в раздел «Скиллы».", "To select toolkits here, add them to the \"Tools\" workspace first.": "Чтобы выбрать инструменты, сначала добавьте их в \"Инструменты\" рабочего пространства.", - "Toast notifications for new updates": "Уведомления о обновлениях", + "Toast Notifications for New Updates": "Уведомления о обновлениях", "Today": "Сегодня", "Today at": "Сегодня в", "Today at {{LOCALIZED_TIME}}": "Сегодня в {{LOCALIZED_TIME}}", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "Переключить, активно ли текущее соединение.", "Token": "Токен", "Token counts are estimates and may not reflect actual API usage": "Количество токенов является приблизительным и может не отражать фактическое использование API", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "токены", "Tokens": "Токены", "Too verbose": "Слишком многословно", @@ -2198,14 +2372,19 @@ "Unpin": "Открепить", "Unpin from Sidebar": "Открепить от боковой панели", "Unravel secrets": "Разгадать секреты", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Отменить публикацию чата", "Unsupported file type.": "Неподдерживаемый тип файла.", "Untagged": "Без тегов", "Untitled": "Без заголовка", "Update": "Обновить", "Update and Copy Link": "Обновить и скопировать ссылку", + "Update Email": "", "Update for the latest features and improvements.": "Обновитесь для получения последних функций и улучшений.", + "Update Name": "", "Update password": "Обновить пароль", + "Update Picture": "", "Update your status": "Обновите свой статус", "Updated": "Обновлено", "Updated at": "Обновлено", @@ -2232,13 +2411,18 @@ "Use": "Использовать", "Use '#' in the prompt input to load and include your knowledge.": "Используйте «#» в строке ввода, чтобы загрузить и включить свои знания.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Используйте эндпоинт /v1/chat/completions вместо /v1/audio/transcriptions для потенциально лучшей точности.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Использовать Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Используйте группы для организации пользователей и назначения прав.", "Use LLM": "Использовать LLM", "Use no proxy to fetch page contents.": "Не используйте прокси-сервер для получения содержимого страницы.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Используйте прокси-сервер, обозначенный переменными окружения http_proxy и https_proxy, для получения содержимого страницы.", + "Use Web Search?": "", "user": "пользователь", "User": "Пользователь", + "User Access": "", "User Activity": "Активность пользователей", "User Groups": "Группы пользователей", "User location successfully retrieved.": "Местоположение пользователя успешно получено.", @@ -2248,6 +2432,7 @@ "User Status": "Статус пользователя", "User Webhooks": "Пользовательские веб-хуки", "Username": "Имя пользователя", + "Username Claim": "", "users": "пользователи", "Users": "Пользователи", "Uses DefaultAzureCredential to authenticate": "Использует DefaultAzureCredential для аутентификации", @@ -2261,6 +2446,7 @@ "Valves updated": "Параметры обновлены", "Valves updated successfully": "Параметры успешно обновлены", "variable": "переменная", + "Vector Field": "", "Verify Connection": "Проверить подключение", "Verify SSL Certificate": "Проверять SSL-сертификат", "Version": "Версия", @@ -2290,11 +2476,14 @@ "Web API": "Веб API", "Web Loader Engine": "Движок веб-загрузчика", "Web Search": "Веб-поиск", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Поисковая система", "Web Search in Chat": "Поисковая система в чате", "Web Search Query Generation": "Генерация запросов веб-поиска", + "Webhook deleted": "", "Webhook Name": "Название вебхука", - "Webhook URL": "URL-адрес веб-хука", + "Webhook saved": "", "Webhooks": "Вебхуки", "Webpage URLs": "URL веб-страниц", "WebUI Settings": "Настройки WebUI", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "API-ключ Яндекс Поиска", "Yandex Web Search config": "Настройки Яндекс Поиска", "Yandex Web Search URL": "URL Яндекс Поиска", + "Yearly": "", "Yesterday": "Вчера", "Yesterday at {{LOCALIZED_TIME}}": "Вчера в {{LOCALIZED_TIME}}", "You": "Вы", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "Ваш браузер не поддерживает тег video.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Весь ваш взнос будет направлен непосредственно разработчику плагина; Open WebUI не взимает никаких процентов. Однако выбранная платформа финансирования может иметь свои собственные сборы.", "Your message text or inputs": "Текст ваших сообщений", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Ваша статистика использования успешно синхронизирована.", "YouTube": "YouTube", "Youtube Language": "Язык YouTube", diff --git a/src/lib/i18n/locales/sk-SK/translation.json b/src/lib/i18n/locales/sk-SK/translation.json index 501e3888bc..1f6aea91cc 100644 --- a/src/lib/i18n/locales/sk-SK/translation.json +++ b/src/lib/i18n/locales/sk-SK/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "{{user}}'s konverzácie", "{{webUIName}} Backend Required": "Vyžaduje sa {{webUIName}} Backend", "*Prompt node ID(s) are required for image generation": "*Sú potrebné IDs pre prompt node na generovanie obrázkov", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -63,6 +79,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Prístupné pre všetkých užívateľov", "Account": "Účet", @@ -78,6 +95,7 @@ "Activity": "", "Add": "Pridať", "Add a model ID": "Pridať ID modelu", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Pridajte krátky popis toho, čo tento model robí.", "Add a tag": "Pridať štítok", "Add a tag...": "", @@ -90,8 +108,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Pridať súbory", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -106,6 +126,7 @@ "Add to favorites": "", "Add User": "Pridať užívateľa", "Add User Group": "Pridať skupinu užívateľov", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -118,7 +139,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Admin panel", + "Admin Roles": "", "Admin Settings": "Nastavenia admina", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administrátori majú prístup ku všetkým nástrojom kedykoľvek; užívatelia potrebujú mať nástroje priradené podľa modelu v workspace.", "Advanced": "", "Advanced Parameters": "Pokročilé parametre", @@ -129,16 +152,21 @@ "All": "Všetky", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Všetky modely úspešne odstránené", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "Povoliť odstránenie chatu", "Allow Chat Edit": "Povoliť úpravu chatu", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -158,9 +186,11 @@ "Allow User Location": "Povoliť užívateľskú polohu", "Allow Voice Interruption in Call": "Povoliť prerušenie hlasu počas hovoru", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Už máte účet?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Vždy", @@ -179,6 +209,7 @@ "API Base URL": "Základná URL adresa API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API kľúč", + "API Key / Token": "", "API Key created.": "API kľúč bol vytvorený.", "API Key Endpoint Restrictions": "", "API keys": "API kľúče", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena modely", "Artifacts": "Artefakty", "Asc": "", "Ask": "", "Ask a question": "Opýtajte sa otázku", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistent", "Async Embedding Processing": "", "At time of event": "", @@ -229,14 +265,20 @@ "Audio": "Zvuk", "August": "August", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentifikovať", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatické kopírovanie odpovede do schránky", - "Auto-playback response": "Automatická odpoveď pri prehrávaní", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatická odpoveď pri prehrávaní", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "Základná URL pre AUTOMATIC1111", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "", "available users": "dostupní používatelia", + "Available variables": "", "available!": "k dispozícii!", "Away": "Neprítomný", "Awful": "", @@ -264,16 +307,17 @@ "Bad Response": "Zlá odozva", "Banners": "Bannery", "Base Model (From)": "Základný model (z)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "pred", "Being lazy": "", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -330,7 +374,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Smer chatu", + "Chat Direction": "Smer chatu", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "", + "Collection Field": "", "Collections": "", "Color": "Farba", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "Pracovný postup ComfyUI", "ComfyUI Workflow Nodes": "Pracovné uzly ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Príkaz", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Doplnenia", "Compress Images in Channels": "", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Kontaktujte administrátora pre prístup k webovému rozhraniu.", "Content": "Obsah", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Pokračovať v odpovedi", "Continue with {{provider}}": "Pokračovať s {{provider}}", "Continue with Email": "", @@ -501,6 +557,7 @@ "Create new secret key": "Vytvoriť nový tajný kľúč", "Create note": "Vytvoriť poznámku", "Create Note": "Vytvoriť Poznámku", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Vytvorené dňa", @@ -518,6 +575,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Nebezpečná zóna", @@ -540,7 +598,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Predvolený model", "Default model updated": "Predvolený model aktualizovaný.", "Default permissions": "Predvolené povolenia", @@ -550,6 +607,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Predvolená rola užívateľa", + "Default webhook": "", "Defaults": "", "Delete": "Odstrániť", "Delete {{name}}": "", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Zakázané", "Disconnect OAuth": "", "Discover a function": "Objaviť funkciu", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Objavte, stiahnite a preskúmajte prednastavenia modelov", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Zobrazenie emoji počas hovoru", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Zobraziť užívateľské meno namiesto \"Vás\" v chate", + "Display the Username Instead of You in the Chat": "Zobraziť užívateľské meno namiesto \"Vás\" v chate", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -638,6 +698,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -693,12 +754,14 @@ "Edit Default Permissions": "", "Edit Folder": "Upraviť priečinok", "Edit Image": "Upraviť obrázok", + "Edit Knowledge Connection": "", "Edit Last Message": "Upraviť poslednú správu", "Edit Memory": "Upraviť pamäť", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Upraviť užívateľa", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "upravené", "Edited": "Upravené", @@ -707,6 +770,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "E-mail", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -715,6 +779,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -722,22 +787,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Povoliť zdieľanie komunity", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "Povoliť hodnotenie správ", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Povoliť nové registrácie", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Povolené", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Uistite sa, že váš CSV súbor obsahuje 4 stĺpce v tomto poradí: Name, Email, Password, Role.", "Enter {{role}} message here": "Zadajte správu {{role}} sem", - "Enter a detail about yourself for your LLMs to recall": "Zadajte podrobnosť o sebe, ktorú si vaše LLM majú zapamätať.", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Zadajte prekryv časti", "Enter Chunk Size": "Zadajte veľkosť časti", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Zadajte kódy jazykov", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -812,6 +887,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Zadajte skóre", "Enter SearchApi API Key": "Zadajte API kľúč pre SearchApi", "Enter SearchApi Engine": "Zadajte vyhľadávací engine SearchApi", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Zadajte Serper API kľúč", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Zadajte API kľúč pre Serply", "Enter Serpstack API Key": "Zadajte kľúč API pre Serpstack", "Enter server host": "", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Zadajte URL servera Tika", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Zadajte horné K", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Zadajte URL (napr. http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Hodnotenia", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -913,12 +996,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "Externé", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Nepodarilo sa vytvoriť API kľúč.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -943,6 +1033,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -952,6 +1043,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepodarilo sa prečítať obsah schránky", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Nepodarilo sa aktualizovať nastavenia", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Nepodarilo sa nahrať súbor.", "Features": "", "Features Permissions": "", @@ -995,6 +1089,8 @@ "File uploaded successfully": "Súbor bol úspešne nahraný", "Filename": "", "Files": "Súbory", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filter je teraz globálne zakázaný", "Filter is now globally enabled": "Filter je teraz globálne povolený.", @@ -1017,6 +1113,7 @@ "Folder options": "", "Folder updated successfully": "Priečinok bol úspešne aktualizovaný.", "Folders": "Priečinky", + "Folders Sharing": "", "Follow up": "Doplňujúce otázky", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Funkcia je teraz globálne povolená.", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funkcia bola úspešne aktualizovaná.", "Functions": "Funkcie", "Functions allow arbitrary code execution.": "Funkcie umožňujú vykonávanie ľubovoľného kódu.", @@ -1079,7 +1177,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1091,6 +1192,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Haptická spätná väzba", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1121,6 +1223,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1146,6 +1250,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Dôležitá aktualizácia", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "Klávesové skratky", "Keyboard Shortcuts": "", "Knowledge": "Znalosti", "Knowledge Access": "", @@ -1216,6 +1320,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Znalosti úspešne aktualizované", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1232,7 +1338,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "Rebríček", "Learn more": "", "Learn More": "", @@ -1254,6 +1359,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Svetlo", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1277,6 +1383,7 @@ "Location access not allowed": "", "Lost": "Stratený", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Vytvorené komunitou OpenWebUI", "Make password visible in the user interface": "", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Správa pipelines", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Marec", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Pamäť bola úspešne vymazaná.", "Memory deleted successfully": "Pamäť bola úspešne vymazaná", "Memory updated successfully": "Pamäť úspešne aktualizovaná", + "Merge Accounts by Email": "", "Merge Responses": "Zlúčiť odpovede", "Merged Response": "Zlúčená odpoveď", "Message": "", @@ -1330,9 +1439,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Správy, ktoré odošlete po vytvorení odkazu, nebudú zdieľané. Používatelia s URL budú môcť zobraziť zdieľaný chat.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1385,6 +1497,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Viac", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "Pomenujte svoju databázu znalostí", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "Nový", "New Automation": "", @@ -1431,6 +1545,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "Žiadne konverzácie neboli nájdené", @@ -1443,8 +1558,10 @@ "No data": "", "No data found": "", "No distance available": "Nie je dostupná žiadna vzdialenosť", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Nebola vybratá žiadna súbor", "No files found": "", @@ -1472,6 +1589,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Neboli nájdené žiadne výsledky", "No results found": "Neboli nájdené žiadne výsledky", "No search query generated": "Nebola vygenerovaná žiadna vyhľadávacia otázka.", @@ -1491,6 +1609,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Žiadny", + "Not configured": "", "Not factually correct": "Nie je fakticky správne", "Not helpful": "Nepomocné", "Not Registered": "", @@ -1506,20 +1625,25 @@ "Notifications": "Oznámenia", "November": "November", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Október", "Off": "Vypnuté", "Okay, Let's Go!": "Dobre, poďme na to!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Dark", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Verzia Ollama", + "Omit": "", "On": "Zapnuté", "Once": "", "OneDrive": "", @@ -1590,6 +1714,7 @@ "Password": "Heslo", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF dokument (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "čaká na vybavenie", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Odmietnutie povolenia pri prístupe k mediálnym zariadeniam", "Permission denied when accessing microphone": "Prístup k mikrofónu bol zamietnutý", "Permission denied when accessing microphone: {{error}}": "Oprávnenie zamietnuté pri prístupe k mikrofónu: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Personalizácia", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "Prosím, vyplňte všetky polia.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "Prosím vyberte dôvod", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Pozitívny prístup", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Verejné", "Pull \"{{searchValue}}\" from Ollama.com": "Stiahnite \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Stiahnite model z Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "", "Read Aloud": "Čítať nahlas", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Nahrať hlas", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Presmerovanie na komunitu OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Odkazujte na seba ako na \"užívateľa\" (napr. \"Užívateľ sa učí španielsky\").", "Reference Chats": "Odkázať na chaty", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Odmietnuté, keď nemalo byť.", "Regenerate": "Regenerovať", "Regenerate Menu": "", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Model na prehodnotenie poradia", + "Research Knowledge": "", "Reset": "režim Reset", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Resetovať obrázok", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Resetovať adresár nahrávania", "Reset Vector Storage/Knowledge": "Resetovanie úložiska vektorov/znalostí", "Reset view": "", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Vstup pre chat vo formáte Rich Text", "Role": "Funkcia", + "Roles Claim": "", "RTL": "RTL", "Run": "Spustiť", "Run All": "", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Ukladanie záznamov chatu priamo do úložiska vášho prehliadača už nie je podporované. Venujte prosím chvíľu stiahnutiu a vymazaniu svojich záznamov chatu kliknutím na tlačidlo nižšie. Nemajte obavy, môžete ľahko znovu importovať svoje záznamy chatu na backend prostredníctvom", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Vyhľadávanie", "Search a model": "Vyhľadať model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1810,6 +1960,7 @@ "Search Chats": "Vyhľadávanie v chate", "Search Collection": "Hľadať kolekciu", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1824,13 +1975,16 @@ "Search Models": "Vyhľadávacie modely", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "Vyhľadávacie dotazy", "Search Result Count": "Počet výsledkov hľadania", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Nástroje na vyhľadávanie", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Kľúč API pre SearchApi", "SearchApi Engine": "Vyhľadávací engine API", @@ -1846,7 +2000,6 @@ "Seed": "Semienko", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Vyberte základný model", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Vyberte engine", @@ -1884,18 +2037,25 @@ "semantic": "", "Send": "Odoslať", "Send a Message": "Odoslať správu", + "Send events for": "", "Send message": "Odoslať správu", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Odošle `stream_options: { include_usage: true }` v žiadosti. Podporovaní poskytovatelia vrátia informácie o využití tokenov v odpovedi, keď je táto možnosť nastavená.", "September": "September", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Kľúč API pre Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API kľúč", "Serpstack API Key": "Kľúč API pre Serpstack", "Server connection failed": "", "Server connection verified": "Pripojenie k serveru overené", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Nastaviť ako predvolené", "Set as Production": "", "Set embedding model": "", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Zdieľať s komunitou OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Zobraziť", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "Zobraziť podrobnosti administrátora v prekryvnom okne s čakajúcim účtom", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Zdroj", + "Specific users or groups": "", "Speech Playback Speed": "Rýchlosť prehrávania reči", "Speech recognition error: {{error}}": "Chyba rozpoznávania reči: {{error}}", "Speech-to-Text": "", @@ -2013,6 +2176,7 @@ "STT Settings": "Nastavenia STT (Rozpoznávanie reči)", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2037,8 +2201,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Systém", + "System events only": "", "System Instructions": "", "System Prompt": "Systémový prompt", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Rozdeľovač textu", "Text-to-Speech": "", "Text-to-Speech Engine": "Stroj na prevod textu na reč", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Hodnotiaca tabuľka je momentálne v beta verzii a môžeme upraviť výpočty hodnotenia, ako budeme zdokonaľovať algoritmus.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Maximálna veľkosť súboru v MB. Ak veľkosť súboru presiahne tento limit, súbor nebude nahraný.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Maximálny počet súborov, ktoré je možné použiť naraz v chate. Ak počet súborov presiahne tento limit, súbory nebudú nahrané.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2096,6 +2267,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Toto je experimentálna funkcia, nemusí fungovať podľa očakávania a môže byť kedykoľvek zmenená.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Ak chcete tu vybrať nástroje, pridajte ich najprv do pracovného priestoru \"Tools\".", - "Toast notifications for new updates": "Oznámenia vo forme toastov pre nové aktualizácie", + "Toast Notifications for New Updates": "Oznámenia vo forme toastov pre nové aktualizácie", "Today": "Dnes", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Príliš rozvláčne", @@ -2198,14 +2372,19 @@ "Unpin": "Odopnúť", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Nebola označená", "Untitled": "", "Update": "Aktualizovať", "Update and Copy Link": "Aktualizovať a skopírovať odkaz", + "Update Email": "", "Update for the latest features and improvements.": "Aktualizácia pre najnovšie funkcie a vylepšenia.", + "Update Name": "", "Update password": "Aktualizovať heslo", + "Update Picture": "", "Update your status": "", "Updated": "Aktualizované", "Updated at": "Aktualizované dňa", @@ -2232,13 +2411,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Použite '#' vo vstupe promptu na načítanie a zahrnutie vašich vedomostí.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "používateľ", "User": "Používateľ", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Umiestnenie používateľa bolo úspešne získané.", @@ -2248,6 +2432,7 @@ "User Status": "", "User Webhooks": "", "Username": "Používateľské meno", + "Username Claim": "", "users": "", "Users": "Používatelia", "Uses DefaultAzureCredential to authenticate": "", @@ -2261,6 +2446,7 @@ "Valves updated": "Ventily aktualizované", "Valves updated successfully": "Ventily boli úspešne aktualizované.", "variable": "premenná", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Verzia", @@ -2290,11 +2476,14 @@ "Web API": "Webové API", "Web Loader Engine": "", "Web Search": "Vyhľadávanie na webe", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Webový vyhľadávač", "Web Search in Chat": "Webové vyhľadávanie v chate", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Nastavenia WebUI", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Včera", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Vy", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Celý váš príspevok pôjde priamo vývojárovi pluginu; Open WebUI si neberie žiadne percento. Zvolená platforma na financovanie však môže mať vlastné poplatky.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "", diff --git a/src/lib/i18n/locales/sr-RS/translation.json b/src/lib/i18n/locales/sr-RS/translation.json index 0e3c53ac95..209d20add0 100644 --- a/src/lib/i18n/locales/sr-RS/translation.json +++ b/src/lib/i18n/locales/sr-RS/translation.json @@ -17,6 +17,12 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -28,12 +34,17 @@ "{{count}} selected_few": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -41,8 +52,10 @@ "{{user}}'s Chats": "Ћаскања корисника {{user}}", "{{webUIName}} Backend Required": "Захтева се {{webUIName}} позадинац", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -60,6 +73,7 @@ "Access Control": "Контрола приступа", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Доступно свим корисницима", "Account": "Налог", @@ -75,6 +89,7 @@ "Activity": "", "Add": "Додај", "Add a model ID": "Додај ИБ модела", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Додавање кратког описа о томе шта овај модел ради", "Add a tag": "Додај ознаку", "Add a tag...": "", @@ -87,8 +102,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Додај датотеке", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -103,6 +120,7 @@ "Add to favorites": "", "Add User": "Додај корисника", "Add User Group": "Додај корисничку групу", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -115,7 +133,9 @@ "Admin": "Админ", "Admin Contact Email": "", "Admin Panel": "Админ табла", + "Admin Roles": "", "Admin Settings": "Админ део", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Админи имају приступ свим алатима у сваком тренутку, корисницима је потребно доделити алате по моделу у радном простору", "Advanced": "", "Advanced Parameters": "Напредни параметри", @@ -126,16 +146,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Сви модели су успешно обрисани", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Дозволи контроле ћаскања", "Allow Chat Delete": "Дозволи брисање ћаскања", "Allow Chat Edit": "Дозволи измену ћаскања", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -155,9 +180,11 @@ "Allow User Location": "Дозволи корисничку локацију", "Allow Voice Interruption in Call": "Дозволи прекид гласа у позиву", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Већ имате налог?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -176,6 +203,7 @@ "API Base URL": "Основна адреса API-ја", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API кључ", + "API Key / Token": "", "API Key created.": "API кључ направљен.", "API Key Endpoint Restrictions": "", "API keys": "API кључеви", @@ -205,13 +233,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Да ли сигурно желите обрисати ову поруку?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Да ли сигурно желите деархивирати све архиве?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Модели са Арене", "Artifacts": "Артефакти", "Asc": "", "Ask": "", "Ask a question": "Постави питање", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Помоћник", "Async Embedding Processing": "", "At time of event": "", @@ -226,14 +259,20 @@ "Audio": "Звук", "August": "Август", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Идентификација", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Самостално копирање одговора у оставу", - "Auto-playback response": "Самостално пуштање одговора", + "Auto-Create Groups": "", + "Auto-Playback Response": "Самостално пуштање одговора", "Autocomplete Generation": "Стварање самодовршавања", "Autocomplete Generation Input Max Length": "Најдужи улаз стварања самодовршавања", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Automatic1111 Api ниска идентификације", "AUTOMATIC1111 Base URL": "Основна адреса за AUTOMATIC1111", @@ -251,6 +290,7 @@ "Available Skills": "", "Available Tools": "", "available users": "доступни корисници", + "Available variables": "", "available!": "доступно!", "Away": "Одсутан", "Awful": "Грозно", @@ -261,16 +301,17 @@ "Bad Response": "Лош одговор", "Banners": "Барјаке", "Base Model (From)": "Основни модел (од)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "пре", "Being lazy": "Бити лењ", - "Beta": "Бета", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -327,7 +368,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Смер ћаскања", + "Chat Direction": "Смер ћаскања", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -399,6 +440,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Колекција", + "Collection Field": "", "Collections": "", "Color": "Боја", "ComfyUI": "ComfyUI", @@ -408,12 +450,14 @@ "ComfyUI Workflow": "ComfyUI радни ток", "ComfyUI Workflow Nodes": "ComfyUI чворови радног тока", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Наредба", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Допуне", "Compress Images in Channels": "", @@ -436,6 +480,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -448,8 +493,16 @@ "Contact Admin for WebUI Access": "Пишите админима за приступ на WebUI", "Content": "Садржај", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Настави одговор", "Continue with {{provider}}": "Настави са {{provider}}", "Continue with Email": "Настави са е-адресом", @@ -497,6 +550,7 @@ "Create new secret key": "Направи нови тајни кључ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Направљено у", @@ -514,6 +568,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -536,7 +591,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Подразумевани модел", "Default model updated": "Подразумевани модел ажуриран", "Default permissions": "Подразумевана овлашћења", @@ -546,6 +600,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Подразумевана улога корисника", + "Default webhook": "", "Defaults": "", "Delete": "Обриши", "Delete {{name}}": "", @@ -606,6 +661,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Онемогућено", "Disconnect OAuth": "", "Discover a function": "Откријте функцију", @@ -620,10 +677,10 @@ "Discover, download, and explore model presets": "Откријте, преузмите и истражите образце модела", "Discussion channel where access is based on groups and permissions": "", "Display": "Приказ", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Прикажи емоџије у позиву", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Прикажи корисничко уместо Ти у ћаскању", + "Display the Username Instead of You in the Chat": "Прикажи корисничко уместо Ти у ћаскању", "Displays citations in the response": "Прикажи цитате у одговору", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Ускочите у знање", @@ -634,6 +691,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Документ", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -689,12 +747,14 @@ "Edit Default Permissions": "Измени подразумевана овлашћења", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Измени сећање", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Измени корисника", "Edit User Group": "Измени корисничку групу", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -703,6 +763,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Е-пошта", + "Email Claim": "", "Embark on adventures": "Започните пустоловину", "Embedding": "", "Embedding Batch Size": "", @@ -711,6 +772,7 @@ "Embedding Model Engine": "Мотор модела уградње", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -718,22 +780,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "Омогући дељење заједнице", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Омогући нове пријаве", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Омогућено", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Уверите се да ваша CSV датотека укључује 4 колоне у овом редоследу: Име, Е-пошта, Лозинка, Улога.", "Enter {{role}} message here": "Унесите {{role}} поруку овде", - "Enter a detail about yourself for your LLMs to recall": "Унесите детаље за себе да ће LLMs преузимати", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -750,6 +817,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Унесите преклапање делова", "Enter Chunk Size": "Унесите величину дела", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -787,8 +856,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "Унесите кодове језика", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -808,6 +880,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "Унесите резултат", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -817,6 +890,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "Унесите Серпер АПИ кључ", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "Унесите Серпстацк АПИ кључ", "Enter server host": "", @@ -837,6 +911,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Унесите Топ К", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "Унесите адресу (нпр. http://127.0.0.1:7860/)", @@ -877,11 +953,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Процењивања", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -909,12 +989,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -932,6 +1018,7 @@ "Failed to create API Key.": "Неуспешно стварање API кључа.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -939,6 +1026,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -948,6 +1036,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Неуспешно читање садржаја оставе", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -956,9 +1045,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -991,6 +1082,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Датотеке", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1013,6 +1106,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1043,6 +1137,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "Функције", "Functions allow arbitrary code execution.": "", @@ -1075,7 +1170,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Група направљена успешно", "Group deleted successfully": "Група обрисана успешно", "Group Description": "Опис групе", @@ -1087,6 +1185,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Вибрација као одговор", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1117,6 +1216,8 @@ "ID": "ИБ", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1142,6 +1243,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Важно ажурирање", @@ -1199,7 +1301,6 @@ "Keep in Sidebar": "", "Key": "Кључ", "Key is required": "", - "Keyboard shortcuts": "Пречице на тастатури", "Keyboard Shortcuts": "", "Knowledge": "Знање", "Knowledge Access": "Приступ знању", @@ -1212,6 +1313,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1228,7 +1331,6 @@ "Last ran": "", "Last reply": "Последњи одговор", "LDAP": "ЛДАП", - "LDAP server updated": "ЛДАП сервер измењен", "Leaderboard": "Ранг листа", "Learn more": "", "Learn More": "", @@ -1250,6 +1352,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "Светла", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1273,6 +1376,7 @@ "Location access not allowed": "", "Lost": "Пораза", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "ЛНД", "Made by Open WebUI Community": "Израдила OpenWebUI заједница", "Make password visible in the user interface": "", @@ -1289,6 +1393,7 @@ "Manage Pipelines": "Управљање цевоводима", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Март", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1316,6 +1421,7 @@ "Memory cleared successfully": "Сећање успешно очишћено", "Memory deleted successfully": "Сећање успешно обрисано", "Memory updated successfully": "Сећање успешно измењено", + "Merge Accounts by Email": "", "Merge Responses": "Спој одговоре", "Merged Response": "Спојени одговор", "Message": "", @@ -1326,9 +1432,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Поруке које пошаљете након стварања ваше везе неће бити подељене. Корисници са URL-ом ће моћи да виде дељено ћаскање.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1381,6 +1490,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Више", @@ -1398,6 +1508,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1427,6 +1538,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1439,8 +1551,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1468,6 +1582,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Нема резултата", "No results found": "Нема резултата", "No search query generated": "Није генерисан упит за претрагу", @@ -1487,6 +1602,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Нико", + "Not configured": "", "Not factually correct": "Није чињенично тачно", "Not helpful": "Није од помоћи", "Not Registered": "", @@ -1502,20 +1618,25 @@ "Notifications": "Обавештења", "November": "Новембар", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Октобар", "Off": "Искључено", "Okay, Let's Go!": "У реду, хајде да кренемо!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED тамна", "Ollama": "Ollama", "Ollama API": "Оллама АПИ", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "Издање Ollama-е", + "Omit": "", "On": "Укључено", "Once": "", "OneDrive": "", @@ -1586,6 +1707,7 @@ "Password": "Лозинка", "Passwords do not match.": "", "Paste Large Text as File": "Убаци велики текст као датотеку", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF документ (.pdf)", @@ -1594,18 +1716,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "на чекању", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Приступ медијским уређајима одбијен", "Permission denied when accessing microphone": "Приступ микрофону је одбијен", "Permission denied when accessing microphone: {{error}}": "Приступ микрофону је одбијен: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Прилагођавање", + "Picture Claim": "", "Pin": "Закачи", "Pin to Sidebar": "", "Pinned": "Закачено", @@ -1638,13 +1763,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "Позитиван став", @@ -1674,6 +1799,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Повуците \"{{searchValue}}\" са Ollama.com", "Pull a model from Ollama.com": "Повуците модел са Ollama.com", @@ -1691,21 +1818,30 @@ "Read": "Читање", "Read Aloud": "Прочитај наглас", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Јачина размишљања", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Сними глас", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Преусмеравање на OpenWebUI заједницу", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Одбијено када није требало", "Regenerate": "Поново створи", "Regenerate Menu": "", @@ -1740,19 +1876,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Модел поновног рангирања", + "Research Knowledge": "", "Reset": "Поврати", "Reset All Models": "Поврати све моделе", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Ресетуј слику", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1773,6 +1916,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Богат унос текста у ћаскању", "Role": "Улога", + "Roles Claim": "", "RTL": "ДНЛ", "Run": "Покрени", "Run All": "", @@ -1791,10 +1935,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Чување ћаскања директно у складиште вашег прегледача више није подржано. Одвојите тренутак да преузмете и избришете ваша ћаскања кликом на дугме испод. Не брините, можете лако поново увезти ваша ћаскања у бекенд кроз", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Претражи", "Search a model": "Претражи модел", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1804,6 +1950,7 @@ "Search Chats": "Претражи ћаскања", "Search Collection": "Претражи колекцију", "Search Files": "", + "Search filters": "", "Search Filters": "Претражи филтере", "search for archived chats": "", "search for folders": "", @@ -1818,13 +1965,16 @@ "Search Models": "Модели претраге", "Search Notes": "", "Search options": "Опције претраге", + "Search or add pattern": "", "Search Prompts": "Претражи упите", "Search Result Count": "Број резултата претраге", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Алати претраге", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1840,7 +1990,6 @@ "Seed": "Семе", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Избор основног модела", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Изабери мотор", @@ -1878,18 +2027,25 @@ "semantic": "", "Send": "Пошаљи", "Send a Message": "Пошаљи поруку", + "Send events for": "", "Send message": "Пошаљи поруку", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Септембар", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "Серпер АПИ кључ", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "Серпстацк АПИ кључ", "Server connection failed": "", "Server connection verified": "Веза са сервером потврђена", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Подеси као подразумевано", "Set as Production": "", "Set embedding model": "", @@ -1917,15 +2073,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Подели са OpenWebUI заједницом", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Прикажи", - "Show \"What's New\" modal on login": "Прикажи \"Погледај шта је ново\" прозорче при пријави", + "Show \"What's New\" Modal on Login": "Прикажи \"Погледај шта је ново\" прозорче при пријави", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1969,6 +2127,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Извор", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "Грешка у препознавању говора: {{error}}", "Speech-to-Text": "", @@ -2006,6 +2165,7 @@ "STT Settings": "STT подешавања", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2030,8 +2190,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Систем", + "System events only": "", "System Instructions": "Системске инструкције", "System Prompt": "Системски упит", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "Стварање ознака", @@ -2052,6 +2214,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Раздвајач текста", "Text-to-Speech": "", "Text-to-Speech Engine": "Мотор за текст у говор", @@ -2067,7 +2235,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2089,6 +2256,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2129,7 +2297,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "Тост-обавештења за нове исправке", + "Toast Notifications for New Updates": "Тост-обавештења за нове исправке", "Today": "Данас", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2143,6 +2311,8 @@ "Toggle whether current connection is active.": "", "Token": "Жетон", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Преопширно", @@ -2191,14 +2361,19 @@ "Unpin": "Откачи", "Unpin from Sidebar": "", "Unravel secrets": "Разоткриј тајне", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Неозначено", "Untitled": "", "Update": "Ажурирај", "Update and Copy Link": "Ажурирај и копирај везу", + "Update Email": "", "Update for the latest features and improvements.": "Ажурирајте за најновије могућности и побољшања.", + "Update Name": "", "Update password": "Ажурирај лозинку", + "Update Picture": "", "Update your status": "", "Updated": "Ажурирано", "Updated at": "Ажурирано у", @@ -2225,13 +2400,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "корисник", "User": "Корисник", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Корисничка локација успешно добављена.", @@ -2241,6 +2421,7 @@ "User Status": "", "User Webhooks": "", "Username": "Корисничко име", + "Username Claim": "", "users": "", "Users": "Корисници", "Uses DefaultAzureCredential to authenticate": "", @@ -2254,6 +2435,7 @@ "Valves updated": "Вентили ажурирани", "Valves updated successfully": "Вентили успешно ажурирани", "variable": "променљива", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Издање", @@ -2283,11 +2465,14 @@ "Web API": "Веб АПИ", "Web Loader Engine": "", "Web Search": "Веб претрага", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Веб претраживач", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Адреса веб-куке", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Подешавања веб интерфејса", @@ -2330,6 +2515,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Јуче", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Ти", @@ -2359,6 +2545,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Јутјуб", "Youtube Language": "", diff --git a/src/lib/i18n/locales/sv-SE/translation.json b/src/lib/i18n/locales/sv-SE/translation.json index 69c1dbd37a..14a54d5673 100644 --- a/src/lib/i18n/locales/sv-SE/translation.json +++ b/src/lib/i18n/locales/sv-SE/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} filer", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} dolda rader", "{{COUNT}} members": "{{COUNT}} medlemmar", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "{{count}} vald", "{{count}} selected_other": "{{count}} valda", "{{COUNT}} Sources": "{{COUNT}} källor", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} ord", "{{COUNT}}d_time_ago": "{{COUNT}}d sedan", "{{COUNT}}h_time_ago": "{{COUNT}}h sedan", "{{COUNT}}m_time_ago": "{{COUNT}}m sedan", "{{COUNT}}w_time_ago": "{{COUNT}}v sedan", "{{COUNT}}y_time_ago": "{{COUNT}}å sedan", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} kl {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} nedladdning har avbrutits", "{{modelName}} profile image": "{{modelName}} profilbild", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}s Chattar", "{{webUIName}} Backend Required": "{{webUIName}} Backend krävs", "*Prompt node ID(s) are required for image generation": "*Prompt node ID(s) krävs för bildgenerering", + "1 group": "", "1 hour before": "1 timme före", "1 Source": "1 källa", + "1 user": "", "10 minutes before": "10 minuter före", "15 minutes before": "15 minuter före", "1m_time_ago": "1m sedan", @@ -57,6 +67,7 @@ "Access Control": "Åtkomstkontroll", "Access Grants": "Tillgång till bidrag", "Access List": "Åtkomstlista", + "Access prohibited": "", "Access updated": "Åtkomst uppdaterad", "Accessible to all users": "Tillgänglig för alla användare", "Account": "Konto", @@ -72,6 +83,7 @@ "Activity": "Aktivitet", "Add": "Lägg till", "Add a model ID": "Lägg till ett modell-ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Lägg till en kort beskrivning om vad den här modellen gör", "Add a tag": "Lägg till en tagg", "Add a tag...": "Lägg till en tagg...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Lägg till anpassad uppmaning", "Add description": "Lägg till beskrivning", "Add Details": "Lägg till information", + "Add durable context for future chats": "", "Add Files": "Lägg till filer", "Add Image": "Lägg till bild", + "Add Knowledge Connection": "", "Add location": "Lägg till plats", "Add Member": "Lägg till medlem", "Add Members": "Lägg till medlemmar", @@ -100,6 +114,7 @@ "Add to favorites": "Lägg till bland favoriter", "Add User": "Lägg till användare", "Add User Group": "Lägg till användargrupp", + "Add webhook": "", "Add webpage": "Lägg till webbsida", "Add your Open Terminal URL and API key in Settings → Integrations.": "Lägg till din Open Terminal-URL och API-nyckel i Inställningar → Integrationer.", "Additional Config": "Ytterligare inställningar", @@ -112,7 +127,9 @@ "Admin": "Admin", "Admin Contact Email": "E-post för administratörskontakt", "Admin Panel": "Administrationspanel", + "Admin Roles": "", "Admin Settings": "Administratörsinställningar", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratörer har tillgång till alla verktyg hela tiden, medan användare behöver verktyg som tilldelas per modell i arbetsytan.", "Advanced": "Avancerad", "Advanced Parameters": "Avancerade parametrar", @@ -123,16 +140,21 @@ "All": "Alla", "All chats have been unarchived.": "Alla konversationer har avarkiverats.", "All day": "Hela dagen", + "All events": "", "All models are now hidden": "Alla modeller är nu dolda", "All models are now visible": "Alla modeller är nu synliga", "All models deleted successfully": "Alla modeller har raderats framgångsrikt", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Hela tiden", "All Users": "Alla användare", + "All users and system events": "", "Allow Call": "Tillåt samtal", "Allow Chat Controls": "Tillåt chattkontroller", "Allow Chat Delete": "Tillåt radering av chatt", "Allow Chat Edit": "Tillåt redigering av chatt", "Allow Chat Export": "Tillåt export av chatt", + "Allow Chat Import": "", "Allow Chat Params": "Tillåt chattparametrar", "Allow Chat Share": "Tillåt delning av chatt", "Allow Chat System Prompt": "Tillåt systemprompt i chatt", @@ -152,9 +174,11 @@ "Allow User Location": "Tillåt användarplats", "Allow Voice Interruption in Call": "Tillåt röstavbrott under samtal", "Allow Web Upload": "Tillåt webbuppladdning", + "Allowed Domains": "", "Allowed Endpoints": "Tillåtna Endpoints", "Allowed File Extensions": "Tillåtna filändelser", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Tillåtna filändelser för uppladdning. Separera flera filändelser med kommatecken. Lämna tomt för alla filtyper.", + "Allowed Roles": "", "Already have an account?": "Har du redan ett konto?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Alternativ till top_p, och syftar till att säkerställa en balans mellan kvalitet och variation. Parametern p representerar den minsta sannolikheten för att en token ska beaktas, relativt sannolikheten för den mest sannolika token. Till exempel, med p=0.05 och den mest sannolika token som har en sannolikhet på 0.9, filtreras logits med ett värde mindre än 0.045 bort.", "Always": "Alltid", @@ -173,6 +197,7 @@ "API Base URL": "API-bas-URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "API-bas-URL för Datalab Marker-tjänsten. Standardvärde: https://www.datalab.to/api/v1/marker", "API Key": "API-nyckel", + "API Key / Token": "", "API Key created.": "API-nyckel skapad.", "API Key Endpoint Restrictions": "API-nyckel Endpoint-begränsningar", "API keys": "API-nycklar", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Är du säker på att du vill radera det här minnet? Den här åtgärd kan inte ångras.", "Are you sure you want to delete this message?": "Är du säker på att du vill radera det här meddelande?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Är du säker på att du vill ta bort den här versionen? Underordnade versioner länkas om till den här versionens överordnade version.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Är du säker på att du vill ta bort det här?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Är du säker på att du vill avarkivera alla arkiverade chattar?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arenamodeller", "Artifacts": "Artefakter", "Asc": "Asc", "Ask": "Fråga", "Ask a question": "Ställ en fråga", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Assistent", "Async Embedding Processing": "Asynkron inbäddning av bearbetning", "At time of event": "Vid händelsens tidpunkt", @@ -223,14 +253,20 @@ "Audio": "Ljud", "August": "augusti", "Auth": "Autentisering", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentisera", "Authentication": "Autentisering", "Auto": "Auto", "Auto (Random)": "Auto (slumpmässig)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Automatisk kopiering av svar till urklipp", - "Auto-playback response": "Automatisk uppspelning av svar", + "Auto-Create Groups": "", + "Auto-Playback Response": "Automatisk uppspelning av svar", "Autocomplete Generation": "Automatisk komplettering av generering", "Autocomplete Generation Input Max Length": "Maxlängd för inmatning av automatisk komplettering", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 bas-URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Tillgängliga verktyg", "available users": "tillgängliga användare", + "Available variables": "", "available!": "tillgänglig!", "Away": "Borta", "Awful": "Hemsk", @@ -258,16 +295,17 @@ "Bad Response": "Dåligt svar", "Banners": "Banners", "Base Model (From)": "Basmodell (från)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Base Model List Cache påskyndar åtkomsten genom att hämta basmodeller endast vid start eller när inställningarna sparas snabbare, men visar kanske inte de senaste basmodelländringarna.", "Bearer": "Bearer", "before": "före", "Being lazy": "Är lat", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Search V7 Endpoint", "Bing Search V7 Subscription Key": "Bing Search V7 Prenumerationsnyckel", "Bio": "Personlig information om dig", "Birth Date": "Födelsedatum", + "Blocked Groups": "", "BM25 Weight": "BM25 Vikt", "Bocha Search API Key": "Bocha Search API-nyckel", "Bold": "Fet", @@ -324,7 +362,7 @@ "Chat Completions": "Chattavslutningar", "Chat Conversation": "Chattkonversation", "Chat deleted.": "Chatt borttagen.", - "Chat direction": "Chattriktning", + "Chat Direction": "Chattriktning", "Chat exported successfully": "Chatten exporterades framgångsrikt", "Chat History": "Chatthistorik", "Chat ID": "Chatt-ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "Samarbetskanal där människor ansluter sig som medlemmar", "Collapse": "Fäll ihop", "Collection": "Samling", + "Collection Field": "", "Collections": "Samlingar", "Color": "Färg", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI Arbetsflöde", "ComfyUI Workflow Nodes": "ComfyUI Arbetsflödesnoder", "Comma separated Node Ids (e.g. 1 or 1,2)": "Kommaseparerade nod-ID:n (t.ex. 1 eller 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "kommando", "Command": "Kommando", "Comment": "Kommentar", "Commit Message": "Engagera meddelande", "Community Reviews": "Gemenskapens recensioner", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Slutföranden", "Compress Images in Channels": "Komprimera bilder i kanaler", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Anslut till Open Terminal-instanser. Alla användare kommer att ha tillgång till filbläddring och terminalverktyg via de här servrar.", "Connect to your own OpenAI compatible API endpoints.": "Anslut till dina egna OpenAI-kompatibla API-endpoints.", "Connect to your own OpenAPI compatible external tool servers.": "Anslut till dina egna OpenAPI-kompatibla externa verktygsservrar.", + "Connected": "", "Connected ({{type}})": "Ansluten ({{type}})", "Connection failed": "Anslutning misslyckades", "Connection lost. Reconnecting...": "Anslutningen bröts. Ansluter igen...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "Kontakta administratören för att få åtkomst till WebUI", "Content": "Innehåll", "Content Extraction Engine": "Motor för innehållsextrahering", + "Content Field": "", "Content lengths (character counts only)": "Innehållets längd (endast antal tecken)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Kontexttoken", + "Continue": "", "Continue Response": "Fortsätt svar", "Continue with {{provider}}": "Fortsätt med {{provider}}", "Continue with Email": "Fortsätt med e-post", @@ -493,6 +543,7 @@ "Create new secret key": "Skapa ny hemlig nyckel", "Create note": "Skapa anteckning", "Create Note": "Skapa anteckning", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Skapa schemalagda promptar som körs automatiskt återkommande.", "Create your first note by clicking on the plus button below.": "Skapa din första anteckning genom att klicka på plusknappen nedan.", "Created at": "Skapad", @@ -510,6 +561,7 @@ "Custom Gender": "Anpassat kön", "Custom Parameter Name": "Anpassat parameternamn", "Custom Parameter Value": "Anpassat parametervärde", + "Custom range": "", "Daily": "Dagligen", "Daily Messages": "Dagliga meddelanden", "Danger Zone": "Fara", @@ -532,7 +584,6 @@ "Default Features": "Föraktiverade funktioner", "Default Filters": "Standardfilter", "Default Group": "Standardgrupp", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Standardläget fungerar med ett bredare utbud av modeller genom att anropa verktyg en gång före körning. Inbyggt läge utnyttjar modellens inbyggda verktygsanropsfunktioner, men kräver att modellen har stöd för den här funktionen.", "Default Model": "Standardmodell", "Default model updated": "Standardmodell uppdaterad", "Default permissions": "Standardbehörigheter", @@ -542,6 +593,7 @@ "Default to ALL": "Standard till ALLA", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Standard till segmenterad hämtning för fokuserad och relevant innehållsextrahering, det här rekommenderas för de flesta fall.", "Default User Role": "Standardanvändarroll", + "Default webhook": "", "Defaults": "Standardinställningar", "Delete": "Radera", "Delete {{name}}": "Ta bort {{name}}", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Inaktivera kodtolkare", "Disable Image Extraction": "Inaktivera bildextrahering", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Inaktivera bildextrahering från PDF-filen. Om Använd LLM är aktiverat kommer bilder att automatiskt bildtextas. Standardvärdet är False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Inaktiverad", "Disconnect OAuth": "Koppla från OAuth", "Discover a function": "Upptäck en funktion", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Upptäck, ladda ner och utforska modellförinställningar", "Discussion channel where access is based on groups and permissions": "Diskussionskanal där åtkomst baseras på grupper och behörigheter", "Display": "Visa", - "Display chat title in tab": "Visa chattrubrik i flik", + "Display Chat Title in Tab": "Visa chattrubrik i flik", "Display Emoji in Call": "Visa Emoji under samtal", "Display Multi-model Responses in Tabs": "Visa simultana modellsvar i flikar", - "Display the username instead of You in the Chat": "Visa ditt användarnamn istället för \"Du\" i chatten", + "Display the Username Instead of You in the Chat": "Visa ditt användarnamn istället för \"Du\" i chatten", "Displays citations in the response": "Visar citeringar i svaret", "Displays status updates (e.g., web search progress) in the response": "Visar statusuppdateringar (t.ex. webbsökningens förlopp) i svaret", "Dive into knowledge": "Dyk in i kunskap", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling Parametrar", "Docling Server URL required.": "Docling Server URL krävs.", "Document": "Dokument", + "Document ID Field": "", "Document Intelligence": "Dokumentinformation", "Document Intelligence endpoint required.": "Slutpunkt för Document Intelligence krävs.", "Document Intelligence Model": "Modell för dokumentintelligens", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Redigera standardbehörigheter", "Edit Folder": "Redigera mapp", "Edit Image": "Redigera bild", + "Edit Knowledge Connection": "", "Edit Last Message": "Redigera Senaste meddelande", "Edit Memory": "Redigera minne", "Edit Prompt": "Redigeringsprompt", "Edit Terminal Connection": "Redigera terminalanslutning", "Edit User": "Redigera användare", "Edit User Group": "Redigera användargrupp", + "Edit webhook": "", "Edit workflow.json content": "Redigera innehållet i workflow.json", "edited": "redigerad", "Edited": "Redigerad", @@ -699,6 +756,7 @@ "Eject model": "Skjut ut modellen", "ElevenLabs": "ElevenLabs", "Email": "E-post", + "Email Claim": "", "Embark on adventures": "Ge dig ut på äventyr", "Embedding": "Inbäddning", "Embedding Batch Size": "Batchstorlek för inbäddning", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Motor för inbäddningsmodell", "Emoji": "", "Emojis": "Emojier", + "Empty": "", "Empty message": "Tomt meddelande", "Enable All": "Aktivera alla", "Enable API Keys": "Aktivera API-nycklar", @@ -714,22 +773,27 @@ "Enable Code Execution": "Aktivera kodkörning", "Enable Code Interpreter": "Aktivera kodtolk", "Enable Community Sharing": "Aktivera community-delning", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Aktivera minneslåsning (mlock) för att förhindra att modelldata swappas ut ur RAM. Det här alternativ låser modellens arbetsuppsättning av sidor i RAM, vilket säkerställer att de inte swappas ut till disk. Det här kan bidra till att upprätthålla prestanda genom att undvika sidfel och säkerställa snabb dataåtkomst.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Aktivera minnesmappning (mmap) för att ladda modelldata. Det här alternativ tillåter systemet att använda disklagring som en förlängning av RAM genom att behandla diskfiler som om de vore i RAM. Det här kan förbättra modellens prestanda genom att möjliggöra snabbare dataåtkomst. Det kanske dock inte fungerar korrekt med alla system och kan förbruka en betydande mängd diskutrymme.", "Enable Message Queue": "Aktivera Message Queue", "Enable Message Rating": "Aktivera meddelandebetyg", "Enable Mirostat sampling for controlling perplexity.": "Aktivera Mirostat-sampling för att kontrollera perplexitet.", "Enable New Sign Ups": "Aktivera nya registreringar", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Aktivera, inaktivera eller anpassa de taggar för resonemang som används av modellen. \"Enabled\" använder standardtaggar, \"Disabled\" stänger av resonemangstaggar och \"Custom\" låter dig ange dina egna start- och sluttaggar.", "Enabled": "Aktiverad", "End Tag": "Avsluta tagg", + "Endpoint": "", "Endpoint URL": "Endpoint URL", "Enforce Temporary Chat": "Tvinga fram tillfällig chatt", "Enhance": "Förbättra", "Enrich Hybrid Search Text": "Berika hybrid söktext", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Se till att din CSV-fil innehåller fyra kolumner i den här ordningen: Name, Email, Password, Role.", "Enter {{role}} message here": "Skriv {{role}} meddelande här", - "Enter a detail about yourself for your LLMs to recall": "Skriv en detalj om dig själv för att dina LLMs ska komma ihåg", "Enter a title for the pending user info overlay. Leave empty for default.": "Ange en titel för den väntande användarinformationen. Lämna tomt för standard.", "Enter a watermark for the response. Leave empty for none.": "Ange en vattenstämpel för svaret. Lämna tomt för ingen.", "Enter additional headers in JSON format": "Ange ytterligare rubriker i JSON-format", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Enter Chunk Min Storlek Mål", "Enter Chunk Overlap": "Ange chunköverlappning", "Enter Chunk Size": "Ange chunkstorlek", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Ange komma-separerade \"token:bias_value\"-par (exempel: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Ange innehåll för den väntande användarinformationen. Lämna tomt för standard.", "Enter coordinates (e.g. 51.505, -0.09)": "Ange koordinater (t.ex. 51,505, -0,09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Ange Jupyter URL", "Enter Kagi Search API Key": "Ange Kagi Search API-nyckel", "Enter Key Behavior": "Ange nyckelbeteende", + "Enter language": "", "Enter language codes": "Skriv språkkoder", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "Ange MinerU API-nyckel", "Enter Mistral API Base URL": "Ange URL för Mistral API-bas", "Enter Mistral API Key": "Ange Mistral API-nyckel", @@ -804,6 +873,7 @@ "Enter prompt here.": "Ange prompt här.", "Enter proxy URL (e.g. https://user:password@host:port)": "Ange proxy-URL (t.ex. https://user:password@host:port)", "Enter reasoning effort": "Ange resonemangsinsats", + "Enter Redirect URI": "", "Enter Score": "Ange betyg", "Enter SearchApi API Key": "Ange SearchApi API-nyckel", "Enter SearchApi Engine": "Ange SearchApi Engine", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "Ange SerpApi API-nyckel", "Enter SerpApi Engine": "Ange SerpApi Engine", "Enter Serper API Key": "Ange Serper API-nyckel", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Ange Serply API-nyckel", "Enter Serpstack API Key": "Ange Serpstack API-nyckel", "Enter server host": "Ange servervärd", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Ange Tika Server URL", "Enter timeout in seconds": "Ange timeout i sekunder", "Enter to Send": "Enter för att skicka", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Ange Top K", "Enter Top K Reranker": "Ange Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Ange URL (t.ex. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Felmeddelande: En modell med ID '{{modelId}}' finns redan. välj ett annat ID för att fortsätta.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Fel: Modell-ID kan inte vara tomt: Modell-ID kan inte vara tomt. Ange ett giltigt ID för att fortsätta.", "Evaluations": "Utvärderingar", + "Event": "", "Event created": "Händelse skapad", "Event deleted": "Händelse borttagen", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Händelsetitel", "Event updated": "Händelse uppdaterad", + "Events": "", "Exa API Key": "Exa API-nyckel", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exempel: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exempel: ALLA", "Example: mail": "Exempel: mail", @@ -905,12 +982,18 @@ "Export Config": "Exportera konfiguration", "Export Models": "Exportmodeller", "Export Prompts": "Exportera promptar", + "Export Skills": "", "Export to CSV": "Exportera till CSV", "Export Tools": "Verktyg för export", "Export Users": "Exportera användare", "External": "Extern", + "External connection not found.": "", "External Document Loader URL required.": "Extern dokumentinläsare URL krävs.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Extern uppgiftsmodell", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Extern webbinläsare API-nyckel", "External Web Loader URL": "Extern webbinläsare URL", "External Web Search API Key": "Extern webbsökning API-nyckel", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "Misslyckades med att skapa API-nyckel.", "Failed to delete calendar": "Det gick inte att ta bort kalendern", "Failed to delete note": "Misslyckades med att ta bort anteckning", + "Failed to delete webhook": "", "Failed to disconnect": "Det gick inte att koppla från", "Failed to download image": "Misslyckades med att ladda ner bilden", "Failed to extract content from the file: {{error}}": "Misslyckades med att extrahera innehåll från filen: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Misslyckades med att hämta modeller", "Failed to generate title": "Misslyckades med att generera titel", "Failed to import models": "Misslyckades med att importera modeller", + "Failed to load chat": "", "Failed to load chat preview": "Misslyckades med att ladda förhandsgranskning av chatt", "Failed to load DOCX file. Please try downloading it instead.": "Det gick inte att ladda DOCX-filen. Försök ladda ner den istället.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-filen kunde inte laddas. Försök ladda ner den istället.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Misslyckades med att flytta chatten", "Failed to process URL: {{url}}": "Misslyckades med att bearbeta URL: {{url}}", "Failed to read clipboard contents": "Misslyckades med att läsa urklippsinnehåll", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Misslyckades med att ta bort medlemmen", "Failed to render diagram": "Misslyckades med att rendera diagram", "Failed to render visualization": "Misslyckades med att rendera visualisering", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Misslyckades med att spara modellkonfiguration", "Failed to save policy: {{error}}": "Misslyckades med att spara policy: {{error}}", "Failed to save terminal servers": "Misslyckades med att spara terminalservrar", + "Failed to save webhook": "", "Failed to unshare chat.": "Misslyckades med att ta bort chattdelning.", "Failed to update settings": "Misslyckades med att uppdatera inställningarna", "Failed to update status": "Misslyckades med att uppdatera status", + "Failed to update webhook": "", "Failed to upload file.": "Misslyckades med att ladda upp fil.", "Features": "Funktioner", "Features Permissions": "Funktionsbehörigheter", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Filen har laddats upp", "Filename": "Filnamn", "Files": "Filer", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filter", "Filter is now globally disabled": "Filter är nu globalt inaktiverat", "Filter is now globally enabled": "Filter är nu globalt aktiverat", @@ -1009,6 +1099,7 @@ "Folder options": "Alternativ för mapp", "Folder updated successfully": "Mappen har uppdaterats", "Folders": "Mappar", + "Folders Sharing": "", "Follow up": "Uppföljningsfrågor", "Follow Up Generation": "Generering av uppföljningsfrågor", "Follow Up Generation Prompt": "Prompt för generering av uppföljningsfrågor", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funktionen är nu globalt aktiverad", "Function Name": "Funktionsnamn", "Function Name Filter List": "Funktionsnamn Filterlista", + "Function starter": "", "Function updated successfully": "Funktionen har uppdaterats", "Functions": "Funktioner", "Functions allow arbitrary code execution.": "Funktioner tillåter godtycklig kodkörning.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Rutnät", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Grupp Kanal", + "Group Claim": "", "Group created successfully": "Gruppen har skapats", "Group deleted successfully": "Gruppen har tagits bort", "Group Description": "Gruppbeskrivning", @@ -1083,6 +1178,7 @@ "H2": "Rubrik 2", "H3": "Rubrik 3", "Haptic Feedback": "Haptisk återkoppling", + "Header variables": "", "Headers": "Rubriker", "Headers must be a valid JSON object": "Headers måste vara ett giltigt JSON-objekt", "Height": "Höjd", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID kan inte innehålla \":\" eller \"|\" tecken", "ID copied to clipboard": "ID kopierat till urklipp", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Timeout för inaktivitet", "iframe Sandbox Allow Forms": "iframe Sandbox Tillåt formulär", "iframe Sandbox Allow Same Origin": "iframe Sandbox Tillåt samma ursprung", @@ -1138,6 +1236,7 @@ "Import From Link": "Importera från länk", "Import Models": "Importmodeller", "Import Prompts": "Prompter för import", + "Import Skills": "", "Import successful": "Importen lyckades", "Import Tools": "Verktyg för import", "Important Update": "Viktig uppdatering", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Behåll i sidofältet", "Key": "Nyckel", "Key is required": "Nyckel krävs", - "Keyboard shortcuts": "Tangentbordsgenvägar", "Keyboard Shortcuts": "Kortkommandon för tangentbord", "Knowledge": "Kunskapsbaser", "Knowledge Access": "Kunskapsåtkomst", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Kunskapsbasens namn", "Knowledge Public Sharing": "Offentlig delning av kunskapsbaser", "Knowledge Sharing": "Delning av kunskap", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Kunskapen har uppdaterats", "Kokoro.js (Browser)": "Kokoro.js (webbläsare)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Senast körd", "Last reply": "Senaste svar", "LDAP": "LDAP", - "LDAP server updated": "LDAP-servern har uppdaterats", "Leaderboard": "Topplista", "Learn more": "Läs mer om det här", "Learn More": "Lär dig mer", @@ -1246,6 +1345,7 @@ "Legacy": "Arv", "lexical": "lexikalisk", "License": "Licens", + "Lifecycle JSON": "", "Lift List": "Lyftlista", "Light": "Ljus", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Begränsa antalet samtidiga sökfrågor. 0 = obegränsad (standard). Ställ in på 1 för sekventiell körning (rekommenderas för API:er med strikta hastighetsgränser som Brave free tier).", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Åtkomst till platsen är inte tillåten", "Lost": "Förlorad", "Low": "Låg", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "Vänster till höger", "Made by Open WebUI Community": "Skapad av OpenWebUI Community", "Make password visible in the user interface": "Gör lösenordet synligt i användargränssnittet", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Hantera rörledningar", "Manage Tool Servers": "Hantera verktygsservrar", "Manage your account information.": "Hantera din kontoinformation.", + "Mapped Source": "", "March": "mars", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown textdelare för rubriker", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Minnet har rensats", "Memory deleted successfully": "Minnet har tagits bort", "Memory updated successfully": "Minnet har uppdaterats", + "Merge Accounts by Email": "", "Merge Responses": "Sammanslå svar (med AI)", "Merged Response": "Sammansslaget svar", "Message": "Meddelande", @@ -1322,9 +1425,12 @@ "messages": "meddelanden", "Messages": "Meddelanden", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Meddelanden du skickar efter att du har skapat din länk kommer inte att delas. Användare med länken kommer att kunna se allt innehåll i den delade chatten.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (personligt)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (arbete/skola)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "min", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API-nyckel krävs för Cloud API-läge.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Delning av modeller", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Sök API-nyckel", + "Monday – Friday": "", "Month": "Månad", "Monthly": "Månadsvis", "More": "Mer", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Namnge din kunskapsbas", "Name, prompt, and model are required": "Namn, prompt och modell krävs", "Native": "Inbyggd", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Aldrig", "New": "Ny", "New Automation": "Ny automatisering", @@ -1423,6 +1531,7 @@ "Next run": "Nästa körning", "No access grants. Private to you.": "Ingen tillgång beviljas. Privat för dig.", "No activity data": "Ingen aktivitetsdata", + "No additional headers are sent unless configured.": "", "No authentication": "Ingen autentisering", "No automations found": "Inga automatiseringar hittades", "No chats found": "Inga konversationer hittades", @@ -1435,8 +1544,10 @@ "No data": "Inga uppgifter", "No data found": "Inga uppgifter hittades", "No distance available": "Inget avstånd tillgängligt", + "No event webhooks configured.": "", "No execution logs available yet": "Inga körningsloggar finns ännu", "No expiration can pose security risks.": "Ingen utgångstid kan orsaka säkerhetsrisker.", + "No external knowledge sources configured.": "", "No feedback found": "Ingen feedback hittades", "No file selected": "Ingen fil vald", "No files found": "Inga filer hittades", @@ -1464,6 +1575,7 @@ "No output items": "Inga utdataobjekt", "No pinned messages": "Inga fastklistrade meddelanden", "No prompts found": "Inga promptar hittades", + "No Repeat": "", "No results": "Inga resultat hittades", "No results found": "Inga resultat hittades", "No search query generated": "Ingen sökfråga genererad", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Inga webhooks ännu", "Node Ids": "Nod-ID:n", "None": "Ingen", + "Not configured": "", "Not factually correct": "Inte faktiskt korrekt", "Not helpful": "Inte hjälpsam", "Not Registered": "Inte registrerad", @@ -1498,20 +1611,25 @@ "Notifications": "Notifikationer", "November": "november", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (statisk)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "OAuth-server-URL", "OAuth session disconnected": "OAuth-session frånkopplad", "October": "oktober", "Off": "Av", "Okay, Let's Go!": "Okej, nu kör vi!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Mörk (OLED)", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API-inställningar uppdaterade", "Ollama Cloud API Key": "Ollama Cloud API-nyckel", "Ollama Version": "Ollama-version", + "Omit": "", "On": "På", "Once": "En gång", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Lösenord", "Passwords do not match.": "Lösenorden matchar inte.", "Paste Large Text as File": "Klistra in stor text som fil", + "Path": "", "Path copied": "Sökväg kopierad", "Paused": "Pausad", "PDF document (.pdf)": "PDF-dokument (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "väntande", "Pending": "Väntande", + "Pending Accounts": "", "Pending User Overlay Content": "Väntande användaröverlagringsinnehåll", "Pending User Overlay Title": "Väntande användaröverlagringstitel", "Permission denied when accessing media devices": "Nekad behörighet vid åtkomst till mediaenheter", "Permission denied when accessing microphone": "Nekad behörighet vid åtkomst till mikrofon", "Permission denied when accessing microphone: {{error}}": "Tillstånd nekades vid åtkomst till mikrofon: {{error}}", "Permissions": "Behörigheter", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API-nyckel", "Perplexity Model": "Perplexity-modell", "Perplexity Search API URL": "URL för API för Perplexity-sökning", "Perplexity Search Context Usage": "Perplexity Sök Kontextanvändning", "Persistent": "Ihållande", "Personalization": "Personalisering", + "Picture Claim": "", "Pin": "Fäst", "Pin to Sidebar": "Fäst i sidofältet", "Pinned": "Fäst", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Fyll i alla fält.", "Please register the OAuth client": "Registrera OAuth-klienten", "Please save the connection to persist the OAuth client information and do not change the ID": "Spara anslutningen för att behålla informationen om OAuth-klienten och ändra inte ID:t", - "Please select a model first.": "Välj en modell först.", "Please select a model.": "Välj en modell.", "Please select a reason": "Välj en anledning", "Please select a valid JSON file": "Välj en giltig JSON-fil", "Please select at least one user for Direct Message channel.": "Välj minst en användare för kanalen Direct Message.", "Please wait until all files are uploaded.": "Vänta tills alla filer har laddats upp.", "Policy ID": "Policy-ID", + "Policy ID is required": "", "Port": "Port", "Ports": "Portar", "Positive attitude": "Positivt inställning", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Offentlig delning av prompter", "Prompts Sharing": "Frågeställningar Delning", "Provider": "Leverantör", + "Provider Name": "", + "Provider URL": "", "Public": "Offentlig", "Pull \"{{searchValue}}\" from Ollama.com": "Ladda ner \"{{searchValue}}\" från Ollama.com", "Pull a model from Ollama.com": "Ladda ner en modell från Ollama.com", @@ -1687,21 +1811,29 @@ "Read": "Läs", "Read Aloud": "Läs igenom", "Read more →": "Läs mer →", + "Read only": "", "Read Only": "Endast läsning", "Read-Only Access": "Skrivskyddad åtkomst", "Reason": "Anledning", "Reasoning Effort": "Resonemangsinsats", "Reasoning Tags": "Resonemangs-taggar (tags)", "Reasoning text...": "Resonemangstext...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Senast använda", "Reconnected": "Återansluten", "Record": "Spela in", "Record voice": "Spela in röst", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Omdirigerar dig till OpenWebUI Community", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Minskar sannolikheten för att generera nonsens. Ett högre värde (t.ex. 100) ger mer varierande svar, medan ett lägre värde (t.ex. 10) är mer konservativt.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Referera till dig själv som \"Användare\" (t.ex. \"Användaren lär sig spanska\")", "Reference Chats": "Bifoga annan chatt", "Refresh": "Uppdatera", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Avvisades när det inte borde ha gjort det", "Regenerate": "Regenerera", "Regenerate Menu": "Regenerera meny", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "Rendera Markdown i förhandsgranskningar", "Render Markdown in User Messages": "Rendera Markdown i användarmeddelanden", "Reorder Models": "Omordna modeller", + "Repeat": "", "Repeats": "Upprepas", "Reply": "Svara", "Reply in Thread": "Svara i tråd", "Reply to thread...": "Svara i tråd...", "Replying to {{NAME}}": "Svarar {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "obligatoriskt", "Reranking Batch Size": "Batchstorlek för omrankning", "Reranking Engine": "Omrankningsmotor", "Reranking Model": "Reranking modell", + "Research Knowledge": "", "Reset": "Återställ", "Reset All Models": "Återställ alla modeller", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Återställ bild", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Återställ uppladdningskatalog", "Reset Vector Storage/Knowledge": "Återställ vektorlagring/kunskapsbaser", "Reset view": "Återställ vy", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "Hämtade från en källa", "Rich Text Input for Chat": "Rich Text-inmatning för chatt", "Role": "Roll", + "Roles Claim": "", "RTL": "RTL", "Run": "Kör", "Run All": "Kör alla", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Att spara chatloggar direkt till din webbläsares lagring stöds inte längre. Ta en stund och ladda ner och radera dina chattloggar genom att klicka på knappen nedan. Oroa dig inte, du kan enkelt importera dina chattloggar till backend genom", "Schedule": "Schema", "Scheduled time must be in the future": "Schemalagd tid måste ligga i framtiden", + "Scopes": "", "Scroll On Branch Change": "Scrolla vid grenbyte", "Scroll to Top": "Rulla högst upp", "Search": "Sök", "Search a model": "Sök efter en modell", + "Search actions": "", "Search all emojis": "Sök alla emojis", "Search and manage user memories": "Sök och hantera användarminnen", "Search and view user chat history": "Sök och visa chatthistorik för användare", @@ -1798,6 +1940,7 @@ "Search Chats": "Sök i chattar", "Search Collection": "Sök samling", "Search Files": "Sök filer", + "Search filters": "", "Search Filters": "Sökfilter", "search for archived chats": "sök efter arkiverade konversationer", "search for folders": "sök efter mappar", @@ -1812,13 +1955,16 @@ "Search Models": "Sök modeller", "Search Notes": "Sök anteckningar", "Search options": "Sökalternativ", + "Search or add pattern": "", "Search Prompts": "Sök instruktioner", "Search Result Count": "Antal sökresultat", + "Search skills": "", "Search Skills": "Sökfärdigheter", - "Search skills...": "", "Search the internet": "Sök på internet", "Search the web and fetch URLs": "Sök på webben och hämta webbadresser", + "Search tools": "", "Search Tools": "Sökverktyg", + "Search users or groups": "", "Search, view, and manage user notes": "Sök, visa och hantera användarnotiser", "SearchApi API Key": "SearchApi API-nyckel", "SearchApi Engine": "SearchApi-motor", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Välj", "Select {{modelName}} model": "Välj modell {{modelName}}", - "Select a base model": "Välj en basmodell", "Select a base model (e.g. llama3, gpt-4o)": "Välj en basmodell", "Select a conversation to preview": "Välj en konversation för förhandsgranskning", "Select a engine": "Välj en motor", @@ -1872,18 +2017,25 @@ "semantic": "semantisk", "Send": "Skicka", "Send a Message": "Skicka ett meddelande", + "Send events for": "", "Send message": "Skicka meddelande", "Send now": "Skicka nu", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Skickar `stream_options: { include_usage: true }` i begäran.\nLeverantörer som stöds returnerar information om tokenanvändning i svaret när det är inställt.", "September": "september", "SerpApi API Key": "SerpApi API-nyckel", "SerpApi Engine": "SerpApi-motor", "Serper API Key": "Serper API-nyckel", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API-nyckel", "Serpstack API Key": "Serpstack API-nyckel", "Server connection failed": "Serveranslutningen misslyckades", "Server connection verified": "Serveranslutning verifierad", + "Service Account": "", "Session": "Session", + "Session expired. Please sign in again.": "", "Set as default": "Ange som standard", "Set as Production": "Ställ in som produktion", "Set embedding model": "Ställ in embedding-modell", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Dela länk kopierad till urklipp.", "Share to Open WebUI Community": "Dela till OpenWebUI Community", "Share your background and interests": "Dela din bakgrund och intressen", + "Shared": "", "Shared Chats": "Delade chattar", "Shared with you": "Delat med dig", "Sharing Permissions": "Delningsbehörigheter", "Show": "Visa", - "Show \"What's New\" modal on login": "Visa \"Vad är nytt\"-modalen vid inloggning", + "Show \"What's New\" Modal on Login": "Visa \"Vad är nytt\"-modalen vid inloggning", "Show Admin Details in Account Pending Overlay": "Visa administratörsinformation till väntande konton", "Show All": "Visa alla", "Show all ({{COUNT}} characters)": "Visa alla ({{COUNT}} tecken)", "Show Files": "Visa filer", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Visa verktygsfält för textformatering", "Show image preview": "Visa förhandsvisning av bild", "Show Model": "Visa modell", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Sök API sID", "Sougou Search API SK": "Sougou Sök API SK", "Source": "Källa", + "Specific users or groups": "", "Speech Playback Speed": "Uppspelningshastighet för tal", "Speech recognition error: {{error}}": "Fel vid taligenkänning: {{error}}", "Speech-to-Text": "Tal-till-text", @@ -1999,6 +2154,7 @@ "STT Settings": "Tal-till-text-inställningar", "Stylized PDF Export": "Stiliserad PDF-export", "Su_day_of_week": "Sö", + "Sub Claim": "", "Submit question": "Skicka in fråga", "Submit suggestion": "Skicka in förslag", "Subtitle": "Undertitel", @@ -2023,8 +2179,10 @@ "Syncing...": "Synkroniserar...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Synkroniserar endast chattar med uppdateringar efter din senaste tidsstämpel för synkronisering. Avaktivera för att återsynkronisera alla chattar.", "System": "System", + "System events only": "", "System Instructions": "Systeminstruktioner", "System Prompt": "Systemprompt", + "Table": "", "Tag": "Tagg", "Tags": "Taggar", "Tags Generation": "Tagggenerering", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Tillfällig chatt som standard", "Terminal": "Terminal", "Terminal servers saved": "Terminalservrar sparade", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Textdelare", "Text-to-Speech": "Text-till-tal", "Text-to-Speech Engine": "Text-till-tal-motor", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Språket för ljudinmatningen. Att ange ingångsspråket i ISO-639-1-format (t.ex. en) förbättrar noggrannheten och latensen. Lämna tomt för att automatiskt identifiera språket.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP-attributet som mappar till e-postmeddelandet som användarna använder för att logga in.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP-attributet som mappar till användarnamnet som användarna använder för att logga in.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Topplistan är för närvarande i beta, och vi kan justera betygsberäkningarna när vi förfinar algoritmen.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Den maximala filstorleken i MB. Om filstorleken överskrider den här gräns kommer filen inte att laddas upp.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Det maximala antalet filer som kan användas samtidigt i chatten. Om antalet filer överskrider den här gräns kommer filerna inte att laddas upp.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Utdataformatet för texten. Kan vara 'json', 'markdown' eller 'html'. Standardvärdet är 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Den här mapp är tom", "This is a default user permission and will remain enabled.": "Det här är en standardanvändarbehörighet och kommer att förbli aktiv.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Det här är en experimentell funktion som kanske inte fungerar som förväntat och som kan komma att ändras när som helst.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Den här modellen är inte tillgänglig för allmänheten. Välj en annan modell.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Det här alternativet styr hur länge modellen ska vara inläst i minnet efter begäran (standard: 5m)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Det här alternativet styr hur många tokens som bevaras när kontexten uppdateras. Om det till exempel är inställt på 2 behålls de två sista tokens i samtalskontexten. Att bevara kontexten kan bidra till att upprätthålla kontinuiteten i ett samtal, men det kan minska förmågan att svara på nya ämnen.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "För att lära dig mer om tillgängliga endpoints, besök vår dokumentation", "To select skills here, add them to the \"Skills\" workspace first.": "Om du vill välja färdigheter här måste du först lägga till dem i arbetsytan \"Skills\".", "To select toolkits here, add them to the \"Tools\" workspace first.": "Om du vill välja verktygslådor här måste du först lägga till dem i arbetsytan \"Verktyg\".", - "Toast notifications for new updates": "Toast-aviseringar för nya uppdateringar", + "Toast Notifications for New Updates": "Toast-aviseringar för nya uppdateringar", "Today": "Idag", "Today at": "Idag kl.", "Today at {{LOCALIZED_TIME}}": "Idag kl {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Växla om aktuell anslutning är aktiv.", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Antalet token är uppskattningar och kanske inte återspeglar faktisk API-användning", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "token", "Tokens": "Token", "Too verbose": "För utförlig", @@ -2184,14 +2350,19 @@ "Unpin": "Ta bort fästning", "Unpin from Sidebar": "Lossa från sidofältet", "Unravel secrets": "Avslöja hemligheter", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Chatt utan delning", "Unsupported file type.": "Filtypen stöds inte.", "Untagged": "Otaggad", "Untitled": "Namnlös", "Update": "Uppdatera", "Update and Copy Link": "Uppdatera och kopiera länk", + "Update Email": "", "Update for the latest features and improvements.": "Uppdatera för att få de senaste funktionerna och förbättringarna.", + "Update Name": "", "Update password": "Uppdatera lösenord", + "Update Picture": "", "Update your status": "Uppdatera din status", "Updated": "Uppdaterad", "Updated at": "Uppdaterad vid", @@ -2218,13 +2389,18 @@ "Use": "Användning", "Use '#' in the prompt input to load and include your knowledge.": "Använd '#' i prompten för att läsa in och inkludera från kunskapsbaser", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Använd slutpunkten /v1/chat/completions istället för /v1/audio/transcriptions för potentiellt bättre noggrannhet.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Använd API för chattavslut", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Använd grupper för att organisera dina användare och tilldela behörigheter.", "Use LLM": "Använd LLM", "Use no proxy to fetch page contents.": "Använd ingen proxy för att hämta sidinnehåll.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Använd proxy som anges av miljövariablerna http_proxy och https_proxy för att hämta sidinnehåll.", + "Use Web Search?": "", "user": "användare", "User": "Användare", + "User Access": "", "User Activity": "Användaraktivitet", "User Groups": "Användargrupper", "User location successfully retrieved.": "Användarens plats har hämtats", @@ -2234,6 +2410,7 @@ "User Status": "Användarstatus", "User Webhooks": "Användar-webhooks", "Username": "Användarnamn", + "Username Claim": "", "users": "användare", "Users": "Användare", "Uses DefaultAzureCredential to authenticate": "Använder DefaultAzureCredential för att autentisera", @@ -2247,6 +2424,7 @@ "Valves updated": "Ventiler uppdaterade", "Valves updated successfully": "Ventiler uppdaterade", "variable": "variabel", + "Vector Field": "", "Verify Connection": "Verifiera anslutning", "Verify SSL Certificate": "Verifiera SSL-certifikat", "Version": "Version", @@ -2276,11 +2454,14 @@ "Web API": "Webb-API", "Web Loader Engine": "Webbladdarmotor", "Web Search": "Webbsökning", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Sökmotor", "Web Search in Chat": "Webbsökning i chatten", "Web Search Query Generation": "Generering av webbsökningsfrågor", + "Webhook deleted": "", "Webhook Name": "Namn på webhook", - "Webhook URL": "Webhook-URL", + "Webhook saved": "", "Webhooks": "Webhooks", "Webpage URLs": "URL:er till webbsidor", "WebUI Settings": "WebUI-inställningar", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "API-nyckel för Yandex webbsökning", "Yandex Web Search config": "Yandex Web Search konfiguration", "Yandex Web Search URL": "URL för Yandex-webbsökning", + "Yearly": "", "Yesterday": "Igår", "Yesterday at {{LOCALIZED_TIME}}": "Igår kl {{LOCALIZED_TIME}}", "You": "Dig", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Din webbläsare stöder inte videotaggen.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hela ditt bidrag går direkt till pluginutvecklaren; Open WebUI tar ingen procentandel. Däremot kan den valda finansieringsplattformen ha egna avgifter.", "Your message text or inputs": "Din meddelandetext eller inmatningar", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Din användningsstatistik har synkroniserats framgångsrikt.", "YouTube": "Youtube", "Youtube Language": "Youtube-språk", diff --git a/src/lib/i18n/locales/ta-IN/translation.json b/src/lib/i18n/locales/ta-IN/translation.json index 345737b5a4..cd282f698d 100644 --- a/src/lib/i18n/locales/ta-IN/translation.json +++ b/src/lib/i18n/locales/ta-IN/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} கோப்புகள்", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} மறைக்கப்பட்ட கோடுகள்", "{{COUNT}} members": "{{COUNT}} உறுப்பினர்கள்", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "{{count}} தேர்ந்தெடுக்கப்பட்டது", "{{count}} selected_other": "{{count}} தேர்ந்தெடுக்கப்பட்டன", "{{COUNT}} Sources": "{{COUNT}} ஆதாரங்கள்", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} வார்த்தைகள்", "{{COUNT}}d_time_ago": "{{COUNT}} நாட்களுக்கு முன்", "{{COUNT}}h_time_ago": "{{COUNT}} மணி நேரங்களுக்கு முன்", "{{COUNT}}m_time_ago": "{{COUNT}} நிமிடங்களுக்கு முன்", "{{COUNT}}w_time_ago": "{{COUNT}} வாரங்களுக்கு முன்", "{{COUNT}}y_time_ago": "{{COUNT}} ஆண்டுகளுக்கு முன்", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} அன்று {{LOCALIZED_TIME}} மணிக்கு", "{{model}} download has been canceled": "{{model}} பதிவிறக்கம் ரத்துசெய்யப்பட்டது", "{{modelName}} profile image": "{{modelName}} சுயவிவரப் படம்", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} இன் அரட்டைகள்", "{{webUIName}} Backend Required": "{{webUIName}} பின்தளம் தேவை", "*Prompt node ID(s) are required for image generation": "*பட உருவாக்கத்திற்கு உடனடி முனை ID(கள்) தேவை", + "1 group": "", "1 hour before": "", "1 Source": "1 ஆதாரம்", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "1 நிமிடம் முன்", @@ -57,6 +67,7 @@ "Access Control": "அணுகல் கட்டுப்பாடு", "Access Grants": "அணுகல் மானியங்கள்", "Access List": "அணுகல் பட்டியல்", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "அனைத்து பயனர்களுக்கும் அணுகக்கூடியது", "Account": "கணக்கு", @@ -72,6 +83,7 @@ "Activity": "செயல்பாடு", "Add": "சேர்", "Add a model ID": "ID மாதிரியைச் சேர்க்கவும்", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "இந்த மாதிரி என்ன செய்கிறது என்பது பற்றிய சிறு விளக்கத்தைச் சேர்க்கவும்", "Add a tag": "குறிச்சொல்லைச் சேர்க்கவும்", "Add a tag...": "குறிச்சொல்லைச் சேர்...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "தனிப்பயன் வரியில் சேர்க்கவும்", "Add description": "", "Add Details": "விவரங்களைச் சேர்க்கவும்", + "Add durable context for future chats": "", "Add Files": "கோப்புகளைச் சேர்க்கவும்", "Add Image": "படத்தைச் சேர்க்கவும்", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "உறுப்பினரைச் சேர்க்கவும்", "Add Members": "உறுப்பினர்களைச் சேர்க்கவும்", @@ -100,6 +114,7 @@ "Add to favorites": "பிடித்தவைகளில் சேர்க்கவும்", "Add User": "பயனரைச் சேர்க்கவும்", "Add User Group": "பயனர் குழுவைச் சேர்க்கவும்", + "Add webhook": "", "Add webpage": "வலைப்பக்கத்தைச் சேர்க்கவும்", "Add your Open Terminal URL and API key in Settings → Integrations.": "அமைப்புகள் → ஒருங்கிணைப்புகளில் உங்கள் Open Terminal URL மற்றும் API விசையைச் சேர்க்கவும்.", "Additional Config": "கூடுதல் கட்டமைப்பு", @@ -112,7 +127,9 @@ "Admin": "நிர்வாகி", "Admin Contact Email": "நிர்வாகி தொடர்பு மின்னஞ்சல்", "Admin Panel": "நிர்வாக குழு", + "Admin Roles": "", "Admin Settings": "நிர்வாக அமைப்புகள்", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "நிர்வாகிகளுக்கு எல்லா நேரங்களிலும் எல்லா கருவிகளுக்கும் அணுகல் உள்ளது; பயனர்களுக்கு பணியிடத்தில் ஒரு மாதிரிக்கு ஒதுக்கப்பட்ட கருவிகள் தேவை.", "Advanced": "மேம்பட்ட", "Advanced Parameters": "மேம்பட்ட அளவுருக்கள்", @@ -123,16 +140,21 @@ "All": "அனைத்தும்", "All chats have been unarchived.": "அனைத்து அரட்டைகளும் மீட்டெடுக்கப்பட்டன.", "All day": "", + "All events": "", "All models are now hidden": "அனைத்து மாடல்களும் இப்போது மறைக்கப்பட்டுள்ளன", "All models are now visible": "அனைத்து மாடல்களும் இப்போது தெரியும்", "All models deleted successfully": "அனைத்து மாடல்களும் வெற்றிகரமாக நீக்கப்பட்டன", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "எல்லா நேரமும்", "All Users": "அனைத்து பயனர்கள்", + "All users and system events": "", "Allow Call": "அழைப்பை அனுமதிக்கவும்", "Allow Chat Controls": "அரட்டை கட்டுப்பாடுகளை அனுமதிக்கவும்", "Allow Chat Delete": "அரட்டை நீக்கத்தை அனுமதிக்கவும்", "Allow Chat Edit": "அரட்டை திருத்தத்தை அனுமதிக்கவும்", "Allow Chat Export": "அரட்டை ஏற்றுமதியை அனுமதிக்கவும்", + "Allow Chat Import": "", "Allow Chat Params": "அரட்டை அளவுருக்களை அனுமதிக்கவும்", "Allow Chat Share": "அரட்டை பகிர்வை அனுமதிக்கவும்", "Allow Chat System Prompt": "அரட்டை அமைப்பு அறிவுறுத்தலை அனுமதி", @@ -152,9 +174,11 @@ "Allow User Location": "பயனர் இருப்பிடத்தை அனுமதிக்கவும்", "Allow Voice Interruption in Call": "அழைப்பில் குரல் குறுக்கீட்டை அனுமதிக்கவும்", "Allow Web Upload": "இணைய பதிவேற்றத்தை அனுமதிக்கவும்", + "Allowed Domains": "", "Allowed Endpoints": "அனுமதிக்கப்பட்ட இறுதிப்புள்ளிகள்", "Allowed File Extensions": "அனுமதிக்கப்பட்ட கோப்பு நீட்டிப்புகள்", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "பதிவேற்றம் செய்ய அனுமதிக்கப்பட்ட கோப்பு நீட்டிப்புகள். பல நீட்டிப்புகளை காற்புள்ளிகளால் பிரிக்கவும். அனைத்து கோப்பு வகைகளுக்கும் காலியாக விடவும்.", + "Allowed Roles": "", "Already have an account?": "ஏற்கனவே கணக்கு உள்ளதா?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p க்கு மாற்றாக, தரம் மற்றும் பல்வேறு சமநிலையை உறுதி செய்வதை நோக்கமாகக் கொண்டது. அளவுரு p என்பது ஒரு டோக்கனின் குறைந்தபட்ச நிகழ்தகவைக் குறிக்கிறது, இது மிகவும் சாத்தியமான டோக்கனின் நிகழ்தகவுடன் தொடர்புடையது. எடுத்துக்காட்டாக, p=0.05 மற்றும் பெரும்பாலும் 0.9 நிகழ்தகவு கொண்ட டோக்கன், 0.045 க்கும் குறைவான மதிப்பு கொண்ட லாஜிட்கள் வடிகட்டப்படும்.", "Always": "எப்போதும்", @@ -173,6 +197,7 @@ "API Base URL": "API அடிப்படை URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab மார்க்கர் சேவைக்கான API அடிப்படை URL. இயல்புநிலை: https://www.datalab.to/api/v1/marker", "API Key": "API திறவுகோல்", + "API Key / Token": "", "API Key created.": "API விசை உருவாக்கப்பட்டது.", "API Key Endpoint Restrictions": "API முக்கிய இறுதிப்புள்ளி கட்டுப்பாடுகள்", "API keys": "API விசைகள்", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "இந்த நினைவகத்தை நிச்சயமாக நீக்க விரும்புகிறீர்களா? இந்தச் செயலைச் செயல்தவிர்க்க முடியாது.", "Are you sure you want to delete this message?": "இந்தச் செய்தியை நிச்சயமாக நீக்க விரும்புகிறீர்களா?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "இந்தப் பதிப்பை நிச்சயமாக நீக்க விரும்புகிறீர்களா? இந்த பதிப்பின் பெற்றோருடன் சைல்ட் பதிப்புகள் மீண்டும் இணைக்கப்படும்.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "இதை நிச்சயமாக நீக்க வேண்டுமா?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "காப்பகப்படுத்தப்பட்ட அரட்டைகள் அனைத்தையும் மீட்டெடுக்க விரும்புகிறீர்களா?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "அரங்க மாதிரிகள்", "Artifacts": "கலைப்பொருட்கள்", "Asc": "ஏறுவரிசை", "Ask": "கேள்", "Ask a question": "ஒரு கேள்வி கேளுங்கள்", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "உதவியாளர்", "Async Embedding Processing": "ஒத்திசைவு உட்பொதித்தல் செயலாக்கம்", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "ஒலி", "August": "ஆகஸ்ட்", "Auth": "அங்கீகாரம்", + "Auth Mode": "", + "Auth required": "", "Authenticate": "அங்கீகரிக்கவும்", "Authentication": "அங்கீகாரம்", "Auto": "ஆட்டோ", "Auto (Random)": "ஆட்டோ (ரேண்டம்)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "கிளிப்போர்டுக்கு தானாக நகலெடுக்கும் பதில்", - "Auto-playback response": "தானியங்கு பின்னணி பதில்", + "Auto-Create Groups": "", + "Auto-Playback Response": "தானியங்கு பின்னணி பதில்", "Autocomplete Generation": "தானாக முடிக்கப்பட்ட தலைமுறை", "Autocomplete Generation Input Max Length": "தானாக முடிக்கப்பட்ட தலைமுறை உள்ளீடு அதிகபட்ச நீளம்", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api அங்கீகார சரம்", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 அடிப்படை URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "கிடைக்கும் கருவிகள்", "available users": "கிடைக்கும் பயனர்கள்", + "Available variables": "", "available!": "கிடைக்கும்!", "Away": "தொலைவில்", "Awful": "பரிதாபம்", @@ -258,16 +295,17 @@ "Bad Response": "மோசமான பதில்", "Banners": "பதாகைகள்", "Base Model (From)": "அடிப்படை மாதிரி (இருந்து)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "அடிப்படை மாதிரி பட்டியல் கேச், தொடக்கத்தில் அல்லது சேமி அமைப்புகளில் மட்டுமே அடிப்படை மாதிரிகளைப் பெறுவதன் மூலம் அணுகலை விரைவுபடுத்துகிறது, ஆனால் சமீபத்திய அடிப்படை மாதிரி மாற்றங்களைக் காட்டாமல் போகலாம்.", "Bearer": "தாங்குபவர்", "before": "முன்", "Being lazy": "சோம்பேறியாக இருப்பது", - "Beta": "பீட்டா", "Bing": "பிங்", "Bing Search V7 Endpoint": "பிங் தேடல் V7 இறுதிப்புள்ளி", "Bing Search V7 Subscription Key": "Bing தேடல் V7 சந்தா விசை", "Bio": "உயிர்", "Birth Date": "பிறந்த தேதி", + "Blocked Groups": "", "BM25 Weight": "BM25 எடை", "Bocha Search API Key": "போச்சா தேடல் API விசை", "Bold": "தடித்த", @@ -324,7 +362,7 @@ "Chat Completions": "அரட்டை நிறைவுகள்", "Chat Conversation": "அரட்டை உரையாடல்", "Chat deleted.": "", - "Chat direction": "அரட்டை திசை", + "Chat Direction": "அரட்டை திசை", "Chat exported successfully": "அரட்டை வெற்றிகரமாக ஏற்றுமதி செய்யப்பட்டது", "Chat History": "அரட்டை வரலாறு", "Chat ID": "அரட்டை ID", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "மக்கள் உறுப்பினர்களாக சேரும் ஒத்துழைப்பு சேனல்", "Collapse": "சுருக்கு", "Collection": "சேகரிப்பு", + "Collection Field": "", "Collections": "தொகுப்புகள்", "Color": "நிறம்", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI பணிப்பாய்வு", "ComfyUI Workflow Nodes": "ComfyUI பணிப்பாய்வு முனைகள்", "Comma separated Node Ids (e.g. 1 or 1,2)": "கமாவால் பிரிக்கப்பட்ட முனை ஐடிகள் (எ.கா. 1 அல்லது 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "கட்டளை", "Command": "கட்டளை", "Comment": "கருத்து", "Commit Message": "கமிட் செய்தி", "Community Reviews": "சமூக மதிப்புரைகள்", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "நிறைவுகள்", "Compress Images in Channels": "சேனல்களில் படங்களை சுருக்கவும்", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Open Terminal நிகழ்வுகளுடன் இணைக்கவும். இந்த சேவையகங்கள் மூலம் அனைத்து பயனர்களும் கோப்பு உலாவல் மற்றும் முனைய கருவிகளுக்கான அணுகலைப் பெறுவார்கள்.", "Connect to your own OpenAI compatible API endpoints.": "உங்கள் சொந்த OpenAI இணக்கமான API இறுதிப்புள்ளிகளுடன் இணைக்கவும்.", "Connect to your own OpenAPI compatible external tool servers.": "உங்கள் சொந்த OpenAPI இணக்கமான வெளிப்புற கருவி சேவையகங்களுடன் இணைக்கவும்.", + "Connected": "", "Connected ({{type}})": "இணைக்கப்பட்டது ({{type}})", "Connection failed": "இணைப்பு தோல்வியடைந்தது", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUI அணுகலுக்கு நிர்வாகியைத் தொடர்பு கொள்ளவும்", "Content": "உள்ளடக்கம்", "Content Extraction Engine": "உள்ளடக்கத்தை பிரித்தெடுக்கும் இயந்திரம்", + "Content Field": "", "Content lengths (character counts only)": "உள்ளடக்க நீளம் (எழுத்து எண்ணிக்கை மட்டும்)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "பதிலைத் தொடரவும்", "Continue with {{provider}}": "{{provider}} உடன் தொடரவும்", "Continue with Email": "மின்னஞ்சலைத் தொடரவும்", @@ -493,6 +543,7 @@ "Create new secret key": "புதிய ரகசிய விசையை உருவாக்கவும்", "Create note": "குறிப்பை உருவாக்கவும்", "Create Note": "குறிப்பை உருவாக்கவும்", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "தொடர்ச்சியான அடிப்படையில் தானாக இயங்கும் திட்டமிட்ட வினாக்களை உருவாக்கவும்.", "Create your first note by clicking on the plus button below.": "கீழே உள்ள பிளஸ் பொத்தானைக் கிளிக் செய்வதன் மூலம் உங்கள் முதல் குறிப்பை உருவாக்கவும்.", "Created at": "இல் உருவாக்கப்பட்டது", @@ -510,6 +561,7 @@ "Custom Gender": "தனிப்பயன் பாலினம்", "Custom Parameter Name": "தனிப்பயன் அளவுரு பெயர்", "Custom Parameter Value": "தனிப்பயன் அளவுரு மதிப்பு", + "Custom range": "", "Daily": "", "Daily Messages": "தினசரி செய்திகள்", "Danger Zone": "ஆபத்து மண்டலம்", @@ -532,7 +584,6 @@ "Default Features": "இயல்புநிலை அம்சங்கள்", "Default Filters": "இயல்பு வடிப்பான்கள்", "Default Group": "இயல்புநிலை குழு", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "செயல்பாட்டிற்கு முன் ஒருமுறை கருவிகளை அழைப்பதன் மூலம் இயல்புநிலை பயன்முறையானது பரந்த அளவிலான மாடல்களுடன் செயல்படுகிறது. நேட்டிவ் பயன்முறையானது மாடலின் உள்ளமைக்கப்பட்ட கருவி-அழைப்பு திறன்களை மேம்படுத்துகிறது, ஆனால் இந்த அம்சத்தை இயல்பாகவே ஆதரிக்கும் மாதிரி தேவைப்படுகிறது.", "Default Model": "இயல்புநிலை மாதிரி", "Default model updated": "இயல்பு மாதிரி புதுப்பிக்கப்பட்டது", "Default permissions": "இயல்புநிலை அனுமதிகள்", @@ -542,6 +593,7 @@ "Default to ALL": "ALLக்கு இயல்புநிலை", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "கவனம் செலுத்திய மற்றும் தொடர்புடைய உள்ளடக்கத்தைப் பிரித்தெடுப்பதற்காக பிரித்தெடுக்கப்பட்ட மீட்டெடுப்புக்கு இயல்புநிலை, இது பெரும்பாலான சந்தர்ப்பங்களில் பரிந்துரைக்கப்படுகிறது.", "Default User Role": "இயல்புநிலை பயனர் பங்கு", + "Default webhook": "", "Defaults": "இயல்புநிலைகள்", "Delete": "நீக்கு", "Delete {{name}}": "{{name}} நீக்கு", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "குறியீடு மொழிபெயர்ப்பாளரை முடக்கு", "Disable Image Extraction": "படத்தை பிரித்தெடுப்பதை முடக்கு", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF இலிருந்து படத்தை பிரித்தெடுப்பதை முடக்கு. LLMஐப் பயன்படுத்துதல் இயக்கப்பட்டிருந்தால், படங்கள் தானாகவே தலைப்பிடப்படும். இயல்புநிலையிலிருந்து தவறு.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "முடக்கப்பட்டது", "Disconnect OAuth": "", "Discover a function": "ஒரு செயல்பாட்டைக் கண்டறியவும்", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "மாதிரி முன்னமைவுகளைக் கண்டறியவும், பதிவிறக்கவும் மற்றும் ஆராயவும்", "Discussion channel where access is based on groups and permissions": "குழுக்கள் மற்றும் அனுமதிகளின் அடிப்படையில் அணுகல் இருக்கும் கலந்துரையாடல் சேனல்", "Display": "காட்சி", - "Display chat title in tab": "அரட்டை தலைப்பை தாவலில் காண்பி", + "Display Chat Title in Tab": "அரட்டை தலைப்பை தாவலில் காண்பி", "Display Emoji in Call": "அழைப்பில் ஈமோஜியைக் காட்டு", "Display Multi-model Responses in Tabs": "தாவல்களில் பல மாதிரி பதில்களைக் காண்பி", - "Display the username instead of You in the Chat": "அரட்டையில் உங்களுக்குப் பதிலாக பயனர்பெயரைக் காட்டவும்", + "Display the Username Instead of You in the Chat": "அரட்டையில் உங்களுக்குப் பதிலாக பயனர்பெயரைக் காட்டவும்", "Displays citations in the response": "பதிலில் மேற்கோள்களைக் காட்டுகிறது", "Displays status updates (e.g., web search progress) in the response": "பதிலில் நிலை புதுப்பிப்புகளை (எ.கா. இணைய தேடல் முன்னேற்றம்) காட்டுகிறது", "Dive into knowledge": "அறிவில் மூழ்குங்கள்", @@ -630,6 +684,7 @@ "Docling Parameters": "டாக்லிங் அளவுருக்கள்", "Docling Server URL required.": "டாக்லிங் சர்வர் URL தேவை.", "Document": "ஆவணம்", + "Document ID Field": "", "Document Intelligence": "ஆவண நுண்ணறிவு", "Document Intelligence endpoint required.": "ஆவண நுண்ணறிவு இறுதிப்புள்ளி தேவை.", "Document Intelligence Model": "ஆவண நுண்ணறிவு மாதிரி", @@ -685,12 +740,14 @@ "Edit Default Permissions": "இயல்புநிலை அனுமதிகளைத் திருத்தவும்", "Edit Folder": "கோப்புறையைத் திருத்து", "Edit Image": "படத்தை திருத்து", + "Edit Knowledge Connection": "", "Edit Last Message": "கடைசி செய்தியைத் திருத்தவும்", "Edit Memory": "நினைவகத்தைத் திருத்து", "Edit Prompt": "திருத்துதல்", "Edit Terminal Connection": "டெர்மினல் இணைப்பைத் திருத்து", "Edit User": "பயனரைத் திருத்து", "Edit User Group": "பயனர் குழுவைத் திருத்தவும்", + "Edit webhook": "", "Edit workflow.json content": "workflow.json உள்ளடக்கத்தைத் திருத்தவும்", "edited": "திருத்தப்பட்டது", "Edited": "திருத்தப்பட்டது", @@ -699,6 +756,7 @@ "Eject model": "வெளியேற்ற மாதிரி", "ElevenLabs": "லெவன் லேப்ஸ்", "Email": "மின்னஞ்சல்", + "Email Claim": "", "Embark on adventures": "சாகசங்களை மேற்கொள்ளுங்கள்", "Embedding": "உட்பொதித்தல்", "Embedding Batch Size": "உட்பொதித்தல் தொகுதி அளவு", @@ -707,6 +765,7 @@ "Embedding Model Engine": "எம்பெடிங் மாடல் எஞ்சின்", "Emoji": "", "Emojis": "எமோஜிகள்", + "Empty": "", "Empty message": "வெற்று செய்தி", "Enable All": "அனைத்தையும் இயக்கு", "Enable API Keys": "API விசைகளை இயக்கவும்", @@ -714,22 +773,27 @@ "Enable Code Execution": "குறியீடு செயல்படுத்தலை இயக்கு", "Enable Code Interpreter": "குறியீடு மொழிபெயர்ப்பாளரை இயக்கவும்", "Enable Community Sharing": "சமூகப் பகிர்வை இயக்கு", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "RAM இலிருந்து மாதிரி தரவு மாற்றப்படுவதைத் தடுக்க நினைவகப் பூட்டுதலை (mlock) இயக்கவும். இந்த விருப்பம் மாதிரியின் வேலை செய்யும் பக்கங்களின் தொகுப்பை RAM இல் பூட்டுகிறது, அவை வட்டுக்கு மாற்றப்படாது என்பதை உறுதி செய்கிறது. இது பக்க பிழைகளைத் தவிர்ப்பதன் மூலமும், விரைவான தரவு அணுகலை உறுதி செய்வதன் மூலமும் செயல்திறனைப் பராமரிக்க உதவும்.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "மாதிரி தரவை ஏற்ற நினைவக மேப்பிங்கை (mmap) இயக்கவும். வட்டு கோப்புகளை RAM இல் இருப்பதைப் போலவே RAM இன் நீட்டிப்பாக வட்டு சேமிப்பகத்தைப் பயன்படுத்த இந்த விருப்பம் கணினியை அனுமதிக்கிறது. வேகமான தரவு அணுகலை அனுமதிப்பதன் மூலம் இது மாதிரி செயல்திறனை மேம்படுத்தலாம். இருப்பினும், இது அனைத்து கணினிகளிலும் சரியாக வேலை செய்யாமல் போகலாம் மற்றும் கணிசமான அளவு வட்டு இடத்தை எடுத்துக்கொள்ளலாம்.", "Enable Message Queue": "செய்தி வரிசையை இயக்கு", "Enable Message Rating": "செய்தி மதிப்பீட்டை இயக்கு", "Enable Mirostat sampling for controlling perplexity.": "குழப்பத்தைக் கட்டுப்படுத்த Mirostat மாதிரியை இயக்கவும்.", "Enable New Sign Ups": "புதிய பதிவுகளை இயக்கவும்", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "மாதிரியால் பயன்படுத்தப்படும் பகுத்தறிவு குறிச்சொற்களை இயக்கவும், முடக்கவும் அல்லது தனிப்பயனாக்கவும். \"இயக்கப்பட்டது\" இயல்புநிலை குறிச்சொற்களைப் பயன்படுத்துகிறது, \"முடக்கப்பட்டது\" பகுத்தறிவு குறிச்சொற்களை முடக்குகிறது, மேலும் \"தனிப்பயன்\" உங்கள் சொந்த தொடக்க மற்றும் முடிவு குறிச்சொற்களைக் குறிப்பிட உங்களை அனுமதிக்கிறது.", "Enabled": "இயக்கப்பட்டது", "End Tag": "எண்ட் டேக்", + "Endpoint": "", "Endpoint URL": "இறுதிப்புள்ளி URL", "Enforce Temporary Chat": "தற்காலிக அரட்டையைச் செயல்படுத்தவும்", "Enhance": "மேம்படுத்து", "Enrich Hybrid Search Text": "ஹைப்ரிட் தேடல் உரையை வளப்படுத்தவும்", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "உங்கள் CSV கோப்பில் இந்த வரிசையில் 4 நெடுவரிசைகள் உள்ளன: பெயர், மின்னஞ்சல், கடவுச்சொல், பங்கு.", "Enter {{role}} message here": "இங்கே {{role}} செய்தியை உள்ளிடவும்", - "Enter a detail about yourself for your LLMs to recall": "உங்கள் எல்எல்எம்களை நினைவுபடுத்த உங்களைப் பற்றிய விவரங்களை உள்ளிடவும்", "Enter a title for the pending user info overlay. Leave empty for default.": "நிலுவையில் உள்ள பயனர் தகவல் மேலடுக்குக்கான தலைப்பை உள்ளிடவும். இயல்புநிலைக்கு காலியாக விடவும்.", "Enter a watermark for the response. Leave empty for none.": "பதிலுக்கான வாட்டர்மார்க்கை உள்ளிடவும். எதற்கும் காலியாக விடவும்.", "Enter additional headers in JSON format": "கூடுதல் தலைப்புகளை JSON வடிவத்தில் உள்ளிடவும்", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "துண்டின் குறைந்தபட்ச அளவு இலக்கை உள்ளிடவும்", "Enter Chunk Overlap": "Chunk Overlap ஐ உள்ளிடவும்", "Enter Chunk Size": "துண்டின் அளவை உள்ளிடவும்", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "கமாவால் பிரிக்கப்பட்ட \"டோக்கன்:பயாஸ்_மதிப்பு\" ஜோடிகளை உள்ளிடவும் (எடுத்துக்காட்டு: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "நிலுவையில் உள்ள பயனர் தகவல் மேலடுக்குக்கான உள்ளடக்கத்தை உள்ளிடவும். இயல்புநிலைக்கு காலியாக விடவும்.", "Enter coordinates (e.g. 51.505, -0.09)": "ஆயங்களை உள்ளிடவும் (எ.கா. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter URL ஐ உள்ளிடவும்", "Enter Kagi Search API Key": "Kagi தேடல் API விசையை உள்ளிடவும்", "Enter Key Behavior": "முக்கிய நடத்தை உள்ளிடவும்", + "Enter language": "", "Enter language codes": "மொழி குறியீடுகளை உள்ளிடவும்", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "MinerU API விசையை உள்ளிடவும்", "Enter Mistral API Base URL": "Mistral API Base URL ஐ உள்ளிடவும்", "Enter Mistral API Key": "Mistral API விசையை உள்ளிடவும்", @@ -804,6 +873,7 @@ "Enter prompt here.": "இங்கே வினாவை உள்ளிடவும்.", "Enter proxy URL (e.g. https://user:password@host:port)": "ப்ராக்ஸியை உள்ளிடவும் URL (எ.கா. https://user:password@host:port)", "Enter reasoning effort": "பகுத்தறிவு முயற்சியை உள்ளிடவும்", + "Enter Redirect URI": "", "Enter Score": "மதிப்பெண்ணை உள்ளிடவும்", "Enter SearchApi API Key": "SearchApi API விசையை உள்ளிடவும்", "Enter SearchApi Engine": "SearchApi இன்ஜினை உள்ளிடவும்", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API விசையை உள்ளிடவும்", "Enter SerpApi Engine": "SerpApi இன்ஜினை உள்ளிடவும்", "Enter Serper API Key": "Serper API விசையை உள்ளிடவும்", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API விசையை உள்ளிடவும்", "Enter Serpstack API Key": "Serpstack API விசையை உள்ளிடவும்", "Enter server host": "சர்வர் ஹோஸ்டை உள்ளிடவும்", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "டிகா சர்வரை உள்ளிடவும் URL", "Enter timeout in seconds": "நொடிகளில் காலாவதியை உள்ளிடவும்", "Enter to Send": "அனுப்ப உள்ளிடவும்", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "மேல் K ஐ உள்ளிடவும்", "Enter Top K Reranker": "டாப் கே ரேங்கரை உள்ளிடவும்", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL உள்ளிடவும் (எ.கா. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "பிழை: ID '{{modelId}}' உடன் ஒரு மாதிரி ஏற்கனவே உள்ளது. தொடர வேறு ID ஐத் தேர்ந்தெடுக்கவும்.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "பிழை: மாடல் ID காலியாக இருக்க முடியாது. தொடர சரியான ID ஐ உள்ளிடவும்.", "Evaluations": "மதிப்பீடுகள்", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API விசை", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "எடுத்துக்காட்டு: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "எடுத்துக்காட்டு: ALL", "Example: mail": "எடுத்துக்காட்டு: அஞ்சல்", @@ -905,12 +982,18 @@ "Export Config": "ஏற்றுமதி கட்டமைப்பு", "Export Models": "ஏற்றுமதி மாதிரிகள்", "Export Prompts": "ஏற்றுமதி தூண்டுதல்கள்", + "Export Skills": "", "Export to CSV": "CSV க்கு ஏற்றுமதி", "Export Tools": "ஏற்றுமதி கருவிகள்", "Export Users": "ஏற்றுமதி பயனர்கள்", "External": "வெளி", + "External connection not found.": "", "External Document Loader URL required.": "வெளிப்புற ஆவண ஏற்றி URL தேவை.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "வெளிப்புற பணி மாதிரி", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "வெளிப்புற வலை ஏற்றி API விசை", "External Web Loader URL": "வெளிப்புற வலை ஏற்றி URL", "External Web Search API Key": "வெளிப்புற வலைத் தேடல் API விசை", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API விசையை உருவாக்குவதில் தோல்வி.", "Failed to delete calendar": "", "Failed to delete note": "குறிப்பை நீக்க முடியவில்லை", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "படத்தைப் பதிவிறக்க முடியவில்லை", "Failed to extract content from the file: {{error}}": "கோப்பிலிருந்து உள்ளடக்கத்தைப் பிரித்தெடுக்க முடியவில்லை: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "மாடல்களைப் பெறுவதில் தோல்வி", "Failed to generate title": "தலைப்பை உருவாக்க முடியவில்லை", "Failed to import models": "மாடல்களை இறக்குமதி செய்ய முடியவில்லை", + "Failed to load chat": "", "Failed to load chat preview": "அரட்டை மாதிரிக்காட்சியை ஏற்றுவதில் தோல்வி", "Failed to load DOCX file. Please try downloading it instead.": "DOCX கோப்பை ஏற்ற முடியவில்லை. அதற்குப் பதிலாகப் பதிவிறக்க முயற்சிக்கவும்.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV கோப்பை ஏற்ற முடியவில்லை. அதற்குப் பதிலாகப் பதிவிறக்க முயற்சிக்கவும்.", @@ -944,6 +1029,7 @@ "Failed to move chat": "அரட்டையை நகர்த்த முடியவில்லை", "Failed to process URL: {{url}}": "URL: {{url}} செயலாக்க முடியவில்லை", "Failed to read clipboard contents": "கிளிப்போர்டு உள்ளடக்கங்களைப் படிக்க முடியவில்லை", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "உறுப்பினரை அகற்ற முடியவில்லை", "Failed to render diagram": "வரைபடத்தை வழங்குவதில் தோல்வி", "Failed to render visualization": "காட்சிப்படுத்தலை வழங்குவதில் தோல்வி", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "மாதிரிகள் உள்ளமைவைச் சேமிப்பதில் தோல்வி", "Failed to save policy: {{error}}": "கொள்கையைச் சேமிக்க முடியவில்லை: {{error}}", "Failed to save terminal servers": "டெர்மினல் சர்வர்களைச் சேமிப்பதில் தோல்வி", + "Failed to save webhook": "", "Failed to unshare chat.": "அரட்டையின் பகிர்வை நீக்க முடியவில்லை.", "Failed to update settings": "அமைப்புகளைப் புதுப்பிக்க முடியவில்லை", "Failed to update status": "நிலையைப் புதுப்பிக்க முடியவில்லை", + "Failed to update webhook": "", "Failed to upload file.": "கோப்பை பதிவேற்ற முடியவில்லை.", "Features": "அம்சங்கள்", "Features Permissions": "அம்சங்கள் அனுமதிகள்", @@ -987,6 +1075,8 @@ "File uploaded successfully": "கோப்பு பதிவேற்றப்பட்டது", "Filename": "கோப்பு பெயர்", "Files": "கோப்புகள்", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "வடிகட்டி", "Filter is now globally disabled": "வடிகட்டி இப்போது உலகளவில் முடக்கப்பட்டுள்ளது", "Filter is now globally enabled": "வடிகட்டி இப்போது உலகளவில் இயக்கப்பட்டுள்ளது", @@ -1009,6 +1099,7 @@ "Folder options": "கோப்புறை விருப்பங்கள்", "Folder updated successfully": "கோப்புறை வெற்றிகரமாக புதுப்பிக்கப்பட்டது", "Folders": "கோப்புறைகள்", + "Folders Sharing": "", "Follow up": "பின்தொடரவும்", "Follow Up Generation": "ஃபாலோ அப் தலைமுறை", "Follow Up Generation Prompt": "ஃபாலோ அப் ஜெனரேஷன் ப்ராம்ப்ட்", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "செயல்பாடு இப்போது உலகளவில் இயக்கப்பட்டுள்ளது", "Function Name": "செயல்பாட்டு பெயர்", "Function Name Filter List": "செயல்பாடு பெயர் வடிகட்டி பட்டியல்", + "Function starter": "", "Function updated successfully": "செயல்பாடு வெற்றிகரமாக புதுப்பிக்கப்பட்டது", "Functions": "செயல்பாடுகள்", "Functions allow arbitrary code execution.": "செயல்பாடுகள் தன்னிச்சையான குறியீடு செயல்படுத்தலை அனுமதிக்கின்றன.", @@ -1071,7 +1163,10 @@ "Gravatar": "கிராவதார்", "Grid": "கட்டம்", "Grokipedia": "க்ரோக்கிபீடியா", + "group": "", + "Group": "", "Group Channel": "குழு சேனல்", + "Group Claim": "", "Group created successfully": "குழு வெற்றிகரமாக உருவாக்கப்பட்டது", "Group deleted successfully": "குழு வெற்றிகரமாக நீக்கப்பட்டது", "Group Description": "குழு விளக்கம்", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "ஹாப்டிக் கருத்து", + "Header variables": "", "Headers": "தலைப்புகள்", "Headers must be a valid JSON object": "தலைப்புகள் சரியான JSON பொருளாக இருக்க வேண்டும்", "Height": "உயரம்", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID இல் \":\" அல்லது \"|\" இருக்கக்கூடாது பாத்திரங்கள்", "ID copied to clipboard": "ID கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "செயலற்ற நேரம் முடிந்தது", "iframe Sandbox Allow Forms": "iframe சாண்ட்பாக்ஸ் படிவங்களை அனுமதி", "iframe Sandbox Allow Same Origin": "iframe சாண்ட்பாக்ஸ் அதே தோற்றத்தை அனுமதிக்கும்", @@ -1138,6 +1236,7 @@ "Import From Link": "இணைப்பிலிருந்து இறக்குமதி செய்யவும்", "Import Models": "இறக்குமதி மாதிரிகள்", "Import Prompts": "இறக்குமதி தூண்டுதல்கள்", + "Import Skills": "", "Import successful": "இறக்குமதி வெற்றி", "Import Tools": "இறக்குமதி கருவிகள்", "Important Update": "முக்கியமான புதுப்பிப்பு", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "பக்கப்பட்டியில் வைக்கவும்", "Key": "முக்கிய", "Key is required": "சாவி தேவை", - "Keyboard shortcuts": "விசைப்பலகை குறுக்குவழிகள்", "Keyboard Shortcuts": "விசைப்பலகை குறுக்குவழிகள்", "Knowledge": "அறிவு", "Knowledge Access": "அறிவு அணுகல்", @@ -1208,6 +1306,8 @@ "Knowledge Name": "அறிவு பெயர்", "Knowledge Public Sharing": "அறிவு பொது பகிர்வு", "Knowledge Sharing": "அறிவுப் பகிர்வு", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "அறிவு வெற்றிகரமாக புதுப்பிக்கப்பட்டது", "Kokoro.js (Browser)": "Kokoro.js (உலாவி)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "கடைசியாக இயங்கியது", "Last reply": "கடைசி பதில்", "LDAP": "LDAP", - "LDAP server updated": "LDAP சேவையகம் புதுப்பிக்கப்பட்டது", "Leaderboard": "லீடர்போர்டு", "Learn more": "மேலும் அறிக", "Learn More": "மேலும் அறிக", @@ -1246,6 +1345,7 @@ "Legacy": "மரபு", "lexical": "சொல்லகராதி", "License": "உரிமம்", + "Lifecycle JSON": "", "Lift List": "லிஃப்ட் பட்டியல்", "Light": "வெளிச்சமான", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "ஒரே நேரத்தில் தேடல் வினவல்களை வரம்பிடவும். 0 = வரம்பற்றது (இயல்புநிலை). தொடர்ச்சியான செயல்பாட்டிற்கு 1 என அமைக்கவும் (பிரேவ் ஃப்ரீ டையர் போன்ற கடுமையான விகித வரம்புகளைக் கொண்ட API களுக்குப் பரிந்துரைக்கப்படுகிறது).", @@ -1269,6 +1369,7 @@ "Location access not allowed": "இருப்பிட அணுகல் அனுமதிக்கப்படவில்லை", "Lost": "இழந்தது", "Low": "குறைந்த", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Open WebUI சமூகத்தால் உருவாக்கப்பட்டது", "Make password visible in the user interface": "கடவுச்சொல்லை பயனர் இடைமுகத்தில் தெரியும்படி செய்யவும்", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "குழாய்களை நிர்வகிக்கவும்", "Manage Tool Servers": "கருவி சேவையகங்களை நிர்வகிக்கவும்", "Manage your account information.": "உங்கள் கணக்கு தகவலை நிர்வகிக்கவும்.", + "Mapped Source": "", "March": "மார்ச்", "Markdown": "மார்க் டவுன்", "Markdown Header Text Splitter": "மார்க் டவுன் தலைப்பு உரை பிரிப்பான்", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "நினைவகம் வெற்றிகரமாக அழிக்கப்பட்டது", "Memory deleted successfully": "நினைவகம் வெற்றிகரமாக நீக்கப்பட்டது", "Memory updated successfully": "நினைவகம் வெற்றிகரமாக புதுப்பிக்கப்பட்டது", + "Merge Accounts by Email": "", "Merge Responses": "பதில்களை ஒன்றிணைக்கவும்", "Merged Response": "இணைக்கப்பட்ட பதில்", "Message": "செய்தி", @@ -1322,9 +1425,12 @@ "messages": "செய்திகள்", "Messages": "செய்திகள்", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "உங்கள் இணைப்பை உருவாக்கிய பிறகு நீங்கள் அனுப்பும் செய்திகள் பகிரப்படாது. URL உள்ள பயனர்கள் பகிரப்பட்ட அரட்டையைப் பார்க்க முடியும்.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (தனிப்பட்ட)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (வேலை/பள்ளி)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "நிமிடம்", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "MinerU API கிளவுட் API பயன்முறைக்கு விசை தேவை.", @@ -1377,6 +1483,7 @@ "Models Sharing": "மாதிரிகள் பகிர்வு", "Mojeek": "மொஜீக்", "Mojeek Search API Key": "Mojeek தேடல் API விசை", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "மேலும்", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "உங்கள் அறிவுத் தளத்தை பெயரிடுங்கள்", "Name, prompt, and model are required": "பெயர், வினா மற்றும் மாதிரி தேவை", "Native": "பூர்வீகம்", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "ஒருபோதும் இல்லை", "New": "புதியது", "New Automation": "புதிய தானியக்கம்", @@ -1423,6 +1531,7 @@ "Next run": "அடுத்த இயக்கம்", "No access grants. Private to you.": "அணுகல் மானியங்கள் இல்லை. உங்களுக்கு தனிப்பட்டது.", "No activity data": "செயல்பாட்டுத் தரவு இல்லை", + "No additional headers are sent unless configured.": "", "No authentication": "அங்கீகாரம் இல்லை", "No automations found": "தானியக்கங்கள் எதுவும் இல்லை", "No chats found": "அரட்டைகள் எதுவும் இல்லை", @@ -1435,8 +1544,10 @@ "No data": "தரவு இல்லை", "No data found": "தரவு எதுவும் கிடைக்கவில்லை", "No distance available": "தூரம் இல்லை", + "No event webhooks configured.": "", "No execution logs available yet": "இன்னும் இயக்க பதிவுகள் இல்லை", "No expiration can pose security risks.": "எந்த காலாவதியும் பாதுகாப்பு அபாயங்களை ஏற்படுத்தாது.", + "No external knowledge sources configured.": "", "No feedback found": "கருத்து எதுவும் இல்லை", "No file selected": "கோப்பு எதுவும் தேர்ந்தெடுக்கப்படவில்லை", "No files found": "கோப்புகள் எதுவும் இல்லை", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "பின் செய்யப்பட்ட செய்திகள் இல்லை", "No prompts found": "எந்த அறிவிப்பும் இல்லை", + "No Repeat": "", "No results": "முடிவுகள் இல்லை", "No results found": "முடிவுகள் எதுவும் கிடைக்கவில்லை", "No search query generated": "தேடல் வினவல் உருவாக்கப்படவில்லை", @@ -1483,6 +1595,7 @@ "No webhooks yet": "இதுவரை வெப்ஹூக்குகள் இல்லை", "Node Ids": "முனை ஐடிகள்", "None": "எதுவுமில்லை", + "Not configured": "", "Not factually correct": "உண்மையில் சரியாக இல்லை", "Not helpful": "உதவியாக இல்லை", "Not Registered": "பதிவு செய்யப்படவில்லை", @@ -1498,20 +1611,25 @@ "Notifications": "அறிவிப்புகள்", "November": "நவம்பர்", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (நிலையான)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "அக்டோபர்", "Off": "ஆஃப்", "Okay, Let's Go!": "சரி, போகலாம்!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED இருண்ட", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API அமைப்புகள் புதுப்பிக்கப்பட்டன", "Ollama Cloud API Key": "Ollama கிளவுட் API விசை", "Ollama Version": "Ollama பதிப்பு", + "Omit": "", "On": "அன்று", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "கடவுச்சொல்", "Passwords do not match.": "கடவுச்சொற்கள் பொருந்தவில்லை.", "Paste Large Text as File": "பெரிய உரையை கோப்பாக ஒட்டவும்", + "Path": "", "Path copied": "", "Paused": "இடைநிறுத்தப்பட்டது", "PDF document (.pdf)": "PDF ஆவணம் (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "நிலுவையில் உள்ளது", "Pending": "நிலுவையில் உள்ளது", + "Pending Accounts": "", "Pending User Overlay Content": "நிலுவையில் உள்ள பயனர் மேலடுக்கு உள்ளடக்கம்", "Pending User Overlay Title": "நிலுவையில் உள்ள பயனர் மேலடுக்கு தலைப்பு", "Permission denied when accessing media devices": "மீடியா சாதனங்களை அணுகும்போது அனுமதி மறுக்கப்பட்டது", "Permission denied when accessing microphone": "மைக்ரோஃபோனை அணுகும்போது அனுமதி மறுக்கப்பட்டது", "Permission denied when accessing microphone: {{error}}": "மைக்ரோஃபோனை அணுகும்போது அனுமதி மறுக்கப்பட்டது: {{error}}", "Permissions": "அனுமதிகள்", + "Permissions reset to defaults": "", "Perplexity API Key": "குழப்பம் API விசை", "Perplexity Model": "குழப்ப மாதிரி", "Perplexity Search API URL": "குழப்பமான தேடல் API URL", "Perplexity Search Context Usage": "குழப்பமான தேடல் சூழல் பயன்பாடு", "Persistent": "பிடிவாதமான", "Personalization": "தனிப்பயனாக்கம்", + "Picture Claim": "", "Pin": "பின்", "Pin to Sidebar": "", "Pinned": "நிலைநிறுத்தப்பட்டவை", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "அனைத்து துறைகளையும் நிரப்பவும்.", "Please register the OAuth client": "OAuth கிளையண்டை பதிவு செய்யவும்", "Please save the connection to persist the OAuth client information and do not change the ID": "OAuth கிளையண்ட் தகவலைத் தொடர இணைப்பைச் சேமிக்கவும் மேலும் ID ஐ மாற்ற வேண்டாம்", - "Please select a model first.": "முதலில் ஒரு மாதிரியைத் தேர்ந்தெடுக்கவும்.", "Please select a model.": "ஒரு மாதிரியைத் தேர்ந்தெடுக்கவும்.", "Please select a reason": "தயவுசெய்து காரணத்தைத் தேர்ந்தெடுக்கவும்", "Please select a valid JSON file": "சரியான JSON கோப்பைத் தேர்ந்தெடுக்கவும்", "Please select at least one user for Direct Message channel.": "நேரடி செய்தி சேனலுக்கு குறைந்தபட்சம் ஒரு பயனரையாவது தேர்ந்தெடுக்கவும்.", "Please wait until all files are uploaded.": "எல்லா கோப்புகளும் பதிவேற்றப்படும் வரை காத்திருக்கவும்.", "Policy ID": "கொள்கை ID", + "Policy ID is required": "", "Port": "துறைமுகம்", "Ports": "துறைமுகங்கள்", "Positive attitude": "நேர்மறையான அணுகுமுறை", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "பொதுப் பகிர்வைத் தூண்டுகிறது", "Prompts Sharing": "பகிர்வதைத் தூண்டுகிறது", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "பொது", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com இலிருந்து \"{{searchValue}}\" ஐ இழுக்கவும்", "Pull a model from Ollama.com": "Ollama.com இலிருந்து ஒரு மாதிரியை இழுக்கவும்", @@ -1687,21 +1811,29 @@ "Read": "படிக்கவும்", "Read Aloud": "உரக்கப் படியுங்கள்", "Read more →": "மேலும் படிக்க →", + "Read only": "", "Read Only": "படிக்க மட்டும்", "Read-Only Access": "படிக்க மட்டும் அணுகல்", "Reason": "காரணம்", "Reasoning Effort": "பகுத்தறிவு முயற்சி", "Reasoning Tags": "பகுத்தறிவு குறிச்சொற்கள்", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "சமீபத்தில் பயன்படுத்தப்பட்டது", "Reconnected": "", "Record": "பதிவு", "Record voice": "குரல் பதிவு", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "உங்களை Open WebUI சமூகத்திற்கு திருப்பி விடுகிறோம்", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "முட்டாள்தனத்தை உருவாக்கும் நிகழ்தகவை குறைக்கிறது. அதிக மதிப்பு (எ.கா. 100) மிகவும் மாறுபட்ட பதில்களைக் கொடுக்கும், அதே சமயம் குறைந்த மதிப்பு (எ.கா. 10) மிகவும் பழமைவாதமாக இருக்கும்.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "உங்களை \"பயனர்\" என்று குறிப்பிடவும் (எ.கா., \"பயனர் ஸ்பானிஷ் மொழியைக் கற்கிறார்\")", "Reference Chats": "குறிப்பு அரட்டைகள்", "Refresh": "புதுப்பி", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "கூடாதபோது மறுத்துவிட்டார்", "Regenerate": "மீண்டும் உருவாக்கு", "Regenerate Menu": "மெனுவை மீண்டும் உருவாக்கவும்", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "முன்னோட்டங்களில் ரெண்டர் மார்க் டவுன்", "Render Markdown in User Messages": "", "Reorder Models": "மாதிரிகளை மறுவரிசைப்படுத்தவும்", + "Repeat": "", "Repeats": "மீண்டும் நிகழ்வுகள்", "Reply": "பதில்", "Reply in Thread": "த்ரெட்டில் பதிலளிக்கவும்", "Reply to thread...": "திரிக்கு பதில்...", "Replying to {{NAME}}": "{{NAME}} க்கு பதிலளிக்கிறது", + "Require users to confirm before using Web Search.": "", "required": "தேவை", "Reranking Batch Size": "", "Reranking Engine": "மறுவரிசைப்படுத்தல் இயந்திரம்", "Reranking Model": "மறுவரிசைப்படுத்தல் மாதிரி", + "Research Knowledge": "", "Reset": "மீட்டமை", "Reset All Models": "அனைத்து மாடல்களையும் மீட்டமைக்கவும்", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "படத்தை மீட்டமைக்கவும்", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "பதிவேற்ற கோப்பகத்தை மீட்டமைக்கவும்", "Reset Vector Storage/Knowledge": "வெக்டர் சேமிப்பகம்/அறிவை மீட்டமைக்கவும்", "Reset view": "பார்வையை மீட்டமைக்கவும்", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 ஆதாரம் மீட்டெடுக்கப்பட்டது", "Rich Text Input for Chat": "அரட்டைக்கான சிறந்த உரை உள்ளீடு", "Role": "பங்கு", + "Roles Claim": "", "RTL": "RTL", "Run": "ஓடவும்", "Run All": "அனைத்தையும் இயக்கவும்", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "உங்கள் உலாவியின் சேமிப்பகத்தில் நேரடியாக அரட்டைப் பதிவுகளைச் சேமிப்பது இனி ஆதரிக்கப்படாது. கீழே உள்ள பொத்தானைக் கிளிக் செய்வதன் மூலம் உங்கள் அரட்டை பதிவுகளை பதிவிறக்கம் செய்து நீக்க சிறிது நேரம் ஒதுக்குங்கள். கவலைப்பட வேண்டாம், உங்கள் அரட்டை பதிவுகளை பின்தளத்தில் எளிதாக மீண்டும் இறக்குமதி செய்யலாம்", "Schedule": "அட்டவணை", "Scheduled time must be in the future": "திட்டமிட்ட நேரம் எதிர்காலத்தில் இருக்க வேண்டும்", + "Scopes": "", "Scroll On Branch Change": "கிளை மாற்றத்தில் உருட்டவும்", "Scroll to Top": "", "Search": "தேடு", "Search a model": "ஒரு மாதிரியைத் தேடுங்கள்", + "Search actions": "", "Search all emojis": "எல்லா எமோஜிகளையும் தேடுங்கள்", "Search and manage user memories": "பயனர் நினைவுகளைத் தேடி நிர்வகிக்கவும்", "Search and view user chat history": "பயனர் அரட்டை வரலாற்றைத் தேடிப் பார்க்கலாம்", @@ -1798,6 +1940,7 @@ "Search Chats": "அரட்டைகளைத் தேடுங்கள்", "Search Collection": "தேடல் சேகரிப்பு", "Search Files": "கோப்புகளைத் தேடுங்கள்", + "Search filters": "", "Search Filters": "தேடல் வடிப்பான்கள்", "search for archived chats": "காப்பகப்படுத்தப்பட்ட அரட்டைகளைத் தேடுங்கள்", "search for folders": "கோப்புறைகளைத் தேடுங்கள்", @@ -1812,13 +1955,16 @@ "Search Models": "தேடல் மாதிரிகள்", "Search Notes": "குறிப்புகளைத் தேடுங்கள்", "Search options": "தேடல் விருப்பங்கள்", + "Search or add pattern": "", "Search Prompts": "தேடல் தூண்டுதல்கள்", "Search Result Count": "தேடல் முடிவுகளின் எண்ணிக்கை", + "Search skills": "", "Search Skills": "தேடல் திறன்கள்", - "Search skills...": "", "Search the internet": "இணையத்தில் தேடுங்கள்", "Search the web and fetch URLs": "இணையத்தில் தேடி URLகளைப் பெறவும்", + "Search tools": "", "Search Tools": "தேடல் கருவிகள்", + "Search users or groups": "", "Search, view, and manage user notes": "பயனர் குறிப்புகளைத் தேடவும், பார்க்கவும் மற்றும் நிர்வகிக்கவும்", "SearchApi API Key": "SearchApi API விசை", "SearchApi Engine": "SearchApi இன்ஜின்", @@ -1834,7 +1980,6 @@ "Seed": "விதை", "Select": "தேர்ந்தெடு", "Select {{modelName}} model": "{{modelName}} மாதிரியைத் தேர்ந்தெடுக்கவும்", - "Select a base model": "அடிப்படை மாதிரியைத் தேர்ந்தெடுக்கவும்", "Select a base model (e.g. llama3, gpt-4o)": "அடிப்படை மாதிரியைத் தேர்ந்தெடுக்கவும் (எ.கா. llama3, gpt-4o)", "Select a conversation to preview": "முன்னோட்டத்திற்கு உரையாடலைத் தேர்ந்தெடுக்கவும்", "Select a engine": "ஒரு இயந்திரத்தைத் தேர்ந்தெடுக்கவும்", @@ -1872,18 +2017,25 @@ "semantic": "சொற்பொருள்", "Send": "அனுப்பு", "Send a Message": "ஒரு செய்தியை அனுப்பு", + "Send events for": "", "Send message": "செய்தி அனுப்பு", "Send now": "இப்போது அனுப்பு", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "கோரிக்கையில் `stream_options: { include_usage: true }` ஐ அனுப்புகிறது.\nஅமைக்கப்படும் போது ஆதரிக்கப்படும் வழங்குநர்கள் பதிலில் டோக்கன் பயன்பாட்டுத் தகவலைத் தருவார்கள்.", "September": "செப்டம்பர்", "SerpApi API Key": "SerpApi API விசை", "SerpApi Engine": "SerpApi இன்ஜின்", "Serper API Key": "Serper API விசை", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API விசை", "Serpstack API Key": "Serpstack API விசை", "Server connection failed": "சேவையக இணைப்பு தோல்வியடைந்தது", "Server connection verified": "சேவையக இணைப்பு சரிபார்க்கப்பட்டது", + "Service Account": "", "Session": "அமர்வு", + "Session expired. Please sign in again.": "", "Set as default": "இயல்புநிலையாக அமைக்கவும்", "Set as Production": "தயாரிப்பாக அமைக்கவும்", "Set embedding model": "உட்பொதித்தல் மாதிரியை அமைக்கவும்", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "பகிர்வு இணைப்பு கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது.", "Share to Open WebUI Community": "Open WebUI சமூகத்தில் பகிரவும்", "Share your background and interests": "உங்கள் பின்னணி மற்றும் ஆர்வங்களைப் பகிரவும்", + "Shared": "", "Shared Chats": "பகிரப்பட்ட அரட்டைகள்", "Shared with you": "உங்களுடன் பகிரப்பட்டது", "Sharing Permissions": "பகிர்தல் அனுமதிகள்", "Show": "காட்டு", - "Show \"What's New\" modal on login": "உள்நுழையும்போது \"புதிது என்ன\" மாதிரியைக் காட்டு", + "Show \"What's New\" Modal on Login": "உள்நுழையும்போது \"புதிது என்ன\" மாதிரியைக் காட்டு", "Show Admin Details in Account Pending Overlay": "கணக்கு நிலுவையில் உள்ள மேலோட்டத்தில் நிர்வாகி விவரங்களைக் காட்டு", "Show All": "அனைத்தையும் காட்டு", "Show all ({{COUNT}} characters)": "அனைத்தையும் காட்டு ({{COUNT}} எழுத்துகள்)", "Show Files": "கோப்புகளைக் காட்டு", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "வடிவமைத்தல் கருவிப்பட்டியைக் காட்டு", "Show image preview": "படத்தின் முன்னோட்டத்தைக் காட்டு", "Show Model": "மாதிரியைக் காட்டு", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou தேடல் API sID", "Sougou Search API SK": "Sougou தேடல் API SK", "Source": "ஆதாரம்", + "Specific users or groups": "", "Speech Playback Speed": "பேச்சு பின்னணி வேகம்", "Speech recognition error: {{error}}": "பேச்சு அறிதல் பிழை: {{error}}", "Speech-to-Text": "பேச்சுக்கு உரை", @@ -1999,6 +2154,7 @@ "STT Settings": "STT அமைப்புகள்", "Stylized PDF Export": "பகட்டான PDF ஏற்றுமதி", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "கேள்வியை சமர்ப்பிக்கவும்", "Submit suggestion": "பரிந்துரையைச் சமர்ப்பிக்கவும்", "Subtitle": "வசனம்", @@ -2023,8 +2179,10 @@ "Syncing...": "ஒத்திசைக்கிறது...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "உங்கள் கடைசி ஒத்திசைவு நேர முத்திரைக்குப் பிறகு புதுப்பிப்புகளுடன் அரட்டைகளை மட்டுமே ஒத்திசைக்கிறது. அனைத்து அரட்டைகளையும் மீண்டும் ஒத்திசைக்க முடக்கவும்.", "System": "அமைப்பு", + "System events only": "", "System Instructions": "கணினி வழிமுறைகள்", "System Prompt": "சிஸ்டம் ப்ராம்ட்", + "Table": "", "Tag": "குறிச்சொல்", "Tags": "குறிச்சொற்கள்", "Tags Generation": "குறிச்சொற்கள் தலைமுறை", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "இயல்பாகவே தற்காலிக அரட்டை", "Terminal": "முனையம்", "Terminal servers saved": "டெர்மினல் சர்வர்கள் சேமிக்கப்பட்டன", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "உரை பிரிப்பான்", "Text-to-Speech": "உரையிலிருந்து பேச்சு", "Text-to-Speech Engine": "உரையிலிருந்து பேச்சு இயந்திரம்", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "உள்ளீட்டு ஆடியோவின் மொழி. உள்ளீட்டு மொழியை ISO-639-1 (எ.கா. en) வடிவத்தில் வழங்குவது துல்லியம் மற்றும் தாமதத்தை மேம்படுத்தும். மொழியைத் தானாகக் கண்டறிய காலியாக விடவும்.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP பண்புக்கூறு பயனர்கள் உள்நுழைவதற்குப் பயன்படுத்தும் மின்னஞ்சலை வரைபடமாக்குகிறது.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP பண்புக்கூறு பயனர்கள் உள்நுழைவதற்குப் பயன்படுத்தும் பயனர்பெயரை வரைபடமாக்குகிறது.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "லீடர்போர்டு தற்போது பீட்டாவில் உள்ளது, மேலும் அல்காரிதத்தைச் செம்மைப்படுத்தும்போது மதிப்பீடு கணக்கீடுகளைச் சரிசெய்யலாம்.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "MB இல் அதிகபட்ச கோப்பு அளவு. கோப்பின் அளவு இந்த வரம்பை மீறினால், கோப்பு பதிவேற்றப்படாது.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "அரட்டையில் ஒரே நேரத்தில் பயன்படுத்தக்கூடிய அதிகபட்ச கோப்புகள். கோப்புகளின் எண்ணிக்கை இந்த வரம்பை மீறினால், கோப்புகள் பதிவேற்றப்படாது.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "உரைக்கான வெளியீட்டு வடிவம். 'json', 'markdown' அல்லது 'html' ஆக இருக்கலாம். இயல்புநிலை 'மார்க் டவுன்'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "இந்தக் கோப்புறை காலியாக உள்ளது", "This is a default user permission and will remain enabled.": "இது இயல்புநிலை பயனர் அனுமதி மற்றும் இயக்கப்பட்டிருக்கும்.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "இது ஒரு சோதனை அம்சமாகும், இது எதிர்பார்த்தபடி செயல்படாமல் இருக்கலாம் மற்றும் எந்த நேரத்திலும் மாற்றத்திற்கு உட்பட்டது.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "இந்த மாதிரி பொதுவில் கிடைக்கவில்லை. தயவுசெய்து வேறு மாதிரியைத் தேர்ந்தெடுக்கவும்.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "கோரிக்கையைத் தொடர்ந்து மாடல் எவ்வளவு நேரம் நினைவகத்தில் ஏற்றப்படும் என்பதை இந்த விருப்பம் கட்டுப்படுத்துகிறது (இயல்புநிலை: 5 மீ)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "சூழலைப் புதுப்பிக்கும்போது எத்தனை டோக்கன்கள் பாதுகாக்கப்படுகின்றன என்பதை இந்த விருப்பம் கட்டுப்படுத்துகிறது. எடுத்துக்காட்டாக, 2 என அமைக்கப்பட்டால், உரையாடல் சூழலின் கடைசி 2 டோக்கன்கள் தக்கவைக்கப்படும். சூழலைப் பாதுகாப்பது உரையாடலின் தொடர்ச்சியைப் பராமரிக்க உதவும், ஆனால் புதிய தலைப்புகளுக்கு பதிலளிக்கும் திறனைக் குறைக்கலாம்.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "கிடைக்கக்கூடிய இறுதிப்புள்ளிகளைப் பற்றி மேலும் அறிய, எங்கள் ஆவணங்களைப் பார்வையிடவும்.", "To select skills here, add them to the \"Skills\" workspace first.": "இங்கே திறன்களைத் தேர்ந்தெடுக்க, முதலில் அவற்றை \"திறன்கள்\" பணியிடத்தில் சேர்க்கவும்.", "To select toolkits here, add them to the \"Tools\" workspace first.": "இங்கே கருவித்தொகுப்புகளைத் தேர்ந்தெடுக்க, முதலில் அவற்றை \"கருவிகள்\" பணியிடத்தில் சேர்க்கவும்.", - "Toast notifications for new updates": "புதிய புதுப்பிப்புகளுக்கான டோஸ்ட் அறிவிப்புகள்", + "Toast Notifications for New Updates": "புதிய புதுப்பிப்புகளுக்கான டோஸ்ட் அறிவிப்புகள்", "Today": "இன்று", "Today at": "இன்று", "Today at {{LOCALIZED_TIME}}": "இன்று {{LOCALIZED_TIME}} இல்", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "தற்போதைய இணைப்பு செயலில் உள்ளதா என்பதை மாற்றவும்.", "Token": "டோக்கன்", "Token counts are estimates and may not reflect actual API usage": "டோக்கன் எண்ணிக்கைகள் மதிப்பீடுகள் மற்றும் உண்மையான API பயன்பாட்டைப் பிரதிபலிக்காமல் இருக்கலாம்", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "டோக்கன்கள்", "Tokens": "டோக்கன்கள்", "Too verbose": "மிகவும் வாய்மொழி", @@ -2184,14 +2350,19 @@ "Unpin": "அன்பின்", "Unpin from Sidebar": "", "Unravel secrets": "இரகசியங்களை அவிழ்த்து விடுங்கள்", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "அரட்டையைப் பகிர்வதை நீக்கு", "Unsupported file type.": "ஆதரிக்கப்படாத கோப்பு வகை.", "Untagged": "குறியிடப்படாதது", "Untitled": "பெயரிடப்படாதது", "Update": "புதுப்பி", "Update and Copy Link": "இணைப்பைப் புதுப்பித்து நகலெடுக்கவும்", + "Update Email": "", "Update for the latest features and improvements.": "சமீபத்திய அம்சங்கள் மற்றும் மேம்பாடுகளுக்குப் புதுப்பிக்கவும்.", + "Update Name": "", "Update password": "கடவுச்சொல்லை புதுப்பிக்கவும்", + "Update Picture": "", "Update your status": "உங்கள் நிலையைப் புதுப்பிக்கவும்", "Updated": "புதுப்பிக்கப்பட்டது", "Updated at": "இல் புதுப்பிக்கப்பட்டது", @@ -2218,13 +2389,18 @@ "Use": "பயன்படுத்தவும்", "Use '#' in the prompt input to load and include your knowledge.": "உங்கள் அறிவை ஏற்ற மற்றும் சேர்க்க, உடனடி உள்ளீட்டில் '#' ஐப் பயன்படுத்தவும்.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "சிறந்த துல்லியத்திற்கு /v1/audio/transscriptions க்குப் பதிலாக /v1/chat/completions இறுதிப்புள்ளியைப் பயன்படுத்தவும்.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "அரட்டை நிறைவுகளைப் பயன்படுத்தவும் API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "உங்கள் பயனர்களை ஒழுங்கமைக்கவும் அனுமதிகளை வழங்கவும் குழுக்களைப் பயன்படுத்தவும்.", "Use LLM": "LLM ஐப் பயன்படுத்தவும்", "Use no proxy to fetch page contents.": "பக்க உள்ளடக்கங்களைப் பெற ப்ராக்ஸியைப் பயன்படுத்த வேண்டாம்.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "பக்க உள்ளடக்கங்களைப் பெற, http_proxy மற்றும் https_proxy சூழல் மாறிகளால் நியமிக்கப்பட்ட ப்ராக்ஸியைப் பயன்படுத்தவும்.", + "Use Web Search?": "", "user": "பயனர்", "User": "பயனர்", + "User Access": "", "User Activity": "பயனர் செயல்பாடு", "User Groups": "பயனர் குழுக்கள்", "User location successfully retrieved.": "பயனர் இருப்பிடம் வெற்றிகரமாக மீட்டெடுக்கப்பட்டது.", @@ -2234,6 +2410,7 @@ "User Status": "பயனர் நிலை", "User Webhooks": "பயனர் வெப்ஹூக்குகள்", "Username": "பயனர் பெயர்", + "Username Claim": "", "users": "பயனர்கள்", "Users": "பயனர்கள்", "Uses DefaultAzureCredential to authenticate": "அங்கீகரிக்க DefaultAzureCredential ஐப் பயன்படுத்துகிறது", @@ -2247,6 +2424,7 @@ "Valves updated": "வால்வுகள் புதுப்பிக்கப்பட்டன", "Valves updated successfully": "வால்வுகள் வெற்றிகரமாக புதுப்பிக்கப்பட்டன", "variable": "மாறி", + "Vector Field": "", "Verify Connection": "இணைப்பைச் சரிபார்க்கவும்", "Verify SSL Certificate": "SSL சான்றிதழைச் சரிபார்க்கவும்", "Version": "பதிப்பு", @@ -2276,11 +2454,14 @@ "Web API": "வலை API", "Web Loader Engine": "வலை ஏற்றி இயந்திரம்", "Web Search": "இணைய தேடல்", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "இணைய தேடுபொறி", "Web Search in Chat": "அரட்டையில் இணையத் தேடல்", "Web Search Query Generation": "இணைய தேடல் வினவல் உருவாக்கம்", + "Webhook deleted": "", "Webhook Name": "வெப்ஹூக் பெயர்", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "வெப்ஹூக்ஸ்", "Webpage URLs": "வலைப்பக்க URLகள்", "WebUI Settings": "WebUI அமைப்புகள்", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex இணைய தேடல் API விசை", "Yandex Web Search config": "Yandex இணைய தேடல் கட்டமைப்பு", "Yandex Web Search URL": "Yandex இணைய தேடல் URL", + "Yearly": "", "Yesterday": "நேற்று", "Yesterday at {{LOCALIZED_TIME}}": "நேற்று {{LOCALIZED_TIME}} இல்", "You": "நீங்கள்", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "உங்கள் உலாவி வீடியோ குறிச்சொல்லை ஆதரிக்கவில்லை.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "உங்கள் முழு பங்களிப்பும் நேரடியாக செருகுநிரல் டெவலப்பரிடம் செல்லும்; Open WebUI எந்த சதவீதத்தையும் எடுக்காது. இருப்பினும், தேர்ந்தெடுக்கப்பட்ட நிதி தளம் அதன் சொந்த கட்டணங்களைக் கொண்டிருக்கலாம்.", "Your message text or inputs": "உங்கள் செய்தி உரை அல்லது உள்ளீடுகள்", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "உங்கள் பயன்பாட்டு புள்ளிவிவரங்கள் வெற்றிகரமாக ஒத்திசைக்கப்பட்டுள்ளன.", "YouTube": "YouTube", "Youtube Language": "Youtube மொழி", diff --git a/src/lib/i18n/locales/th-TH/translation.json b/src/lib/i18n/locales/th-TH/translation.json index de2e21db78..bb40186d82 100644 --- a/src/lib/i18n/locales/th-TH/translation.json +++ b/src/lib/i18n/locales/th-TH/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "{{COUNT}} บรรทัดที่ดึงออกมา", "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} บรรทัดที่ซ่อนอยู่", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "{{COUNT}} แหล่งที่มา", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} คำ", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} เมื่อ {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "การดาวน์โหลด {{model}} ถูกยกเลิกแล้ว", "{{modelName}} profile image": "", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "การแชทของ {{user}}", "{{webUIName}} Backend Required": "ต้องใช้ Backend ของ {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*ต้องระบุ ID ของ prompt node สำหรับการสร้างภาพ", + "1 group": "", "1 hour before": "", "1 Source": "1 แหล่งที่มา", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -54,6 +61,7 @@ "Access Control": "การควบคุมการเข้าถึง", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "เข้าถึงได้สำหรับผู้ใช้ทั้งหมด", "Account": "บัญชี", @@ -69,6 +77,7 @@ "Activity": "", "Add": "เพิ่ม", "Add a model ID": "เพิ่ม ID โมเดล", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "เพิ่มคำอธิบายสั้นๆ เกี่ยวกับสิ่งที่โมเดลนี้ทำ", "Add a tag": "เพิ่มแท็ก", "Add a tag...": "", @@ -81,8 +90,10 @@ "Add Custom Prompt": "เพิ่มพรอมต์ที่กำหนดเอง", "Add description": "", "Add Details": "เพิ่มรายละเอียด", + "Add durable context for future chats": "", "Add Files": "เพิ่มไฟล์", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -97,6 +108,7 @@ "Add to favorites": "", "Add User": "เพิ่มผู้ใช้", "Add User Group": "เพิ่มกลุ่มผู้ใช้", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "การกำหนดค่าเพิ่มเติม", @@ -109,7 +121,9 @@ "Admin": "ผู้ดูแลระบบ", "Admin Contact Email": "", "Admin Panel": "แผงผู้ดูแลระบบ", + "Admin Roles": "", "Admin Settings": "การตั้งค่าผู้ดูแลระบบ", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "ผู้ดูแลระบบสามารถเข้าถึงเครื่องมือทั้งหมดได้ตลอดเวลา ส่วนผู้ใช้ต้องได้รับการกำหนดเครื่องมือต่อโมเดลในแต่ละพื้นที่ทำงาน", "Advanced": "", "Advanced Parameters": "พารามิเตอร์ขั้นสูง", @@ -120,16 +134,21 @@ "All": "ทั้งหมด", "All chats have been unarchived.": "ยกเลิกการเก็บถาวรการแชททั้งหมดแล้ว", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "ลบโมเดลทั้งหมดเรียบร้อยแล้ว", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "อนุญาตให้โทร", "Allow Chat Controls": "อนุญาตการควบคุมแชท", "Allow Chat Delete": "อนุญาตให้ลบแชท", "Allow Chat Edit": "อนุญาตให้แก้ไขแชท", "Allow Chat Export": "อนุญาตให้ส่งออกแชท", + "Allow Chat Import": "", "Allow Chat Params": "อนุญาตพารามิเตอร์แชท", "Allow Chat Share": "อนุญาตให้แชร์แชท", "Allow Chat System Prompt": "อนุญาต System Prompt สำหรับแชท", @@ -149,9 +168,11 @@ "Allow User Location": "อนุญาตให้เข้าถึงตำแหน่งที่อยู่ของผู้ใช้", "Allow Voice Interruption in Call": "อนุญาตให้ขัดจังหวะด้วยเสียงระหว่างสาย", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Endpoints ที่อนุญาต", "Allowed File Extensions": "นามสกุลไฟล์ที่อนุญาต", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "นามสกุลไฟล์ที่อนุญาตให้อัปโหลด คั่นแต่ละนามสกุลด้วยเครื่องหมายจุลภาค เว้นว่างเพื่ออนุญาตไฟล์ทุกประเภท", + "Allowed Roles": "", "Already have an account?": "มีบัญชีอยู่แล้ว?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "ทางเลือกแทน top_p และมุ่งเน้นการสร้างสมดุลระหว่างคุณภาพและความหลากหลาย พารามิเตอร์ p แทนค่าความน่าจะเป็นต่ำสุดสำหรับโทเค็นที่จะถูกพิจารณา โดยอ้างอิงกับความน่าจะเป็นของโทเค็นที่มีโอกาสสูงที่สุด ตัวอย่างเช่น เมื่อ p=0.05 และโทเค็นที่มีโอกาสสูงที่สุดมีความน่าจะเป็น 0.9 logits ที่มีค่าน้อยกว่า 0.045 จะถูกกรองออก", "Always": "เสมอ", @@ -170,6 +191,7 @@ "API Base URL": "URL พื้นฐานของ API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL พื้นฐานของ API สำหรับบริการ Datalab Marker ค่าเริ่มต้น: https://www.datalab.to/api/v1/marker", "API Key": "คีย์ API", + "API Key / Token": "", "API Key created.": "สร้างคีย์ API แล้ว", "API Key Endpoint Restrictions": "ข้อจำกัด Endpoint ของ API Key", "API keys": "คีย์ API", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "คุณแน่ใจหรือว่าต้องการลบข้อความนี้?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "คุณแน่ใจหรือว่าต้องการยกเลิกการเก็บถาวรแชททั้งหมด?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "โมเดลใน Arena", "Artifacts": "Artifacts", "Asc": "", "Ask": "ถาม", "Ask a question": "ถามคำถาม", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "ผู้ช่วย", "Async Embedding Processing": "", "At time of event": "", @@ -220,14 +247,20 @@ "Audio": "เสียง", "August": "สิงหาคม", "Auth": "การยืนยันตัวตน", + "Auth Mode": "", + "Auth required": "", "Authenticate": "ยืนยันตัวตน", "Authentication": "การยืนยันตัวตน", "Auto": "อัตโนมัติ", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "คัดลอกคำตอบไปยังคลิปบอร์ดโดยอัตโนมัติ", - "Auto-playback response": "การเล่นคำตอบอัตโนมัติ", + "Auto-Create Groups": "", + "Auto-Playback Response": "การเล่นคำตอบอัตโนมัติ", "Autocomplete Generation": "การเติมข้อความอัตโนมัติ", "Autocomplete Generation Input Max Length": "ความยาวสูงสุดของอินพุตการสร้างข้อความอัตโนมัติ", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "สตริงการตรวจสอบสิทธิ์ API ของ AUTOMATIC1111", "AUTOMATIC1111 Base URL": "URL พื้นฐานของ AUTOMATIC1111", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "เครื่องมือที่มีให้ใช้", "available users": "ผู้ใช้ที่มีอยู่", + "Available variables": "", "available!": "พร้อมใช้งาน!", "Away": "ไม่อยู่", "Awful": "แย่", @@ -255,16 +289,17 @@ "Bad Response": "การตอบกลับไม่ถูกต้อง", "Banners": "แบนเนอร์", "Base Model (From)": "โมเดลพื้นฐาน (จาก)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "การแคชรายการ Base Model ช่วยเร่งการเข้าถึงโดยดึงข้อมูลโมเดลเฉพาะตอนเริ่มต้นระบบหรือเมื่อบันทึกการตั้งค่า ซึ่งทำให้เร็วขึ้น แต่อาจไม่แสดงการเปลี่ยนแปลงโมเดลล่าสุด", "Bearer": "Bearer", "before": "ก่อน", "Being lazy": "ขี้เกียจ", - "Beta": "เบต้า", "Bing": "", "Bing Search V7 Endpoint": "Endpoint ของ Bing Search V7", "Bing Search V7 Subscription Key": "Subscription Key ของ Bing Search V7", "Bio": "ประวัติส่วนตัว", "Birth Date": "วันเกิด", + "Blocked Groups": "", "BM25 Weight": "น้ำหนัก BM25", "Bocha Search API Key": "API Key ของ Bocha Search", "Bold": "ตัวหนา", @@ -321,7 +356,7 @@ "Chat Completions": "", "Chat Conversation": "การสนทนาแชท", "Chat deleted.": "", - "Chat direction": "ทิศทางแชท", + "Chat Direction": "ทิศทางแชท", "Chat exported successfully": "", "Chat History": "", "Chat ID": "ID การแชท", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "", "Collapse": "ยุบ", "Collection": "คอลเลกชัน", + "Collection Field": "", "Collections": "", "Color": "สี", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "เวิร์กโฟลว์ ComfyUI", "ComfyUI Workflow Nodes": "โหนดเวิร์กโฟลว์ ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID โหนดคั่นด้วยจุลภาค (เช่น 1 หรือ 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "คำสั่ง", "Comment": "ความคิดเห็น", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "การเติมข้อความ", "Compress Images in Channels": "บีบอัดรูปภาพในช่อง", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "เชื่อมต่อกับ API Endpoint ที่เข้ากันได้กับ OpenAI ของคุณเอง", "Connect to your own OpenAPI compatible external tool servers.": "เชื่อมต่อกับเซิร์ฟเวอร์เครื่องมือภายนอกของคุณที่รองรับ OpenAPI", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "การเชื่อมต่อล้มเหลว", "Connection lost. Reconnecting...": "", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "ติดต่อผู้ดูแลระบบเพื่อขอสิทธิ์เข้าใช้ WebUI", "Content": "เนื้อหา", "Content Extraction Engine": "เอนจินดึงเนื้อหา", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ตอบต่อ", "Continue with {{provider}}": "ดำเนินการต่อด้วย {{provider}}", "Continue with Email": "ดำเนินการต่อด้วยอีเมล", @@ -489,6 +536,7 @@ "Create new secret key": "สร้างคีย์ลับใหม่", "Create note": "", "Create Note": "สร้างบันทึก", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "สร้างบันทึกแรกของคุณโดยคลิกที่ปุ่มบวกด้านล่าง", "Created at": "สร้างเมื่อ", @@ -506,6 +554,7 @@ "Custom Gender": "", "Custom Parameter Name": "ชื่อพารามิเตอร์แบบกำหนดเอง", "Custom Parameter Value": "ค่าพารามิเตอร์กำหนดเอง", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "เขตอันตราย", @@ -528,7 +577,6 @@ "Default Features": "ฟีเจอร์เริ่มต้น", "Default Filters": "ตัวกรองเริ่มต้น", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "โหมดเริ่มต้นทำงานร่วมกับโมเดลได้หลากหลายกว่า โดยเรียกใช้เครื่องมือหนึ่งครั้งก่อนการรันคำสั่ง ส่วนโหมด Native จะใช้ความสามารถในการเรียกใช้เครื่องมือที่มีอยู่ในตัวโมเดล แต่ต้องอาศัยว่าโมเดลรองรับฟีเจอร์นี้ในตัวอยู่แล้ว", "Default Model": "โมเดลค่าเริ่มต้น", "Default model updated": "อัปเดตโมเดลค่าเริ่มต้นแล้ว", "Default permissions": "สิทธิ์เริ่มต้น", @@ -538,6 +586,7 @@ "Default to ALL": "ค่าเริ่มต้นเป็นทั้งหมด", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "กำหนดค่าเริ่มต้นให้ใช้การดึงข้อมูลแบบแบ่งส่วนเพื่อการดึงเนื้อหาที่มีโฟกัสและเกี่ยวข้อง แนะนำให้ใช้ตัวเลือกนี้ในกรณีส่วนใหญ่", "Default User Role": "บทบาทผู้ใช้เริ่มต้น", + "Default webhook": "", "Defaults": "", "Delete": "ลบ", "Delete {{name}}": "", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "ปิดใช้งาน Code Interpreter", "Disable Image Extraction": "ปิดใช้งานการแยกรูปภาพ", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "ปิดใช้งานการดึงรูปภาพจากไฟล์ PDF หากเปิดใช้ Use LLM รูปภาพจะถูกสร้างคำบรรยายให้โดยอัตโนมัติ ค่าเริ่มต้นคือ False", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "ปิดใช้งาน", "Disconnect OAuth": "", "Discover a function": "ค้นพบฟังก์ชัน", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "ค้นหา ดาวน์โหลด และสำรวจพรีเซ็ตโมเดล", "Discussion channel where access is based on groups and permissions": "", "Display": "การแสดงผล", - "Display chat title in tab": "แสดงชื่อแชทในแท็บ", + "Display Chat Title in Tab": "แสดงชื่อแชทในแท็บ", "Display Emoji in Call": "แสดงอิโมจิระหว่างการโทร", "Display Multi-model Responses in Tabs": "แสดงคำตอบหลายโมเดลแบบแท็บ", - "Display the username instead of You in the Chat": "แสดงชื่อผู้ใช้แทนคำว่า \"คุณ\" ในการแชท", + "Display the Username Instead of You in the Chat": "แสดงชื่อผู้ใช้แทนคำว่า \"คุณ\" ในการแชท", "Displays citations in the response": "แสดงการอ้างอิงในคำตอบ", "Displays status updates (e.g., web search progress) in the response": "แสดงการอัปเดตสถานะ (เช่น ความคืบหน้าการค้นเว็บ) ภายในคำตอบ", "Dive into knowledge": "เจาะลึกสู่ความรู้", @@ -626,6 +677,7 @@ "Docling Parameters": "", "Docling Server URL required.": "ต้องระบุ Docling Server URL", "Document": "เอกสาร", + "Document ID Field": "", "Document Intelligence": "เอกสารอัจฉริยะ", "Document Intelligence endpoint required.": "ต้องระบุ Endpoint ของ Document Intelligence", "Document Intelligence Model": "", @@ -681,12 +733,14 @@ "Edit Default Permissions": "แก้ไขสิทธิ์เริ่มต้น", "Edit Folder": "แก้ไขโฟลเดอร์", "Edit Image": "แก้ไขรูปภาพ", + "Edit Knowledge Connection": "", "Edit Last Message": "แก้ไขข้อความล่าสุด", "Edit Memory": "แก้ไขความจำ", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "แก้ไขผู้ใช้", "Edit User Group": "แก้ไขกลุ่มผู้ใช้", + "Edit webhook": "", "Edit workflow.json content": "แก้ไขเนื้อหา workflow.json", "edited": "แก้ไขแล้ว", "Edited": "แก้ไขแล้ว", @@ -695,6 +749,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "อีเมล", + "Email Claim": "", "Embark on adventures": "ออกผจญภัย", "Embedding": "Embedding", "Embedding Batch Size": "ขนาดชุดของ Embedding", @@ -703,6 +758,7 @@ "Embedding Model Engine": "เอ็นจินโมเดล Embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -710,22 +766,27 @@ "Enable Code Execution": "เปิดใช้งานการรันโค้ด", "Enable Code Interpreter": "เปิดใช้งาน Code Interpreter", "Enable Community Sharing": "เปิดใช้งานการแชร์ในชุมชน", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "เปิดใช้ Memory Locking (mlock) เพื่อป้องกันไม่ให้ข้อมูลโมเดลถูก Swap ออกจาก RAM ตัวเลือกนี้จะล็อกชุด Pages ที่โมเดลกำลังใช้งานให้อยู่ใน RAM ทำให้ไม่ถูก Swap ออกไปยังดิสก์ ซึ่งช่วยรักษาประสิทธิภาพด้วยการหลีกเลี่ยง Page Fault และทำให้เข้าถึงข้อมูลได้อย่างรวดเร็ว", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "เปิดใช้ Memory Mapping (mmap) เพื่อโหลดข้อมูลโมเดล ตัวเลือกนี้จะทำให้ระบบสามารถใช้พื้นที่ดิสก์เป็นส่วนขยายของ RAM โดยมองไฟล์บนดิสก์เสมือนว่าอยู่ใน RAM ซึ่งอาจช่วยเพิ่มประสิทธิภาพของโมเดลโดยทำให้เข้าถึงข้อมูลได้เร็วขึ้น อย่างไรก็ตาม อาจทำงานไม่ถูกต้องกับทุกระบบและอาจใช้พื้นที่ดิสก์ในปริมาณมาก", "Enable Message Queue": "", "Enable Message Rating": "เปิดใช้งานการให้คะแนนข้อความ", "Enable Mirostat sampling for controlling perplexity.": "เปิดใช้การสุ่มตัวอย่างแบบ Mirostat เพื่อควบคุม Perplexity", "Enable New Sign Ups": "เปิดใช้งานการสมัครใหม่", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "เปิดใช้งาน ปิดใช้งาน หรือปรับแต่ง Reasoning Tag ที่โมเดลใช้ได้ \"เปิดใช้งาน\" จะใช้แท็กเริ่มต้น \"ปิดใช้งาน\" จะปิด Reasoning Tag และ \"กำหนดเอง\" จะให้คุณระบุแท็กเริ่มต้นและสิ้นสุดของคุณเอง", "Enabled": "เปิดใช้งาน", "End Tag": "แท็กปิด", + "Endpoint": "", "Endpoint URL": "Endpoint URL", "Enforce Temporary Chat": "บังคับใช้แชทชั่วคราว", "Enhance": "เพิ่มประสิทธิภาพ", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "ตรวจสอบว่าไฟล์ CSV ของคุณมี 4 คอลัมน์ในลำดับนี้: ชื่อ, อีเมล, รหัสผ่าน, บทบาท", "Enter {{role}} message here": "ระบุข้อความของ {{role}} ที่นี่", - "Enter a detail about yourself for your LLMs to recall": "ระบุรายละเอียดเกี่ยวกับตัวคุณเพื่อให้ LLM ของคุณจดจำ", "Enter a title for the pending user info overlay. Leave empty for default.": "ป้อนชื่อสำหรับหน้าซ้อนข้อมูลผู้ใช้ที่กำลังรออยู่ เว้นว่างไว้เพื่อใช้ค่าเริ่มต้น", "Enter a watermark for the response. Leave empty for none.": "ป้อนลายน้ำสำหรับคำตอบ เว้นว่างหากไม่ต้องการ", "Enter additional headers in JSON format": "ป้อน Headers เพิ่มเติมในรูปแบบ JSON", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "ป้อนค่า Chunk Overlap", "Enter Chunk Size": "ใส่ขนาด Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "ป้อนคู่ \"token:bias_value\" ที่คั่นด้วยจุลภาค (ตัวอย่าง: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "ป้อนเนื้อหาสำหรับ Overlay ข้อมูลผู้ใช้ที่กำลังรออยู่ เว้นว่างไว้เพื่อใช้ค่าเริ่มต้น", "Enter coordinates (e.g. 51.505, -0.09)": "ป้อนพิกัด (เช่น 51.505, -0.09)", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "ป้อน Jupyter URL", "Enter Kagi Search API Key": "ใส่ Kagi Search API Key", "Enter Key Behavior": "การทำงานของปุ่ม Enter", + "Enter language": "", "Enter language codes": "ใส่รหัสภาษา", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "ป้อน URL ฐานของ Mistral API", "Enter Mistral API Key": "กรอก API Key ของ Mistral", @@ -800,6 +866,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "ป้อน URL พร็อกซี (เช่น https://user:password@host:port)", "Enter reasoning effort": "ป้อนระดับการใช้เหตุผล", + "Enter Redirect URI": "", "Enter Score": "ใส่คะแนน", "Enter SearchApi API Key": "ป้อน API Key ของ SearchApi", "Enter SearchApi Engine": "ป้อน SearchApi Engine", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "กรอก SerpApi API Key", "Enter SerpApi Engine": "ป้อนเอนจิน SerpApi", "Enter Serper API Key": "ใส่ API Key ของ Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "ใส่ API Key ของ Serply", "Enter Serpstack API Key": "ใส่ API Key ของ Serpstack", "Enter server host": "ป้อนโฮสต์ของเซิร์ฟเวอร์", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "ใส่ URL เซิร์ฟเวอร์ของ Tika", "Enter timeout in seconds": "ป้อนเวลา Timeout เป็นวินาที", "Enter to Send": "กด Enter เพื่อส่ง", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "ใส่ค่า Top K", "Enter Top K Reranker": "ป้อนค่า Top K ของ Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "ใส่ URL (เช่น http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "ข้อผิดพลาด: มีโมเดลที่ใช้ ID '{{modelId}}' อยู่แล้ว โปรดเลือก ID อื่นเพื่อดำเนินการต่อ", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "ข้อผิดพลาด: ห้ามปล่อย ID โมเดลว่างไว้ กรุณากรอก ID ที่ถูกต้องเพื่อดำเนินการต่อ", "Evaluations": "การประเมิน", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "API Key ของ Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "ตัวอย่าง: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "ตัวอย่าง: ทั้งหมด", "Example: mail": "ตัวอย่าง: mail", @@ -901,12 +975,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "ส่งออกเป็น CSV", "Export Tools": "", "Export Users": "ส่งออกผู้ใช้", "External": "ภายนอก", + "External connection not found.": "", "External Document Loader URL required.": "จำเป็นต้องระบุ External Document Loader URL", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "โมเดลงานภายนอก", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "คีย์ API ของ External Web Loader", "External Web Loader URL": "URL ตัวโหลดเว็บภายนอก", "External Web Search API Key": "API Key สำหรับ External Web Search", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "สร้าง API Key ล้มเหลว", "Failed to delete calendar": "", "Failed to delete note": "ลบบันทึกไม่สำเร็จ", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "ไม่สามารถดึงเนื้อหาจากไฟล์ได้: {{error}}", @@ -931,6 +1012,7 @@ "Failed to fetch models": "ดึงโมเดลไม่สำเร็จ", "Failed to generate title": "สร้างชื่อไม่สำเร็จ", "Failed to import models": "นำเข้าโมเดลไม่สำเร็จ", + "Failed to load chat": "", "Failed to load chat preview": "ไม่สามารถโหลดตัวอย่างแชทได้", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -940,6 +1022,7 @@ "Failed to move chat": "ย้ายแชทไม่สำเร็จ", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "อ่านเนื้อหาคลิปบอร์ดไม่สำเร็จ", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "ไม่สามารถเรนเดอร์ไดอะแกรมได้", "Failed to render visualization": "ไม่สามารถเรนเดอร์ภาพข้อมูลได้", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "บันทึกการตั้งค่าโมเดลล้มเหลว", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "อัปเดตการตั้งค่าล้มเหลว", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "อัปโหลดไฟล์ไม่สำเร็จ", "Features": "ฟีเจอร์", "Features Permissions": "สิทธิ์การใช้งานฟีเจอร์", @@ -983,6 +1068,8 @@ "File uploaded successfully": "อัปโหลดไฟล์สำเร็จแล้ว", "Filename": "", "Files": "ไฟล์", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "กรอง", "Filter is now globally disabled": "การกรองถูกปิดใช้งานทั่วทั้งระบบแล้ว", "Filter is now globally enabled": "เปิดใช้งานตัวกรองในทุกส่วนแล้ว", @@ -1005,6 +1092,7 @@ "Folder options": "", "Folder updated successfully": "อัปเดตโฟลเดอร์สำเร็จแล้ว", "Folders": "โฟลเดอร์", + "Folders Sharing": "", "Follow up": "ติดตามต่อ", "Follow Up Generation": "การสร้างคำถามติดตาม", "Follow Up Generation Prompt": "พรอมต์สร้างคำถามติดตามผล", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "ฟังก์ชันถูกเปิดใช้งานในทุกส่วนแล้ว", "Function Name": "ชื่อฟังก์ชัน", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "อัปเดตฟังก์ชันสำเร็จ", "Functions": "ฟังก์ชัน", "Functions allow arbitrary code execution.": "ฟังก์ชันอนุญาตให้รันโค้ดได้อย่างอิสระ", @@ -1067,7 +1156,10 @@ "Gravatar": "Gravatar", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "สร้างกลุ่มสำเร็จแล้ว", "Group deleted successfully": "ลบกลุ่มสำเร็จแล้ว", "Group Description": "คำอธิบายกลุ่ม", @@ -1079,6 +1171,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "การตอบสนองแบบสั่น", + "Header variables": "", "Headers": "Headers", "Headers must be a valid JSON object": "Headers ต้องเป็นอ็อบเจ็กต์ JSON ที่ถูกต้อง", "Height": "ความสูง", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID ต้องไม่มีอักขระ \":\" หรือ \"|\"", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "อนุญาตฟอร์มใน Sandbox ของ iframe", "iframe Sandbox Allow Same Origin": "ให้ iframe Sandbox ใช้แหล่งที่มาเดียวกันได้", @@ -1134,6 +1229,7 @@ "Import From Link": "นำเข้าโดยใช้ลิงก์", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "นำเข้าเรียบร้อยแล้ว", "Import Tools": "", "Important Update": "อัปเดตสำคัญ", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "ปักหมุดไว้ที่แถบด้านข้าง", "Key": "คีย์", "Key is required": "ต้องระบุคีย์", - "Keyboard shortcuts": "ทางลัดแป้นพิมพ์", "Keyboard Shortcuts": "ปุ่มลัดแป้นพิมพ์", "Knowledge": "ความรู้", "Knowledge Access": "การเข้าถึงความรู้", @@ -1204,6 +1299,8 @@ "Knowledge Name": "ชื่อฐานความรู้", "Knowledge Public Sharing": "การแชร์ฐานความรู้สาธารณะ", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "อัปเดตฐานความรู้สำเร็จแล้ว", "Kokoro.js (Browser)": "Kokoro.js (เบราว์เซอร์)", "Kokoro.js Dtype": "ชนิดข้อมูล Kokoro.js", @@ -1220,7 +1317,6 @@ "Last ran": "", "Last reply": "คำตอบล่าสุด", "LDAP": "LDAP", - "LDAP server updated": "อัปเดตเซิร์ฟเวอร์ LDAP แล้ว", "Leaderboard": "กระดานผู้นำ", "Learn more": "", "Learn More": "เรียนรู้เพิ่มเติม", @@ -1242,6 +1338,7 @@ "Legacy": "เวอร์ชันเก่า", "lexical": "Lexical", "License": "ใบอนุญาต", + "Lifecycle JSON": "", "Lift List": "รายการลิฟต์", "Light": "โหมดสว่าง", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1265,6 +1362,7 @@ "Location access not allowed": "ไม่อนุญาตให้เข้าถึงตำแหน่งที่ตั้ง", "Lost": "หาย", "Low": "ต่ำ", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "ซ้ายไปขวา", "Made by Open WebUI Community": "สร้างโดยชุมชน Open WebUI", "Make password visible in the user interface": "แสดงรหัสผ่านในส่วนติดต่อผู้ใช้", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "จัดการ Pipelines", "Manage Tool Servers": "จัดการเซิร์ฟเวอร์เครื่องมือ", "Manage your account information.": "จัดการข้อมูลบัญชีของคุณ", + "Mapped Source": "", "March": "มีนาคม", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "ล้างความจำสำเร็จแล้ว", "Memory deleted successfully": "ลบความจำสำเร็จ", "Memory updated successfully": "อัปเดตความจำสำเร็จแล้ว", + "Merge Accounts by Email": "", "Merge Responses": "รวมคำตอบ", "Merged Response": "การตอบกลับที่รวมกัน", "Message": "ข้อความ", @@ -1318,9 +1418,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ข้อความที่คุณส่งหลังจากสร้างลิงก์แล้วจะไม่ถูกแชร์ ผู้ใช้ที่มี URL จะสามารถดูแชทที่แชร์ได้", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (ส่วนบุคคล)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (ที่ทำงาน/โรงเรียน)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "ต้องใช้ MinerU API Key สำหรับโหมด Cloud API", @@ -1373,6 +1476,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "API Key สำหรับ Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "เพิ่มเติม", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "ตั้งชื่อฐานความรู้ของคุณ", "Name, prompt, and model are required": "", "Native": "Native", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1419,6 +1524,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "ไม่ต้องยืนยันตัวตน", "No automations found": "", "No chats found": "ไม่พบแชท", @@ -1431,8 +1537,10 @@ "No data": "", "No data found": "", "No distance available": "ไม่มีข้อมูลระยะทาง", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "ไม่มีวันหมดอายุอาจทำให้เกิดความเสี่ยงด้านความปลอดภัย", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "ไม่ได้เลือกไฟล์", "No files found": "", @@ -1460,6 +1568,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "ไม่พบพรอมต์", + "No Repeat": "", "No results": "ไม่มีผลลัพธ์", "No results found": "ไม่มีผลลัพธ์", "No search query generated": "ไม่มีการสร้างคำค้นหา", @@ -1479,6 +1588,7 @@ "No webhooks yet": "", "Node Ids": "รหัสโหนด", "None": "ไม่มี", + "Not configured": "", "Not factually correct": "ไม่ถูกต้องตามข้อเท็จจริง", "Not helpful": "ไม่เป็นประโยชน์", "Not Registered": "ยังไม่ได้ลงทะเบียน", @@ -1494,20 +1604,25 @@ "Notifications": "การแจ้งเตือน", "November": "พฤศจิกายน", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "ตุลาคม", "Off": "ปิด", "Okay, Let's Go!": "ตกลง ไปกันเลย!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "โหมดมืด OLED", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "อัปเดตการตั้งค่า Ollama API แล้ว", "Ollama Cloud API Key": "API Key ของ Ollama Cloud", "Ollama Version": "เวอร์ชัน Ollama", + "Omit": "", "On": "เปิด", "Once": "", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "รหัสผ่าน", "Passwords do not match.": "รหัสผ่านไม่ตรงกัน", "Paste Large Text as File": "วางข้อความขนาดใหญ่เป็นไฟล์", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "เอกสาร PDF (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "รอดำเนินการ", "Pending": "กำลังรอ", + "Pending Accounts": "", "Pending User Overlay Content": "เนื้อหาซ้อนทับผู้ใช้ที่รอดำเนินการ", "Pending User Overlay Title": "ชื่อหน้าซ้อนผู้ใช้ที่รอดำเนินการ", "Permission denied when accessing media devices": "ไม่ได้รับอนุญาตให้เข้าถึงอุปกรณ์สื่อ", "Permission denied when accessing microphone": "ถูกปฏิเสธสิทธิ์ในการเข้าถึงไมโครโฟน", "Permission denied when accessing microphone: {{error}}": "ไม่ได้รับอนุญาตให้เข้าถึงไมโครโฟน: {{error}}", "Permissions": "สิทธิ์", + "Permissions reset to defaults": "", "Perplexity API Key": "API Key ของ Perplexity", "Perplexity Model": "โมเดล Perplexity", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "การใช้บริบทการค้นหา Perplexity", "Persistent": "", "Personalization": "การปรับแต่ง", + "Picture Claim": "", "Pin": "ปักหมุด", "Pin to Sidebar": "", "Pinned": "ปักหมุดแล้ว", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "โปรดกรอกข้อมูลให้ครบทุกช่อง", "Please register the OAuth client": "โปรดลงทะเบียน OAuth Client", "Please save the connection to persist the OAuth client information and do not change the ID": "โปรดบันทึกการเชื่อมต่อเพื่อคงข้อมูล OAuth Client และอย่าเปลี่ยนแปลง ID", - "Please select a model first.": "โปรดเลือกโมเดลก่อน", "Please select a model.": "โปรดเลือกโมเดล", "Please select a reason": "โปรดเลือกเหตุผล", "Please select a valid JSON file": "โปรดเลือกไฟล์ JSON ที่ถูกต้อง", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "โปรดรอจนกว่าไฟล์ทั้งหมดจะอัปโหลดเสร็จสิ้น", "Policy ID": "", + "Policy ID is required": "", "Port": "พอร์ต", "Ports": "", "Positive attitude": "ทัศนคติเชิงบวก", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "การแชร์พรอมต์สาธารณะ", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "สาธารณะ", "Pull \"{{searchValue}}\" from Ollama.com": "ดึง \"{{searchValue}}\" จาก Ollama.com", "Pull a model from Ollama.com": "ดึงโมเดลจาก Ollama.com", @@ -1683,21 +1804,28 @@ "Read": "อ่าน", "Read Aloud": "อ่านออกเสียง", "Read more →": "อ่านเพิ่มเติม →", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "เหตุผล", "Reasoning Effort": "ระดับการใช้เหตุผล", "Reasoning Tags": "ป้ายกำกับการให้เหตุผล", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "บันทึก", "Record voice": "บันทึกเสียง", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "กำลังเปลี่ยนเส้นทางคุณไปยังชุมชน Open WebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "ลดโอกาสในการสร้างข้อความที่ไม่มีความหมาย ค่าให้สูงขึ้น (เช่น 100) จะทำให้ได้คำตอบที่หลากหลายมากขึ้น ในขณะที่ค่าให้ต่ำลง (เช่น 10) จะทำให้คำตอบระมัดระวังมากขึ้น", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "เรียกตัวเองว่า \"User\" (เช่น \"User กำลังเรียนภาษาสเปน\")", "Reference Chats": "การแชทอ้างอิง", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "ปฏิเสธเมื่อไม่ควรปฏิเสธ", "Regenerate": "สร้างใหม่", "Regenerate Menu": "สร้างเมนูใหม่", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "จัดลำดับโมเดลใหม่", + "Repeat": "", "Repeats": "", "Reply": "ตอบกลับ", "Reply in Thread": "ตอบกลับในเธรด", "Reply to thread...": "ตอบกลับเธรด...", "Replying to {{NAME}}": "กำลังตอบกลับ {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "จำเป็น", "Reranking Batch Size": "", "Reranking Engine": "เอนจิน Reranking", "Reranking Model": "โมเดล Reranking", + "Research Knowledge": "", "Reset": "รีเซ็ต", "Reset All Models": "รีเซ็ตโมเดลทั้งหมด", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "รีเซ็ตภาพ", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "รีเซ็ตไดเรกทอรีการอัปโหลด", "Reset Vector Storage/Knowledge": "รีเซ็ตที่เก็บเวกเตอร์/ฐานความรู้", "Reset view": "รีเซ็ตมุมมอง", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "ดึงมาแล้ว 1 แหล่งข้อมูล", "Rich Text Input for Chat": "ช่องป้อนข้อความแบบ Rich Text สำหรับแชท", "Role": "บทบาท", + "Roles Claim": "", "RTL": "ขวาไปซ้าย", "Run": "เรียกใช้", "Run All": "", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "การบันทึก Log การแชทโดยตรงไปยังที่จัดเก็บของเบราว์เซอร์ไม่รองรับอีกต่อไป โปรดสละเวลาสักครู่เพื่อดาวน์โหลดและลบบันทึกการแชทของคุณโดยคลิกปุ่มด้านล่าง ไม่ต้องกังวล คุณสามารถนำเข้าบันทึกการแชทของคุณกลับไปยัง Backend ได้อย่างง่ายดายผ่าน", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "เลื่อนเมื่อเปลี่ยนสาขา", "Scroll to Top": "", "Search": "ค้นหา", "Search a model": "ค้นหาโมเดล", + "Search actions": "", "Search all emojis": "ค้นหาอีโมจิทั้งหมด", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1792,6 +1930,7 @@ "Search Chats": "ค้นหาแชท", "Search Collection": "ค้นหาคอลเลกชัน", "Search Files": "", + "Search filters": "", "Search Filters": "ตัวกรองการค้นหา", "search for archived chats": "ค้นหาการแชทที่เก็บถาวร", "search for folders": "ค้นหาโฟลเดอร์", @@ -1806,13 +1945,16 @@ "Search Models": "ค้นหาโมเดล", "Search Notes": "ค้นหาบันทึก", "Search options": "ตัวเลือกการค้นหา", + "Search or add pattern": "", "Search Prompts": "ค้นหาพรอมต์", "Search Result Count": "จำนวนผลลัพธ์การค้นหา", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "ค้นหาบนอินเทอร์เน็ต", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "เครื่องมือค้นหา", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "API Key ของ SearchApi", "SearchApi Engine": "เอนจินของ SearchApi", @@ -1828,7 +1970,6 @@ "Seed": "Seed", "Select": "เลือก", "Select {{modelName}} model": "", - "Select a base model": "เลือกโมเดลฐาน", "Select a base model (e.g. llama3, gpt-4o)": "เลือกโมเดลพื้นฐาน (เช่น llama3, gpt-4o)", "Select a conversation to preview": "เลือกการสนทนาเพื่อดูตัวอย่าง", "Select a engine": "เลือกเอนจิน", @@ -1866,18 +2007,25 @@ "semantic": "Semantic", "Send": "ส่ง", "Send a Message": "ส่งข้อความ", + "Send events for": "", "Send message": "ส่งข้อความ", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "ส่ง `stream_options: { include_usage: true }` ในคำขอ\nผู้ให้บริการที่รองรับจะส่งคืนข้อมูลการใช้โทเค็นในข้อมูลตอบกลับเมื่อมีการตั้งค่านี้", "September": "กันยายน", "SerpApi API Key": "API Key ของ SerpApi", "SerpApi Engine": "เอนจิน SerpApi", "Serper API Key": "คีย์ API ของ Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "คีย์ API ของ Serply", "Serpstack API Key": "คีย์ API ของ Serpstack", "Server connection failed": "", "Server connection verified": "ยืนยันการเชื่อมต่อเซิร์ฟเวอร์แล้ว", + "Service Account": "", "Session": "Session", + "Session expired. Please sign in again.": "", "Set as default": "ตั้งเป็นค่าเริ่มต้น", "Set as Production": "", "Set embedding model": "ตั้งค่าโมเดล Embedding", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "แชร์ไปยังชุมชน Open WebUI", "Share your background and interests": "เล่าพื้นเพและความสนใจของคุณ", + "Shared": "", "Shared Chats": "", "Shared with you": "แชร์กับคุณ", "Sharing Permissions": "สิทธิ์การแชร์", "Show": "แสดง", - "Show \"What's New\" modal on login": "แสดงหน้าต่าง \"มีอะไรใหม่\" เมื่อเข้าสู่ระบบ", + "Show \"What's New\" Modal on Login": "แสดงหน้าต่าง \"มีอะไรใหม่\" เมื่อเข้าสู่ระบบ", "Show Admin Details in Account Pending Overlay": "แสดงรายละเอียดผู้ดูแลระบบในหน้าต่างซ้อนรอการอนุมัติบัญชี", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "แสดงแถบเครื่องมือการจัดรูปแบบ", "Show image preview": "แสดงตัวอย่างรูปภาพ", "Show Model": "แสดงโมเดล", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "sID ของ Sougou Search API", "Sougou Search API SK": "Sougou Search API SK", "Source": "แหล่งที่มา", + "Specific users or groups": "", "Speech Playback Speed": "ความเร็วการเล่นเสียงพูด", "Speech recognition error: {{error}}": "ข้อผิดพลาดในการรู้จำเสียง: {{error}}", "Speech-to-Text": "แปลงเสียงเป็นข้อความ", @@ -1992,6 +2143,7 @@ "STT Settings": "การตั้งค่าแปลงเสียงเป็นข้อความ", "Stylized PDF Export": "ส่งออก PDF แบบมีสไตล์", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2016,8 +2168,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "ระบบ", + "System events only": "", "System Instructions": "คำสั่งของระบบ", "System Prompt": "System Prompt", + "Table": "", "Tag": "แท็ก", "Tags": "แท็ก", "Tags Generation": "การสร้างแท็ก", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "ใช้แชทชั่วคราวเป็นค่าเริ่มต้น", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "ตัวแบ่งข้อความ", "Text-to-Speech": "แปลงข้อความเป็นเสียง", "Text-to-Speech Engine": "เครื่องมือแปลงข้อความเป็นเสียง", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "ภาษาของเสียงอินพุต การระบุภาษาของอินพุตในรูปแบบ ISO-639-1 (เช่น en) จะช่วยเพิ่มความแม่นยำและลดเวลาแฝง เว้นว่างไว้เพื่อให้ตรวจจับภาษาโดยอัตโนมัติ", "The LDAP attribute that maps to the mail that users use to sign in.": "แอตทริบิวต์ LDAP ที่แมปกับอีเมลที่ผู้ใช้ใช้เพื่อลงชื่อเข้าใช้", "The LDAP attribute that maps to the username that users use to sign in.": "แอตทริบิวต์ LDAP ที่แมปกับชื่อผู้ใช้ที่ผู้ใช้ใช้สำหรับลงชื่อเข้าใช้", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "กระดานจัดอันดับขณะนี้ยังเป็นเวอร์ชันทดสอบ (เบต้า) และเราอาจปรับวิธีคำนวณคะแนนจัดอันดับได้เมื่อปรับปรุงอัลกอริทึม", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "ขนาดไฟล์สูงสุดเป็นหน่วย MB หากขนาดไฟล์เกินค่าที่กำหนดนี้ ไฟล์จะไม่ถูกอัปโหลด", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "จำนวนไฟล์สูงสุดที่สามารถใช้ในการแชทได้พร้อมกัน หากจำนวนไฟล์เกินขีดจำกัดนี้ ไฟล์จะไม่ถูกอัปโหลด", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "รูปแบบผลลัพธ์สำหรับข้อความ อาจเป็น 'json', 'markdown' หรือ 'html' ค่าเริ่มต้นคือ 'markdown'", @@ -2075,6 +2234,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "นี่คือสิทธิ์ของผู้ใช้เริ่มต้นและจะถูกเปิดใช้งานไว้เสมอ", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "นี่เป็นฟีเจอร์ทดลอง อาจไม่ทำงานตามที่คาดไว้และอาจมีการเปลี่ยนแปลงได้ตลอดเวลา", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "โมเดลนี้ไม่เปิดให้ใช้งานสาธารณะ โปรดเลือกโมเดลอื่น", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "ตัวเลือกนี้ควบคุมระยะเวลาที่โมเดลจะถูกโหลดค้างอยู่ในหน่วยความจำหลังจากคำขอ (ค่าเริ่มต้น: 5 นาที)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "ตัวเลือกนี้ใช้กำหนดจำนวนโทเค็นที่จะถูกเก็บไว้เมื่อมีการรีเฟรชบริบท ยกตัวอย่างเช่น หากตั้งค่าเป็น 2 โทเค็น 2 ตัวสุดท้ายของบริบทการสนทนาจะถูกเก็บไว้ การเก็บรักษาบริบทสามารถช่วยให้การสนทนาต่อเนื่องมากขึ้น แต่อาจทำให้ความสามารถในการตอบสนองต่อหัวข้อใหม่ลดลง", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับ Endpoints ที่มีอยู่ โปรดดูที่เอกสารของเรา", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "ในการเลือกชุดเครื่องมือที่นี่ ให้เพิ่มไปยังพื้นที่ทำงาน \"Tools\" ก่อน", - "Toast notifications for new updates": "การแจ้งเตือนแบบ Toast สำหรับอัปเดตใหม่", + "Toast Notifications for New Updates": "การแจ้งเตือนแบบ Toast สำหรับอัปเดตใหม่", "Today": "วันนี้", "Today at": "", "Today at {{LOCALIZED_TIME}}": "วันนี้เวลา {{LOCALIZED_TIME}}", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "สลับการเปิดใช้งานการเชื่อมต่อปัจจุบัน", "Token": "โทเค็น", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "ละเอียดเกินไป", @@ -2177,14 +2339,19 @@ "Unpin": "ยกเลิกการปักหมุด", "Unpin from Sidebar": "", "Unravel secrets": "เปิดเผยความลับ", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "ไม่รองรับไฟล์ประเภทนี้", "Untagged": "ไม่มีแท็ก", "Untitled": "ไม่มีชื่อ", "Update": "อัปเดต", "Update and Copy Link": "อัปเดตและคัดลอกลิงก์", + "Update Email": "", "Update for the latest features and improvements.": "อัปเดตเพื่อรับฟีเจอร์และการปรับปรุงล่าสุด", + "Update Name": "", "Update password": "อัปเดตรหัสผ่าน", + "Update Picture": "", "Update your status": "", "Updated": "อัปเดตแล้ว", "Updated at": "อัปเดตเมื่อ", @@ -2211,13 +2378,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "ใช้ '#' ในการป้อน Prompt เพื่อโหลดและรวมความรู้ของคุณ", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "ใช้ Endpoint /v1/chat/completions แทน /v1/audio/transcriptions เพื่อความแม่นยำที่อาจดีขึ้น", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "ใช้ API Chat Completions", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "ใช้ LLM", "Use no proxy to fetch page contents.": "ไม่ใช้พร็อกซีในการดึงเนื้อหาหน้าเว็บ", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "ใช้พร็อกซีที่กำหนดโดยตัวแปรสภาพแวดล้อม http_proxy และ https_proxy เพื่อดึงเนื้อหาหน้าเว็บ", + "Use Web Search?": "", "user": "ผู้ใช้", "User": "ผู้ใช้", + "User Access": "", "User Activity": "", "User Groups": "กลุ่มผู้ใช้", "User location successfully retrieved.": "ดึงตำแหน่งที่ตั้งของผู้ใช้สำเร็จแล้ว", @@ -2227,6 +2399,7 @@ "User Status": "", "User Webhooks": "Webhooks ของผู้ใช้", "Username": "ชื่อผู้ใช้", + "Username Claim": "", "users": "", "Users": "ผู้ใช้", "Uses DefaultAzureCredential to authenticate": "ใช้ DefaultAzureCredential เพื่อยืนยันตัวตน", @@ -2240,6 +2413,7 @@ "Valves updated": "วาล์วถูกอัปเดตแล้ว", "Valves updated successfully": "อัปเดตวาล์วเรียบร้อยแล้ว", "variable": "ตัวแปร", + "Vector Field": "", "Verify Connection": "ตรวจสอบการเชื่อมต่อ", "Verify SSL Certificate": "ตรวจสอบใบรับรอง SSL", "Version": "เวอร์ชัน", @@ -2269,11 +2443,14 @@ "Web API": "เว็บ API", "Web Loader Engine": "เอนจินโหลดเว็บ", "Web Search": "การค้นหาเว็บ", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "เครื่องมือค้นหาเว็บ", "Web Search in Chat": "การค้นหาเว็บในการแชท", "Web Search Query Generation": "การสร้างคำค้นหาเว็บ", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "URL ของ Webhook", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "การตั้งค่า WebUI", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "เมื่อวาน", "Yesterday at {{LOCALIZED_TIME}}": "เมื่อวาน เวลา {{LOCALIZED_TIME}}", "You": "คุณ", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "การสนับสนุนทั้งหมดของคุณจะถูกส่งไปยังนักพัฒนาปลั๊กอินโดยตรง Open WebUI จะไม่หักส่วนแบ่งใดๆ อย่างไรก็ตาม แพลตฟอร์มการระดมทุนที่คุณเลือกอาจมีการเก็บค่าธรรมเนียมในส่วนของตนเอง", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "YouTube", "Youtube Language": "ภาษาของ YouTube", diff --git a/src/lib/i18n/locales/tk-TM/translation.json b/src/lib/i18n/locales/tk-TM/translation.json index 6097c89305..3c17bc9434 100644 --- a/src/lib/i18n/locales/tk-TM/translation.json +++ b/src/lib/i18n/locales/tk-TM/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}'iň Çatlary", "{{webUIName}} Backend Required": "{{webUIName}} Backend Zerur", "*Prompt node ID(s) are required for image generation": "", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "Hasap", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Goş", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Bu modeliň näme edýändigi barada gysgaça düşündiriş goşuň", "Add a tag": "Bir tag goşuň", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Faýllar goş", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Ulanyjy goş", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "", "Admin Contact Email": "", "Admin Panel": "Admin Paneli", + "Admin Roles": "", "Admin Settings": "Admin Sazlamalary", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", "Advanced": "", "Advanced Parameters": "Ösen Parametrler", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "", "Allow Voice Interruption in Call": "", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Hasabyňyz barmy?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API Esasy URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API Açar", + "API Key / Token": "", "API Key created.": "API Açar döredildi.", "API Key Endpoint Restrictions": "", "API keys": "API açarlary", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "", "Artifacts": "", "Asc": "", "Ask": "", "Ask a question": "", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "Awgust", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "", - "Auto-playback response": "Awto-gaýtadan jogap", + "Auto-Create Groups": "", + "Auto-Playback Response": "Awto-gaýtadan jogap", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "", "AUTOMATIC1111 Api Auth String": "", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Esasy URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "elýeterli ulanyjylar", + "Available variables": "", "available!": "elýeterli!", "Away": "Uzakda", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "Erbet Jogap", "Banners": "Bannerler", "Base Model (From)": "Esasy Model (Kimden)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "öň", "Being lazy": "Ýaltalyk", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Çat ugrukdyryş", + "Chat Direction": "Çat ugrukdyryş", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "Kolleksiýa", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "", "ComfyUI Workflow Nodes": "", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Buýruk", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "", "Content": "Mazmuny", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Jogap Bermegi Dowam et", "Continue with {{provider}}": "", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "Täze gizlin açar döret", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Döredilen wagty", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Nokatlaýyn Model", "Default model updated": "", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "", + "Default webhook": "", "Defaults": "", "Delete": "Öçür", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Ýatyrylan", "Disconnect OAuth": "", "Discover a function": "", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "", "Discussion channel where access is based on groups and permissions": "", "Display": "Görkeziş", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "", + "Display the Username Instead of You in the Chat": "", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "Resminama", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "", "Email": "Email", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "", @@ -707,6 +765,7 @@ "Embedding Model Engine": "", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Işjeň", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "", "Enter {{role}} message here": "", - "Enter a detail about yourself for your LLMs to recall": "", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "", "Enter Chunk Size": "", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "", "Enter SearchApi API Key": "", "Enter SearchApi Engine": "", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "", "Enter Serpstack API Key": "", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "Faýllar", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "", "Filter is now globally enabled": "", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "", "Functions": "Funksiýalar", "Functions allow arbitrary code execution.": "", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Möhüm täzelenme", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Açar", "Key is required": "", - "Keyboard shortcuts": "", "Keyboard Shortcuts": "", "Knowledge": "", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Rugsat", + "Lifecycle JSON": "", "Lift List": "", "Light": "Açyk", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "", "Made by Open WebUI Community": "", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "Mart", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "", "Memory deleted successfully": "", "Memory updated successfully": "", + "Merge Accounts by Email": "", "Merge Responses": "", "Merged Response": "Birleşdirilen jogap", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Has köp", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Netije ýok", "No results found": "", "No search query generated": "", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Hiç", + "Not configured": "", "Not factually correct": "", "Not helpful": "", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "", "November": "Noýabr", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Oktýabr", "Off": "", "Okay, Let's Go!": "", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "", "Ollama": "", "Ollama API": "", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "", + "Omit": "", "On": "Işjeň", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "Parol", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "", "Pending": "Garaşylýar", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "", "Permission denied when accessing microphone": "", "Permission denied when accessing microphone: {{error}}": "", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "", + "Picture Claim": "", "Pin": "", "Pin to Sidebar": "", "Pinned": "", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Jemgyýetçilik", "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "", "Regenerate": "", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "", + "Research Knowledge": "", "Reset": "Täzeden Guruň", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Suraty täzeden sazla", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "", "Reset Vector Storage/Knowledge": "", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "", "Role": "Roli", + "Roles Claim": "", "RTL": "", "Run": "", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Gözleg", "Search a model": "", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "", "Search Collection": "", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "", "Search Result Count": "", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "", "SearchApi Engine": "", @@ -1834,7 +1980,6 @@ "Seed": "", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Iber", "Send a Message": "", + "Send events for": "", "Send message": "", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "", "September": "Sentýabr", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "", "Serpstack API Key": "", "Server connection failed": "", "Server connection verified": "", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "Görkez", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Modeli Görkez", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Çeşme", + "Specific users or groups": "", "Speech Playback Speed": "", "Speech recognition error: {{error}}": "", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Sistema", + "System events only": "", "System Instructions": "", "System Prompt": "", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "", "Text-to-Speech": "", "Text-to-Speech Engine": "", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "", - "Toast notifications for new updates": "", + "Toast Notifications for New Updates": "", "Today": "Şu gün", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "", @@ -2184,14 +2350,19 @@ "Unpin": "", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "", "Untitled": "", "Update": "Täzeläň", "Update and Copy Link": "", + "Update Email": "", "Update for the latest features and improvements.": "", + "Update Name": "", "Update password": "", + "Update Picture": "", "Update your status": "", "Updated": "Täzelenen", "Updated at": "Täzelendi", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "", "User": "Ulanyjy", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "Ulanyjy Ady", + "Username Claim": "", "users": "", "Users": "Ulanyjylar", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "", "Valves updated successfully": "", "variable": "", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "Wersiýasy", @@ -2276,11 +2454,14 @@ "Web API": "", "Web Loader Engine": "", "Web Search": "", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Düýn", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "", "Youtube Language": "", diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index 2649d2df8e..7646548902 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "{{COUNT}} dosya", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} gizli satır", "{{COUNT}} members": "{{COUNT}} üye", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "{{count}} seçildi", "{{count}} selected_other": "{{count}} seçildi", "{{COUNT}} Sources": "{{COUNT}} kaynak", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} kelime", "{{COUNT}}d_time_ago": "{{COUNT}} gün önce", "{{COUNT}}h_time_ago": "{{COUNT}} saat önce", "{{COUNT}}m_time_ago": "{{COUNT}} dakika önce", "{{COUNT}}w_time_ago": "{{COUNT}} hafta önce", "{{COUNT}}y_time_ago": "{{COUNT}} yıl önce", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} tarihinde saat {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "{{model}} indirme işlemi iptal edildi", "{{modelName}} profile image": "{{modelName}} profil resmi", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}}'ın Sohbetleri", "{{webUIName}} Backend Required": "{{webUIName}} Arka-uç Gerekli", "*Prompt node ID(s) are required for image generation": "*Görüntü oluşturma için düğüm ID'leri gereklidir", + "1 group": "", "1 hour before": "1 saat önce", "1 Source": "1 Kaynak", + "1 user": "", "10 minutes before": "10 dakika önce", "15 minutes before": "15 dakika önce", "1m_time_ago": "1 dk önce", @@ -57,6 +67,7 @@ "Access Control": "Erişim Kontrolü", "Access Grants": "Erişim İzinleri", "Access List": "Erişim Listesi", + "Access prohibited": "", "Access updated": "Erişim güncellendi", "Accessible to all users": "Tüm kullanıcılara erişilebilir", "Account": "Hesap", @@ -72,6 +83,7 @@ "Activity": "Etkinlik", "Add": "Ekle", "Add a model ID": "Bir model kimliği ekleyin", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Bu modelin ne yaptığı hakkında kısa bir açıklama ekleyin", "Add a tag": "Bir etiket ekleyin", "Add a tag...": "Bir etiket ekleyin...", @@ -84,8 +96,10 @@ "Add Custom Prompt": "Özel Prompt Ekle", "Add description": "Açıklama ekle", "Add Details": "Ayrıntı Ekle", + "Add durable context for future chats": "", "Add Files": "Dosyalar Ekle", "Add Image": "Görsel Ekle", + "Add Knowledge Connection": "", "Add location": "Konum ekle", "Add Member": "Üye Ekle", "Add Members": "Üyeleri Ekle", @@ -100,6 +114,7 @@ "Add to favorites": "Favorilere ekle", "Add User": "Kullanıcı Ekle", "Add User Group": "Kullanıcı Grubu Ekle", + "Add webhook": "", "Add webpage": "Web sayfası ekle", "Add your Open Terminal URL and API key in Settings → Integrations.": "Open Terminal URL'nizi ve API anahtarınızı Ayarlar → Entegrasyonlar bölümünde girin.", "Additional Config": "Ek Yapılandırma", @@ -112,7 +127,9 @@ "Admin": "Yönetici", "Admin Contact Email": "Yönetici İletişim E-postası", "Admin Panel": "Yönetici Paneli", + "Admin Roles": "", "Admin Settings": "Yönetici Ayarları", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Yöneticiler her zaman tüm araçlara erişebilir; kullanıcıların çalışma alanındaki model başına atanmış araçlara ihtiyacı vardır.", "Advanced": "Gelişmiş", "Advanced Parameters": "Gelişmiş Parametreler", @@ -123,16 +140,21 @@ "All": "Tüm", "All chats have been unarchived.": "Tüm sohbetler arşivden çıkarıldı.", "All day": "Tüm gün", + "All events": "", "All models are now hidden": "Tüm modeller artık gizli", "All models are now visible": "Tüm modeller artık görünür", "All models deleted successfully": "Tüm modeller başarıyla silindi", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "Tüm zamanlar", "All Users": "Tüm Kullanıcılar", + "All users and system events": "", "Allow Call": "Aramaya İzin Ver", "Allow Chat Controls": "Sohbet Kontrollerine İzin Ver", "Allow Chat Delete": "Sohbet Silmeye İzin Ver", "Allow Chat Edit": "Sohbet Düzenlemeye İzin Ver", "Allow Chat Export": "Sohbetin Dışa Aktarımına İzin Ver", + "Allow Chat Import": "", "Allow Chat Params": "Sohbet Parametrelerine İzin Ver", "Allow Chat Share": "Sohbetin Paylaşılmasına İzin Ver", "Allow Chat System Prompt": "Sohbet Sistem Promptuna İzin Ver", @@ -152,9 +174,11 @@ "Allow User Location": "Kullanıcı Konumuna İzin Ver", "Allow Voice Interruption in Call": "Aramada Ses Kesintisine İzin Ver", "Allow Web Upload": "Web İçeriği Yüklemeye İzin Ver", + "Allowed Domains": "", "Allowed Endpoints": "İzin Verilen Uç Noktalar", "Allowed File Extensions": "İzin Verilen Dosya Uzantıları", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Yükleme için izin verilen dosya uzantıları. Birden fazla uzantıyı virgülle ayırın. Tüm dosya türleri için boş bırakın.", + "Allowed Roles": "", "Already have an account?": "Zaten bir hesabınız mı var?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p'ye alternatiftir ve kalite ile çeşitlilik arasında bir denge sağlamayı amaçlar. p parametresi, bir tokenin dikkate alınması için en olası tokenin olasılığına göre minimum olasılığını temsil eder. Örneğin, p=0,05 ve en olası tokenin olasılığı 0,9 ise, 0,045'ten küçük değere sahip logitler filtrelenir.", "Always": "Daima", @@ -173,6 +197,7 @@ "API Base URL": "API Temel URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker hizmeti için API temel URL'si. Varsayılan: https://www.datalab.to/api/v1/marker", "API Key": "API Anahtarı", + "API Key / Token": "", "API Key created.": "API Anahtarı oluşturuldu.", "API Key Endpoint Restrictions": "API Anahtarı Uç Nokta Kısıtlamaları", "API keys": "API anahtarları", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "Bu hafızayı silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", "Are you sure you want to delete this message?": "Bu mesajı silmek istediğinizden emin misiniz?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Bu sürümü silmek istediğinizden emin misiniz? Alt sürümler bu sürümün üst sürümüne yeniden bağlanacaktır.", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "Bunu silmek istediğinizden emin misiniz?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Arşivlenmiş tüm sohbetlerin arşivini kaldırmak istediğinizden emin misiniz?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena Modelleri", "Artifacts": "Eserler", "Asc": "Artan", "Ask": "Sor", "Ask a question": "Bir soru sorun", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Asistan", "Async Embedding Processing": "Eşzamansız Gömme İşleme", "At time of event": "Etkinlik zamanında", @@ -223,14 +253,20 @@ "Audio": "Ses", "August": "Ağustos", "Auth": "Yetki", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Kimlik Doğrulama", "Authentication": "Kimlik Doğrulama", "Auto": "Otomatik", "Auto (Random)": "Otomatik (Rastgele)", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Yanıtı Panoya Otomatik Kopyala", - "Auto-playback response": "Yanıtı otomatik oynatma", + "Auto-Create Groups": "", + "Auto-Playback Response": "Yanıtı otomatik oynatma", "Autocomplete Generation": "Otomatik Tamamlama Üretimi", "Autocomplete Generation Input Max Length": "Otomatik Tamamlama Üretimi Maksimum Uzunlukta Giriş", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API Kimlik Doğrulama Dizesi", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 Temel URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Mevcut Araçlar", "available users": "kullanılabilir kullanıcılar", + "Available variables": "", "available!": "mevcut!", "Away": "Uzakta", "Awful": "Berbat", @@ -258,16 +295,17 @@ "Bad Response": "Kötü Yanıt", "Banners": "Afişler", "Base Model (From)": "Temel Model ('den)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "Temel Model Listesi Önbelleği, temel modelleri yalnızca başlangıçta veya ayarlar kaydedilirken getirerek erişimi hızlandırır—daha hızlıdır, ancak son temel model değişikliklerini göstermeyebilir.", "Bearer": "Bearer", "before": "önce", "Being lazy": "Tembelleşiyor", - "Beta": "Beta", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Arama V7 Uç Noktası", "Bing Search V7 Subscription Key": "Bing Arama V7 Abonelik Anahtarı", "Bio": "Biyografi", "Birth Date": "Doğum Tarihi", + "Blocked Groups": "", "BM25 Weight": "BM25 Ağırlığı", "Bocha Search API Key": "Bocha Arama API Anahtarı", "Bold": "Kalın", @@ -324,7 +362,7 @@ "Chat Completions": "Sohbet Tamamlamaları", "Chat Conversation": "Sohbet Konuşması", "Chat deleted.": "Sohbet silindi.", - "Chat direction": "Sohbet Yönü", + "Chat Direction": "Sohbet Yönü", "Chat exported successfully": "Sohbet başarıyla dışa aktarıldı", "Chat History": "Sohbet Geçmişi", "Chat ID": "Sohbet Kimliği", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "İnsanların üye olarak katıldığı bir iş birliği kanalı", "Collapse": "Daralt", "Collection": "Koleksiyon", + "Collection Field": "", "Collections": "Koleksiyonlar", "Color": "Renk", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI İş Akışı", "ComfyUI Workflow Nodes": "ComfyUI İş Akışı Düğümleri", "Comma separated Node Ids (e.g. 1 or 1,2)": "Virgülle ayrılmış Node ID'leri (örn. 1 veya 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "komut", "Command": "Komut", "Comment": "Yorum", "Commit Message": "Commit Mesajı", "Community Reviews": "Topluluk İncelemeleri", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Tamamlamalar", "Compress Images in Channels": "Kanallarda Görselleri Sıkıştır", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Open Terminal örneklerine bağlanın. Tüm kullanıcılar bu sunucular üzerinden dosya gezintisine ve terminal araçlarına erişebilecek.", "Connect to your own OpenAI compatible API endpoints.": "Kendi OpenAI uyumlu API uç noktalarınıza bağlanın.", "Connect to your own OpenAPI compatible external tool servers.": "Kendi OpenAPI uyumlu harici araç sunucularınıza bağlanın.", + "Connected": "", "Connected ({{type}})": "Bağlandı ({{type}})", "Connection failed": "Bağlantı başarısız", "Connection lost. Reconnecting...": "Bağlantı kesildi. Yeniden bağlanılıyor...", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUI Erişimi için Yöneticiyle İletişime Geçin", "Content": "İçerik", "Content Extraction Engine": "İçerik Çıkarma Motoru", + "Content Field": "", "Content lengths (character counts only)": "İçerik uzunlukları (sadece karakter sayısı)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "Bağlam Tokenleri", + "Continue": "", "Continue Response": "Yanıta Devam Et", "Continue with {{provider}}": "{{provider}} ile devam et", "Continue with Email": "E-posta ile devam edin", @@ -493,6 +543,7 @@ "Create new secret key": "Yeni gizli anahtar oluştur", "Create note": "Not oluştur", "Create Note": "Not Oluştur", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "Yinelenen şekilde otomatik olarak çalışan zamanlanmış istemler oluşturun.", "Create your first note by clicking on the plus button below.": "İlk notunuzu aşağıdaki artı düğmesine basarak oluşturun.", "Created at": "Oluşturulma tarihi", @@ -510,6 +561,7 @@ "Custom Gender": "Özel Cinsiyet", "Custom Parameter Name": "Özel Parametre Adı", "Custom Parameter Value": "Özel Parametre Değeri", + "Custom range": "", "Daily": "Günlük", "Daily Messages": "Günlük Mesajlar", "Danger Zone": "Tehlikeli Bölge", @@ -532,7 +584,6 @@ "Default Features": "Varsayılan Özellikler", "Default Filters": "Varsayılan Filtreler", "Default Group": "Varsayılan Grup", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Varsayılan mod, araçları yürütmeden önce bir kez çağırarak daha geniş bir model yelpazesiyle çalışır. Yerel mod, modelin yerleşik araç çağırma yeteneklerinden yararlanır, ancak modelin bu özelliği doğal olarak desteklemesini gerektirir.", "Default Model": "Varsayılan Model", "Default model updated": "Varsayılan model güncellendi", "Default permissions": "Varsayılan izinler", @@ -542,6 +593,7 @@ "Default to ALL": "TÜMÜ'nü varsayılan olarak", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Odaklanmış ve ilgili içerik çıkarımı için varsayılan olarak bölümlenmiş alma kullanılır, çoğu durum için bu önerilir.", "Default User Role": "Varsayılan Kullanıcı Rolü", + "Default webhook": "", "Defaults": "Varsayılanlar", "Delete": "Sil", "Delete {{name}}": "{{name}} öğesini sil", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "Kod Yorumlayıcıyı Devre Dışı Bırak", "Disable Image Extraction": "Görsel Çıkarmayı Devre Dışı Bırak", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF'den görsel çıkarmayı devre dışı bırakır. LLM Kullan etkinse görseller otomatik olarak altyazılanır. Varsayılan olarak False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Devre Dışı", "Disconnect OAuth": "OAuth Bağlantısını Kes", "Discover a function": "Bir fonksiyon keşfedin", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Model ön ayarlarını keşfedin, indirin ve inceleyin", "Discussion channel where access is based on groups and permissions": "Erişimin gruplar ve izinlere dayandığı bir tartışma kanalı", "Display": "Görüntüle", - "Display chat title in tab": "Sekmede sohbet başlığını göster", + "Display Chat Title in Tab": "Sekmede sohbet başlığını göster", "Display Emoji in Call": "Aramada Emoji Göster", "Display Multi-model Responses in Tabs": "Çoklu model yanıtlarını sekmelerde göster", - "Display the username instead of You in the Chat": "Sohbet'te Siz yerine kullanıcı adını göster", + "Display the Username Instead of You in the Chat": "Sohbet'te Siz yerine kullanıcı adını göster", "Displays citations in the response": "Yanıtta alıntıları gösterir", "Displays status updates (e.g., web search progress) in the response": "Yanıtta durum güncellemelerini gösterir (ör. web arama ilerlemesi)", "Dive into knowledge": "Bilgiye dalmak", @@ -630,6 +684,7 @@ "Docling Parameters": "Docling Parametreleri", "Docling Server URL required.": "Docling Sunucu URL'si gereklidir.", "Document": "Belge", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Document Intelligence uç noktası gereklidir.", "Document Intelligence Model": "Document Intelligence Modeli", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Varsayılan İzinleri Düzenle", "Edit Folder": "Klasörü Düzenle", "Edit Image": "Görseli Düzenle", + "Edit Knowledge Connection": "", "Edit Last Message": "Son Mesajı Düzenle", "Edit Memory": "Belleği Düzenle", "Edit Prompt": "Prompt'u Düzenle", "Edit Terminal Connection": "Terminal Bağlantısını Düzenle", "Edit User": "Kullanıcıyı Düzenle", "Edit User Group": "Kullanıcı Grubunu Düzenle", + "Edit webhook": "", "Edit workflow.json content": "workflow.json içeriğini düzenle", "edited": "düzenlendi", "Edited": "Düzenlendi", @@ -699,6 +756,7 @@ "Eject model": "Modeli çıkar", "ElevenLabs": "ElevenLabs", "Email": "E-posta", + "Email Claim": "", "Embark on adventures": "Maceralara atıl", "Embedding": "Gömme", "Embedding Batch Size": "Gömme Yığın Boyutu", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Gömme Modeli Motoru", "Emoji": "", "Emojis": "Emojiler", + "Empty": "", "Empty message": "Boş mesaj", "Enable All": "Tümünü Etkinleştir", "Enable API Keys": "API Anahtarlarını Etkinleştir", @@ -714,22 +773,27 @@ "Enable Code Execution": "Kod Çalıştırmayı Etkinleştir", "Enable Code Interpreter": "Kod Yorumlayıcıyı Etkinleştir", "Enable Community Sharing": "Topluluk Paylaşımını Etkinleştir", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Model verilerinin RAM'den takas edilmesini önlemek için Hafıza Kilitlemeyi (mlock) etkinleştirin. Bu seçenek, modelin çalışan sayfa kümesini RAM'e kilitleyerek disk takasına alınmamalarını sağlar. Bu, sayfa hatalarını önleyerek ve hızlı veri erişimi sağlayarak performansın korunmasına yardımcı olabilir.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Model verilerini yüklemek için Hafıza Eşlemeyi (mmap) etkinleştirin. Bu seçenek, sistemin disk dosyalarını RAM'deymiş gibi ele alarak disk depolamasını RAM'in bir uzantısı olarak kullanmasına olanak tanır. Bu, daha hızlı veri erişimi sağlayarak model performansını artırabilir. Ancak tüm sistemlerde düzgün çalışmayabilir ve önemli miktarda disk alanı tüketebilir.", "Enable Message Queue": "Mesaj Kuyruğunu Etkinleştir", "Enable Message Rating": "Mesaj Değerlendirmeyi Etkinleştir", "Enable Mirostat sampling for controlling perplexity.": "Şaşkınlığı (perplexity) kontrol etmek için Mirostat örneklemesini etkinleştirin.", "Enable New Sign Ups": "Yeni Kayıtları Etkinleştir", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "Model tarafından kullanılan akıl yürütme etiketlerini etkinleştirin, devre dışı bırakın veya özelleştirin. \"Etkin\" varsayılan etiketleri kullanır, \"Devre Dışı\" akıl yürütme etiketlerini kapatır ve \"Özel\" kendi başlangıç ve bitiş etiketlerinizi belirtmenize olanak tanır.", "Enabled": "Etkin", "End Tag": "Bitiş Etiketi", + "Endpoint": "", "Endpoint URL": "Uçnokta URL", "Enforce Temporary Chat": "Geçici Sohbete Zorla", "Enhance": "İyileştir", "Enrich Hybrid Search Text": "Hibrit Arama Metnini Zenginleştir", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV dosyanızın şu sırayla 4 sütun içerdiğinden emin olun: İsim, E-posta, Şifre, Rol.", "Enter {{role}} message here": "Buraya {{role}} mesajını girin", - "Enter a detail about yourself for your LLMs to recall": "LLM'lerinizin hatırlaması için kendiniz hakkında bir bilgi girin", "Enter a title for the pending user info overlay. Leave empty for default.": "Bekleyen kullanıcı bilgi katmanı için bir başlık girin. Varsayılan için boş bırakın.", "Enter a watermark for the response. Leave empty for none.": "Yanıt için bir filigran girin. Yoksa boş bırakın.", "Enter additional headers in JSON format": "JSON formatında ek başlıklar girin", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "Parça Minimum Boyut Hedefini Girin", "Enter Chunk Overlap": "Parça Çakışmasını Girin", "Enter Chunk Size": "Parça Boyutunu Girin", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Virgülle ayrılmış \"token:bias_value\" çiftlerini girin (örnek: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Bekleyen kullanıcı bilgi katmanı için içerik girin. Varsayılan için boş bırakın.", "Enter coordinates (e.g. 51.505, -0.09)": "Koordinatları girin (örn. 51.505, -0.09)", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter URL'sini Girin", "Enter Kagi Search API Key": "Kagi Search API Anahtarını Girin", "Enter Key Behavior": "Enter Tuşu Davranışı", + "Enter language": "", "Enter language codes": "Dil kodlarını girin", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "MinerU API Anahtarını Girin", "Enter Mistral API Base URL": "Mistral API Taban URL'sini Girin", "Enter Mistral API Key": "Mistral API Anahtarını Girin", @@ -804,6 +873,7 @@ "Enter prompt here.": "İstemi buraya girin.", "Enter proxy URL (e.g. https://user:password@host:port)": "Vekil sunucu URL'sini girin (örn. https://user:password@host:port)", "Enter reasoning effort": "Muhakeme çabasını girin", + "Enter Redirect URI": "", "Enter Score": "Skoru Girin", "Enter SearchApi API Key": "Arama-API Anahtarını Girin", "Enter SearchApi Engine": "Arama-API Motorunu Girin", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API Anahtarını Girin", "Enter SerpApi Engine": "SerpApi Motorunu Girin", "Enter Serper API Key": "Serper API Anahtarını Girin", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API Anahtarını Girin", "Enter Serpstack API Key": "Serpstack API Anahtarını Girin", "Enter server host": "Sunucu ana bilgisayarını girin", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Tika Sunucu URL'sini Girin", "Enter timeout in seconds": "Zaman aşımını saniye cinsinden girin", "Enter to Send": "Göndermek için Enter", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K'yı girin", "Enter Top K Reranker": "Top K Yeniden Sıralayıcıyı Girin", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL'yi Girin (örn. http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Hata: '{{modelId}}' ID'sine sahip bir model zaten mevcut. Devam etmek için lütfen farklı bir ID seçin.", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Hata: Model ID'si boş olamaz. Devam etmek için lütfen geçerli bir ID girin.", "Evaluations": "Değerlendirmeler", + "Event": "", "Event created": "Etkinlik oluşturuldu", "Event deleted": "Etkinlik silindi", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "Etkinlik başlığı", "Event updated": "Etkinlik güncellendi", + "Events": "", "Exa API Key": "Exa API Anahtarı", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Örnek: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Örnek: ALL", "Example: mail": "Örnek: mail", @@ -905,12 +982,18 @@ "Export Config": "Yapılandırmayı Dışa Aktar", "Export Models": "Modelleri Dışa Aktar", "Export Prompts": "Promptları Dışa Aktar", + "Export Skills": "", "Export to CSV": "CSV'ye Aktar", "Export Tools": "Araçları Dışa Aktar", "Export Users": "Kullanıcıları Dışa Aktar", "External": "Harici", + "External connection not found.": "", "External Document Loader URL required.": "Harici Belge Yükleyici URL gerekli.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Harici Görev Modeli", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Harici Web Yükleyici API Anahtarı", "External Web Loader URL": "Harici Web Yükleyici URL'si", "External Web Search API Key": "Harici Web Arama API Anahtarı", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API Anahtarı oluşturulamadı.", "Failed to delete calendar": "Takvim silinemedi", "Failed to delete note": "Not silinemedi", + "Failed to delete webhook": "", "Failed to disconnect": "Bağlantı kesilemedi", "Failed to download image": "Görsel indirilemedi", "Failed to extract content from the file: {{error}}": "Dosyadan içerik çıkarılamadı: {{error}}", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Modeller alınamadı", "Failed to generate title": "Başlık oluşturulamadı", "Failed to import models": "Modeller içe aktarılamadı", + "Failed to load chat": "", "Failed to load chat preview": "Sohbet ön izlemesi yüklenemedi", "Failed to load DOCX file. Please try downloading it instead.": "DOCX dosyası yüklenemedi. Lütfen bunun yerine indirmeyi deneyin.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV dosyası yüklenemedi. Lütfen bunun yerine indirmeyi deneyin.", @@ -944,6 +1029,7 @@ "Failed to move chat": "Sohbet taşınamadı", "Failed to process URL: {{url}}": "URL işlenemedi: {{url}}", "Failed to read clipboard contents": "Pano içeriği okunamadı", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "Üye kaldırılamadı", "Failed to render diagram": "Diyagram oluşturulamadı", "Failed to render visualization": "Görselleştirme oluşturulamadı", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Modeller yapılandırması kaydedilemedi", "Failed to save policy: {{error}}": "İlke kaydedilemedi: {{error}}", "Failed to save terminal servers": "Terminal sunucuları kaydedilemedi", + "Failed to save webhook": "", "Failed to unshare chat.": "Sohbet paylaşımı kaldırılamadı.", "Failed to update settings": "Ayarlar güncellenemedi", "Failed to update status": "Durum güncellenemedi", + "Failed to update webhook": "", "Failed to upload file.": "Dosya yüklenemedi.", "Features": "Özellikler", "Features Permissions": "Özellik Yetkileri", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Dosya başarıyla yüklendi", "Filename": "Dosya adı", "Files": "Dosyalar", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "Filtre", "Filter is now globally disabled": "Filtre artık global olarak devre dışı", "Filter is now globally enabled": "Filtre artık global olarak devrede", @@ -1009,6 +1099,7 @@ "Folder options": "Klasör seçenekleri", "Folder updated successfully": "Klasör başarıyla güncellendi", "Folders": "Klasörler", + "Folders Sharing": "", "Follow up": "Takip", "Follow Up Generation": "Takip Oluşturma", "Follow Up Generation Prompt": "Takip Oluşturma Prompt'u", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Fonksiyon artık global olarak aktif", "Function Name": "Fonksiyon Adı", "Function Name Filter List": "Fonksiyon Adı Filtre Listesi", + "Function starter": "", "Function updated successfully": "Fonksiyon başarıyla güncellendi", "Functions": "Fonksiyonlar", "Functions allow arbitrary code execution.": "Fonksiyonlar keyfi kod yürütülmesine izin verir.", @@ -1071,7 +1163,10 @@ "Gravatar": "Gravatar", "Grid": "Izgara", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "Grup Kanalı", + "Group Claim": "", "Group created successfully": "Grup başarıyla oluşturuldu", "Group deleted successfully": "Grup başarıyla silindi", "Group Description": "Grup Açıklaması", @@ -1083,6 +1178,7 @@ "H2": "H2", "H3": "H3", "Haptic Feedback": "Dokunsal Geri Bildirim", + "Header variables": "", "Headers": "Başlıklar", "Headers must be a valid JSON object": "Başlıklar geçerli bir JSON nesnesi olmalıdır", "Height": "Yükseklik", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "Kimlik \":\" veya \"|\" karakterlerini içeremez", "ID copied to clipboard": "Kimlik panoya kopyalandı", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "Boşta Kalma Zaman Aşımı", "iframe Sandbox Allow Forms": "iframe Korumalı Alanı Formlara İzin Ver", "iframe Sandbox Allow Same Origin": "iframe Korumalı Alanı Aynı Kaynağa İzin Ver", @@ -1138,6 +1236,7 @@ "Import From Link": "Bağlantıdan İçe Aktar", "Import Models": "Modelleri İçe Aktar", "Import Prompts": "İstemleri İçe Aktar", + "Import Skills": "", "Import successful": "İçe aktarma başarılı", "Import Tools": "Araçları İçe Aktar", "Important Update": "Önemli güncelleme", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "Kenar Çubuğunda Tut", "Key": "Anahtar", "Key is required": "Anahtar gerekli", - "Keyboard shortcuts": "Klavye kısayolları", "Keyboard Shortcuts": "Klavye Kısayolları", "Knowledge": "Bilgi", "Knowledge Access": "Bilgi Erişimi", @@ -1208,6 +1306,8 @@ "Knowledge Name": "Bilgi Adı", "Knowledge Public Sharing": "Bilginin Herkese Açık Paylaşımı", "Knowledge Sharing": "Bilgi Paylaşımı", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Bilgi başarıyla güncellendi", "Kokoro.js (Browser)": "Kokoro.js (Tarayıcı)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "Son çalıştırma", "Last reply": "Son yanıt", "LDAP": "LDAP", - "LDAP server updated": "LDAP sunucusu güncellendi", "Leaderboard": "Liderlik Tablosu", "Learn more": "Daha fazla bilgi edinin", "Learn More": "Daha Fazla Bilgi Edinin", @@ -1246,6 +1345,7 @@ "Legacy": "Eski Sürüm", "lexical": "sözcüksel", "License": "Lisans", + "Lifecycle JSON": "", "Lift List": "Listeyi Yükselt", "Light": "Açık", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Eşzamanlı arama sorgularını sınırla. 0 = sınırsız (varsayılan). Sıralı yürütme için 1 olarak ayarlayın (Brave ücretsiz katman gibi katı oran sınırlarına sahip API'ler için önerilir).", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Konum erişimine izin verilmiyor", "Lost": "Kayıp", "Low": "Düşük", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "Soldan Sağa", "Made by Open WebUI Community": "OpenWebUI Topluluğu tarafından yapılmıştır", "Make password visible in the user interface": "Parolayı kullanıcı arayüzünde görünür yap", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Pipelineları Yönet", "Manage Tool Servers": "Araç Sunucularını Yönet", "Manage your account information.": "Hesap bilgilerinizi yönetin.", + "Mapped Source": "", "March": "Mart", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown Başlık Metni Bölücü", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Bellek başarıyla temizlendi", "Memory deleted successfully": "Bellek başarıyla silindi", "Memory updated successfully": "Bellek başarıyla güncellendi", + "Merge Accounts by Email": "", "Merge Responses": "Yanıtları Birleştir", "Merged Response": "Birleştirilmiş Yanıt", "Message": "Mesaj", @@ -1322,9 +1425,12 @@ "messages": "mesajlar", "Messages": "Mesajlar", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Bağlantınızı oluşturduktan sonra gönderdiğiniz mesajlar paylaşılmayacaktır. URL'ye sahip kullanıcılar paylaşılan sohbeti görüntüleyebilecektir.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (kişisel)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (iş/okul)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "dk", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "Bulut API modu için MinerU API Anahtarı gereklidir.", @@ -1377,6 +1483,7 @@ "Models Sharing": "Model Paylaşımı", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search API Anahtarı", + "Monday – Friday": "", "Month": "Ay", "Monthly": "Aylık", "More": "Daha Fazla", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Bilgi tabanınıza bir ad verin", "Name, prompt, and model are required": "Ad, istem ve model gereklidir", "Native": "Yerel", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "Asla", "New": "Yeni", "New Automation": "Yeni Otomasyon", @@ -1423,6 +1531,7 @@ "Next run": "Sonraki çalıştırma", "No access grants. Private to you.": "Erişim izni yok. Size özel.", "No activity data": "Aktivite verisi yok", + "No additional headers are sent unless configured.": "", "No authentication": "Kimlik doğrulama yok", "No automations found": "Otomasyon bulunamadı", "No chats found": "Sohbet bulunamadı", @@ -1435,8 +1544,10 @@ "No data": "Veri yok", "No data found": "Veri bulunamadı", "No distance available": "Mesafe mevcut değil", + "No event webhooks configured.": "", "No execution logs available yet": "Henüz yürütme günlüğü yok", "No expiration can pose security risks.": "Son kullanma tarihi olmaması güvenlik riskleri oluşturabilir.", + "No external knowledge sources configured.": "", "No feedback found": "Geri bildirim bulunamadı", "No file selected": "Hiçbir dosya seçilmedi", "No files found": "Dosya bulunamadı", @@ -1464,6 +1575,7 @@ "No output items": "Çıktı ögesi yok", "No pinned messages": "Sabitlenmiş mesaj yok", "No prompts found": "Prompt bulunamadı", + "No Repeat": "", "No results": "Sonuç bulunamadı", "No results found": "Sonuç bulunamadı", "No search query generated": "Hiç arama sorgusu oluşturulmadı", @@ -1483,6 +1595,7 @@ "No webhooks yet": "Henüz webhook yok", "Node Ids": "Düğüm Kimlikleri", "None": "Yok", + "Not configured": "", "Not factually correct": "Gerçeklere göre doğru değil", "Not helpful": "Yardımcı olmadı", "Not Registered": "Kayıtlı Değil", @@ -1498,20 +1611,25 @@ "Notifications": "Bildirimler", "November": "Kasım", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1 (Statik)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "OAuth Sunucu URL'si", "OAuth session disconnected": "OAuth oturumu bağlantısı kesildi", "October": "Ekim", "Off": "Kapalı", "Okay, Let's Go!": "Tamam, Hadi Başlayalım!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Koyu", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API ayarları güncellendi", "Ollama Cloud API Key": "Ollama Cloud API Anahtarı", "Ollama Version": "Ollama Sürümü", + "Omit": "", "On": "Açık", "Once": "Bir kez", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Parola", "Passwords do not match.": "Parolalar eşleşmiyor.", "Paste Large Text as File": "Büyük Metni Dosya Olarak Yapıştır", + "Path": "", "Path copied": "Yol kopyalandı", "Paused": "Duraklatıldı", "PDF document (.pdf)": "PDF belgesi (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "beklemede", "Pending": "Beklemede", + "Pending Accounts": "", "Pending User Overlay Content": "Bekleyen Kullanıcı Yer Paylaşımı İçeriği", "Pending User Overlay Title": "Bekleyen Kullanıcı Yer Paylaşımı Başlığı", "Permission denied when accessing media devices": "Medya cihazlarına erişim izni reddedildi", "Permission denied when accessing microphone": "Mikrofona erişim izni reddedildi", "Permission denied when accessing microphone: {{error}}": "Mikrofona erişim izni reddedildi: {{error}}", "Permissions": "İzinler", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API Anahtarı", "Perplexity Model": "Perplexity Modeli", "Perplexity Search API URL": "Perplexity Search API URL'si", "Perplexity Search Context Usage": "Perplexity Search Bağlam Kullanımı", "Persistent": "Kalıcı", "Personalization": "Kişiselleştirme", + "Picture Claim": "", "Pin": "Sabitle", "Pin to Sidebar": "Kenar Çubuğuna Sabitle", "Pinned": "Sabitlenmiş", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Lütfen tüm alanları doldurun.", "Please register the OAuth client": "Lütfen OAuth istemcisini kaydedin", "Please save the connection to persist the OAuth client information and do not change the ID": "OAuth istemci bilgilerini kalıcı hale getirmek için lütfen bağlantıyı kaydedin ve Kimliği değiştirmeyin", - "Please select a model first.": "Lütfen önce bir model seçin.", "Please select a model.": "Lütfen bir model seçin", "Please select a reason": "Lütfen bir neden seçin", "Please select a valid JSON file": "Lütfen geçerli bir JSON dosyası seçin", "Please select at least one user for Direct Message channel.": "Doğrudan Mesaj kanalı için lütfen en az bir kullanıcı seçin.", "Please wait until all files are uploaded.": "Lütfen tüm dosyalar yüklenene kadar bekleyin.", "Policy ID": "İlke Kimliği", + "Policy ID is required": "", "Port": "Port", "Ports": "Bağlantı Noktaları", "Positive attitude": "Olumlu yaklaşım", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "İstemlerin Herkese Açık Paylaşımı", "Prompts Sharing": "İstem Paylaşımı", "Provider": "Sağlayıcı", + "Provider Name": "", + "Provider URL": "", "Public": "Herkese Açık", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com'dan \"{{searchValue}}\" çekin", "Pull a model from Ollama.com": "Ollama.com'dan bir model çekin", @@ -1687,21 +1811,29 @@ "Read": "Oku", "Read Aloud": "Sesli Oku", "Read more →": "Devamını oku →", + "Read only": "", "Read Only": "Salt Okunur", "Read-Only Access": "Salt Okunur Erişim", "Reason": "Neden", "Reasoning Effort": "Akıl Yürütme Çabası", "Reasoning Tags": "Akıl Yürütme Etiketleri", "Reasoning text...": "Akıl yürütme metni...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "Son Kullanılanlar", "Reconnected": "Yeniden bağlandı", "Record": "Kaydet", "Record voice": "Ses kaydı yap", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "OpenWebUI Topluluğuna yönlendiriliyorsunuz", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Anlamsız çıktı üretme olasılığını azaltır. Daha yüksek bir değer (örneğin 100) daha çeşitli yanıtlar verirken, daha düşük bir değer (örneğin 10) daha tutucu olur.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Kendinizden \"User\" olarak bahsedin (örneğin, \"User İspanyolca öğreniyor\")", "Reference Chats": "Referans Sohbetler", "Refresh": "Yenile", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Reddedilmemesi gerekirken reddedildi", "Regenerate": "Tekrar Oluştur", "Regenerate Menu": "Yeniden Oluşturma Menüsü", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "Önizlemelerde Markdown'u İşle", "Render Markdown in User Messages": "Kullanıcı Mesajlarında Markdown'ı İşle", "Reorder Models": "Modelleri Yeniden Sırala", + "Repeat": "", "Repeats": "Yinelemeler", "Reply": "Yanıtla", "Reply in Thread": "Konuya Yanıtla", "Reply to thread...": "Konuya yanıt ver...", "Replying to {{NAME}}": "{{NAME}} kullanıcısına yanıt veriliyor", + "Require users to confirm before using Web Search.": "", "required": "gerekli", "Reranking Batch Size": "Yeniden Sıralama Toplu İş Boyutu", "Reranking Engine": "Yeniden Sıralama Motoru", "Reranking Model": "Yeniden Sıralama Modeli", + "Research Knowledge": "", "Reset": "Sıfırla", "Reset All Models": "Tüm Modelleri Sıfırla", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Görüntüyü sıfırla", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Yükleme Dizinini Sıfırla", "Reset Vector Storage/Knowledge": "Vektör Depolama/Bilgiyi Sıfırla", "Reset view": "Görünümü sıfırla", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "1 kaynak getirildi", "Rich Text Input for Chat": "Sohbet için Zengin Metin Girişi", "Role": "Rol", + "Roles Claim": "", "RTL": "Sağdan Sola", "Run": "Çalıştır", "Run All": "Tümünü Çalıştır", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Sohbet kayıtlarının doğrudan tarayıcınızın depolama alanına kaydedilmesi artık desteklenmemektedir. Lütfen aşağıdaki butona tıklayarak sohbet kayıtlarınızı indirmek ve silmek için bir dakikanızı ayırın. Endişelenmeyin, sohbet günlüklerinizi arkayüze kolayca yeniden aktarabilirsiniz:", "Schedule": "Zamanla", "Scheduled time must be in the future": "Zamanlanan saat gelecekte olmalıdır", + "Scopes": "", "Scroll On Branch Change": "Dal Değişiminde Kaydır", "Scroll to Top": "Başa Kaydır", "Search": "Ara", "Search a model": "Bir model ara", + "Search actions": "", "Search all emojis": "Tüm emojileri ara", "Search and manage user memories": "Kullanıcı anılarını ara ve yönet", "Search and view user chat history": "Kullanıcı sohbet geçmişini ara ve görüntüle", @@ -1798,6 +1940,7 @@ "Search Chats": "Sohbetleri Ara", "Search Collection": "Koleksiyon Ara", "Search Files": "Dosyaları Ara", + "Search filters": "", "Search Filters": "Filtreleri Ara", "search for archived chats": "arşivlenmiş sohbetleri ara", "search for folders": "klasörleri ara", @@ -1812,13 +1955,16 @@ "Search Models": "Modelleri Ara", "Search Notes": "Notları Ara", "Search options": "Arama seçenekleri", + "Search or add pattern": "", "Search Prompts": "Prompt Ara", "Search Result Count": "Arama Sonucu Sayısı", + "Search skills": "", "Search Skills": "Yetenekleri Ara", - "Search skills...": "", "Search the internet": "İnternette Ara", "Search the web and fetch URLs": "Web'de ara ve URL'leri getir", + "Search tools": "", "Search Tools": "Arama Araçları", + "Search users or groups": "", "Search, view, and manage user notes": "Kullanıcı notlarını ara, görüntüle ve yönet", "SearchApi API Key": "Arama-API API Anahtarı", "SearchApi Engine": "Arama-API Motoru", @@ -1834,7 +1980,6 @@ "Seed": "Seed", "Select": "Seç", "Select {{modelName}} model": "{{modelName}} modelini seç", - "Select a base model": "Bir temel model seç", "Select a base model (e.g. llama3, gpt-4o)": "Bir temel model seçin (örn. llama3, gpt-4o)", "Select a conversation to preview": "Bir sohbeti önizlemek için seç", "Select a engine": "Bir motor seç", @@ -1872,18 +2017,25 @@ "semantic": "semantik", "Send": "Gönder", "Send a Message": "Bir Mesaj Gönder", + "Send events for": "", "Send message": "Mesaj gönder", "Send now": "Şimdi gönder", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "İsteğe `stream_options: { include_usage: true }` gönderir.\nDesteklenen sağlayıcılar, ayarlandığında yanıtta token kullanım bilgilerini döndürecektir.", "September": "Eylül", "SerpApi API Key": "SerpApi API Anahtarı", "SerpApi Engine": "SerpApi Motoru", "Serper API Key": "Serper API Anahtarı", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API Anahtarı", "Serpstack API Key": "Serpstack API Anahtarı", "Server connection failed": "Sunucu bağlantısı başarısız", "Server connection verified": "Sunucu bağlantısı doğrulandı", + "Service Account": "", "Session": "Oturum", + "Session expired. Please sign in again.": "", "Set as default": "Varsayılan olarak ayarla", "Set as Production": "Prodüksiyon Olarak Ayarla", "Set embedding model": "Gömme modelini ayarla", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "Bağlantı panoya kopyalandı.", "Share to Open WebUI Community": "OpenWebUI Topluluğu ile Paylaş", "Share your background and interests": "Arka planınızı ve ilgi alanlarınızı paylaşın", + "Shared": "", "Shared Chats": "Paylaşılan Sohbetler", "Shared with you": "Sizinle paylaşılan", "Sharing Permissions": "Paylaşım İzinleri", "Show": "Göster", - "Show \"What's New\" modal on login": "Girişte \"Yenilikler\" modalını göster", + "Show \"What's New\" Modal on Login": "Girişte \"Yenilikler\" modalını göster", "Show Admin Details in Account Pending Overlay": "Yönetici Ayrıntılarını Hesap Bekliyor Ekranında Göster", "Show All": "Tümünü Göster", "Show all ({{COUNT}} characters)": "Tümünü göster ({{COUNT}} karakter)", "Show Files": "Dosyaları Göster", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "Biçimlendirme Araç Çubuğunu Göster", "Show image preview": "Görsel önizlemesini göster", "Show Model": "Modeli Göster", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID'si", "Sougou Search API SK": "Sougou Search API SK'si", "Source": "Kaynak", + "Specific users or groups": "", "Speech Playback Speed": "Konuşma Oynatma Hızı", "Speech recognition error: {{error}}": "Konuşma tanıma hatası: {{error}}", "Speech-to-Text": "Konuşmadan Metne", @@ -1999,6 +2154,7 @@ "STT Settings": "STT Ayarları", "Stylized PDF Export": "Biçimlendirilmiş PDF Dışa Aktarımı", "Su_day_of_week": "Pz", + "Sub Claim": "", "Submit question": "Soru gönder", "Submit suggestion": "Öneri gönder", "Subtitle": "Altyazı", @@ -2023,8 +2179,10 @@ "Syncing...": "Eşitleniyor...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "Sadece son eşitleme zaman damganızdan sonraki güncellemelere sahip sohbetleri eşitler. Tüm sohbetleri yeniden eşitlemek için devre dışı bırakın.", "System": "Sistem", + "System events only": "", "System Instructions": "Sistem Talimatları", "System Prompt": "Sistem Promptu", + "Table": "", "Tag": "Etiket", "Tags": "Etiketler", "Tags Generation": "Etiketler Oluşturma", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "Varsayılan Olarak Geçici Sohbet", "Terminal": "Terminal", "Terminal servers saved": "Terminal sunucuları kaydedildi", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Metin Bölücü", "Text-to-Speech": "Metinden Sese", "Text-to-Speech Engine": "Metinden Sese Motoru", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Giriş sesinin dili. Giriş dilini ISO-639-1 (örn. en) biçiminde sağlamak doğruluğu ve gecikmeyi iyileştirir. Dili otomatik olarak algılamak için boş bırakın.", "The LDAP attribute that maps to the mail that users use to sign in.": "Kullanıcıların oturum açmak için kullandığı e-postaya eşlenen LDAP özniteliği.", "The LDAP attribute that maps to the username that users use to sign in.": "Kullanıcıların oturum açmak için kullandığı kullanıcı adına eşlenen LDAP özniteliği.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Lider tablosu şu anda beta aşamasındadır ve algoritmayı geliştirdikçe derecelendirme hesaplamalarını ayarlayabiliriz.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "MB cinsinden maksimum dosya boyutu. Dosya boyutu bu sınırı aşarsa, dosya yüklenmeyecektir.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Sohbette aynı anda kullanılabilecek maksimum dosya sayısı. Dosya sayısı bu sınırı aşarsa, dosyalar yüklenmeyecektir.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Metin için çıktı biçimi. 'json', 'markdown' veya 'html' olabilir. Varsayılan 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "Bu klasör boş", "This is a default user permission and will remain enabled.": "Bu, varsayılan bir kullanıcı iznidir ve etkin kalacaktır.", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Bu deneysel bir özelliktir, beklendiği gibi çalışmayabilir ve her an değişiklik yapılabilir.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Bu model herkese açık değildir. Lütfen başka bir model seçin.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Bu seçenek, modelin istekten sonra ne kadar süre hafızada yüklü kalacağını kontrol eder (varsayılan: 5d)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Bu seçenek, bağlam yenilenirken kaç tokenin korunacağını kontrol eder. Örneğin 2 olarak ayarlanırsa, konuşma bağlamının son 2 tokeni korunur. Bağlamı korumak, bir konuşmanın sürekliliğinin sağlanmasına yardımcı olabilir, ancak yeni konulara yanıt verme yeteneğini azaltabilir.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Mevcut uç noktalar hakkında daha fazla bilgi edinmek için belgelerimize göz atın.", "To select skills here, add them to the \"Skills\" workspace first.": "Burada yetenek seçmek için önce bunları \"Yetenekler\" çalışma alanına ekleyin.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Araçları burada seçmek için öncelikle bunları \"Araçlar\" çalışma alanına ekleyin.", - "Toast notifications for new updates": "Yeni güncellemeler için anlık bildirimler", + "Toast Notifications for New Updates": "Yeni güncellemeler için anlık bildirimler", "Today": "Bugün", "Today at": "Bugün saat", "Today at {{LOCALIZED_TIME}}": "Bugün saat {{LOCALIZED_TIME}}", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "Geçerli bağlantının etkin olup olmadığını değiştirin.", "Token": "Birim", "Token counts are estimates and may not reflect actual API usage": "Token sayıları tahminidir ve gerçek API kullanımını yansıtmayabilir", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "token", "Tokens": "Tokenler", "Too verbose": "Çok ayrıntılı", @@ -2184,14 +2350,19 @@ "Unpin": "Sabitlemeyi Kaldır", "Unpin from Sidebar": "Kenar Çubuğundan Sabitlemeyi Kaldır", "Unravel secrets": "Sırları çöz", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "Sohbet Paylaşımını Kaldır", "Unsupported file type.": "Desteklenmeyen dosya türü.", "Untagged": "Etiketsiz", "Untitled": "Başlıksız", "Update": "Güncelle", "Update and Copy Link": "Güncelle ve Bağlantıyı Kopyala", + "Update Email": "", "Update for the latest features and improvements.": "En son özellikler ve iyileştirmeler için güncelleyin.", + "Update Name": "", "Update password": "Parolayı Güncelle", + "Update Picture": "", "Update your status": "Durumunuzu güncelleyin", "Updated": "Güncellendi", "Updated at": "Şu tarihte güncellendi:", @@ -2218,13 +2389,18 @@ "Use": "Kullan", "Use '#' in the prompt input to load and include your knowledge.": "Bilginizi yüklemek ve dahil etmek için prompt girişinde '#' kullanın.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "Olası daha iyi doğruluk için /v1/audio/transcriptions yerine /v1/chat/completions uç noktasını kullanın.", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "Sohbet Tamamlama API'sini Kullan", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "Kullanıcılarınızı düzenlemek ve izinler atamak için grupları kullanın.", "Use LLM": "LLM Kullan", "Use no proxy to fetch page contents.": "Sayfa içeriklerini getirmek için proxy kullanmayın.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Sayfa içeriklerini getirmek için http_proxy ve https_proxy ortam değişkenleriyle belirlenen proxy'yi kullanın.", + "Use Web Search?": "", "user": "kullanıcı", "User": "Kullanıcı", + "User Access": "", "User Activity": "Kullanıcı Etkinliği", "User Groups": "Kullanıcı Grupları", "User location successfully retrieved.": "Kullanıcı konumu başarıyla alındı.", @@ -2234,6 +2410,7 @@ "User Status": "Kullanıcı Durumu", "User Webhooks": "Kullanıcı Web Kancaları", "Username": "Kullanıcı Adı", + "Username Claim": "", "users": "kullanıcılar", "Users": "Kullanıcılar", "Uses DefaultAzureCredential to authenticate": "Kimlik doğrulaması için DefaultAzureCredential kullanır", @@ -2247,6 +2424,7 @@ "Valves updated": "Valfler güncellendi", "Valves updated successfully": "Valfler başarıyla güncellendi", "variable": "değişken", + "Vector Field": "", "Verify Connection": "Bağlantıyı Doğrula", "Verify SSL Certificate": "SSL Sertifikasını Doğrula", "Version": "Sürüm", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "Web Yükleyici Motoru", "Web Search": "Web Araması", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Web Arama Motoru", "Web Search in Chat": "Sohbette Web Araması", "Web Search Query Generation": "Web Arama Sorgusu Oluşturma", + "Webhook deleted": "", "Webhook Name": "Web Kancası Adı", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "Web Kancaları", "Webpage URLs": "Web Sayfası URL'leri", "WebUI Settings": "WebUI Ayarları", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "Yandex Web Arama API Anahtarı", "Yandex Web Search config": "Yandex Web Arama Yapılandırması", "Yandex Web Search URL": "Yandex Web Arama URL'si", + "Yearly": "", "Yesterday": "Dün", "Yesterday at {{LOCALIZED_TIME}}": "Dün saat {{LOCALIZED_TIME}}", "You": "Sen", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "Tarayıcınız video etiketini desteklemiyor.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tüm katkınız doğrudan eklenti geliştiricisine gidecektir; Open WebUI herhangi bir yüzde almaz. Ancak seçilen finansman platformunun kendi ücretleri olabilir.", "Your message text or inputs": "Mesaj metniniz veya girdileriniz", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "Kullanım istatistikleriniz başarıyla eşitlendi.", "YouTube": "Youtube", "Youtube Language": "Youtube Dili", diff --git a/src/lib/i18n/locales/ug-CN/translation.json b/src/lib/i18n/locales/ug-CN/translation.json index 22f152b6c2..9207733d04 100644 --- a/src/lib/i18n/locales/ug-CN/translation.json +++ b/src/lib/i18n/locales/ug-CN/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} يوشۇرۇن قۇرلار", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} نىڭ سۆھبەتلىرى", "{{webUIName}} Backend Required": "{{webUIName}} ئارقا سۇپا زۆرۈر", "*Prompt node ID(s) are required for image generation": "رەسىم ھاسىل قىلىش ئۈچۈن تۈرتكە نۇسخا ئۇچۇر ID(لىرى) زۆرۈر", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "زىيارەت باشقۇرۇش", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "بارلىق ئىشلەتكۈچىلەر كىرەلەيدىغان", "Account": "ھېسابات", @@ -72,6 +83,7 @@ "Activity": "", "Add": "قوشۇش", "Add a model ID": "مودېل ID قوشۇش", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "بۇ مودېلنىڭ ئىشلىتىلىشى توغرىسىدا قىسقا چۈشەندۈرۈش قوشۇڭ", "Add a tag": "تەغ قوشۇش", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "ھۆججەتلەر قوشۇش", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "ئىشلەتكۈچى قوشۇش", "Add User Group": "ئىشلەتكۈچى گۇرۇپپىسى قوشۇش", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "باشقۇرغۇچى", "Admin Contact Email": "", "Admin Panel": "باشقۇرغۇچى تاختىسى", + "Admin Roles": "", "Admin Settings": "باشقۇرغۇچى تەڭشەكلىرى", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "باشقۇرغۇچىلارنىڭ ھەممىسى قوراللارنى تولۇق ئىشلىتىش ھوقۇقىغا ئىگە؛ ئىشلەتكۈچىلەرنىڭ ئىشخانىدا مودېلغا باغلانغان قوراللار بولۇشى كېرەك.", "Advanced": "", "Advanced Parameters": "ئالىي پارامېتىرلار", @@ -123,16 +140,21 @@ "All": "ھەممىسى", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "بارلىق مودېللار مۇۋەپپەقىيەتلىك ئۆچۈرۈلدى", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "چاقىرىشقا ئىجازەت", "Allow Chat Controls": "سۆھبەت باشقۇرۇشقا ئىجازەت", "Allow Chat Delete": "سۆھبەت ئۆچۈرۈشكى ئىجازەت", "Allow Chat Edit": "سۆھبەت تەھرىرلەشكە ئىجازەت", "Allow Chat Export": "سۆھبەت چىقىرىشقا ئىجازەت", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "سۆھبەت ھەمبەھىرلىشكە ئىجازەت", "Allow Chat System Prompt": "پاراڭ سىستېمىسى تۈرتكەسىگە ئىجازەت", @@ -152,9 +174,11 @@ "Allow User Location": "ئىشلەتكۈچى ئورنىنى كۆرسىتىشكە ئىجازەت", "Allow Voice Interruption in Call": "چاقىرىشتا ئاۋاز دەخلى قىلىشقا ئىجازەت", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "ئىجازەتلىك ئۇلانمىلار", "Allowed File Extensions": "ئىجازەتلىك ھۆججەت كېڭەيتىلمىلىرى", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "يۈكلەشكە بولىدىغان ھۆججەت كېڭەيتىلمىسى. بىر نەچچىسى بولسا پەش بىلەن ئايرىڭ. بارلىق تىپقا ئىجازەت بولسا بوش قالدۇرۇڭ.", + "Allowed Roles": "", "Already have an account?": "ئاللىقاچان ھېسابىڭىز بارمۇ؟", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Top_p نىڭ ئورنىغا ، سۈپەت ۋە كۆپ خىللىقنىڭ تەڭپۇڭلۇقىغا كاپالەتلىك قىلىشنى مەقسەت قىلىدۇ. P پارامېتىرى ئەڭ چوڭ بەلگە ئېھتىماللىقىغا سېلىشتۇرغاندا ، بەلگە ئويلىنىشنىڭ ئەڭ تۆۋەن ئېھتىماللىقىنى كۆرسىتىدۇ. مەسىلەن ، p = 0.05 ۋە ئېھتىماللىقى ئەڭ يۇقىرى بولغان بەلگە 0.9 بولۇش ئېھتىماللىقى بار ، قىممىتى 0.045 دىن تۆۋەن بولغان خاتىرىلەر سۈزۈلىدۇ.", "Always": "ھەمىشە", @@ -173,6 +197,7 @@ "API Base URL": "API ئاساسىي URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API ئاچقۇچى", + "API Key / Token": "", "API Key created.": "API ئاچقۇچى قۇرۇلدى.", "API Key Endpoint Restrictions": "API ئاچقۇچى ئۇلانما چەكلىمەسى", "API keys": "API ئاچقۇچلىرى", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "بۇ ئۇچۇرنى ئۆچۈرەمسىز؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "بارلىق ئارخىپلانغان سۆھبەتلەرنى قايتا ئەسلىگە كەلتۈرەمسىز؟", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena مودېللىرى", "Artifacts": "ئۇزۇقلار", "Asc": "", "Ask": "سوراڭ", "Ask a question": "سؤئال سوراڭ", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "ياردەمچى", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "ئاۋاز", "August": "ئاۋغۇست", "Auth": "تەستىقلاش", + "Auth Mode": "", + "Auth required": "", "Authenticate": "دەلىللەش", "Authentication": "كىرىش دەلىللەش", "Auto": "ئاپتوماتىك", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "ئىنكاسنى ئۆزلۈكىدىن چاپلاش تاختىسىغا كۆچۈرۈش", - "Auto-playback response": "ئاپتۇماتىك قۇيۇش ئىنكاسى", + "Auto-Create Groups": "", + "Auto-Playback Response": "ئاپتۇماتىك قۇيۇش ئىنكاسى", "Autocomplete Generation": "ئاپتوماتىك تولدۇرۇش", "Autocomplete Generation Input Max Length": "ئاپتوماتىك تولدۇرۇش كىرگۈزۈش ئەڭ چوڭ ئۇزۇنلۇقى", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API دەلىللەش ھەرپ تىزىقى", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 ئاساسىي URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "بار قوراللار", "available users": "ئىشلەتكىلى بولىدىغان ئىشلەتكۈچىلەر", + "Available variables": "", "available!": "بار!", "Away": "يوق", "Awful": "ناچار", @@ -258,16 +295,17 @@ "Bad Response": "خاتا ئىنكاس", "Banners": "لوزۇنكىلار", "Base Model (From)": "ئاساسىي مودېل (مەنبە)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "بۇرۇن", "Being lazy": "ھورۇن بۇلۇش", - "Beta": "بەتا", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 ئۇلانمىسى", "Bing Search V7 Subscription Key": "Bing Search V7 ئەزا ئاچقۇچى", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Bocha ئىزدەش API ئاچقۇچى", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "سۆھبەت يۆنىلىشى", + "Chat Direction": "سۆھبەت يۆنىلىشى", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "يىغىش", "Collection": "توپلام", + "Collection Field": "", "Collections": "", "Color": "رەڭ", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI جەريانى", "ComfyUI Workflow Nodes": "ComfyUI جەريان ئۇچۇرلىرى", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "بۇيرۇق", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "تولۇقلىنىشلار", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "ئۆزىڭىزنىڭ OpenAI غا ماس كېلىدىغان API ئۇلانمىلىرىڭىزغا باغلىنىڭ.", "Connect to your own OpenAPI compatible external tool servers.": "OpenAPI ماس كېلىدىغان سىرتقى قورال مۇلازىمېتىرلىرىغا باغلىنىڭ.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "ئۇلىنىش مەغلۇپ بولدى", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUI كىرىش ئۈچۈن باشقۇرغۇچى بىلەن ئالاقىلىشىڭ", "Content": "مەزمۇن", "Content Extraction Engine": "مەزمۇن چىقىرىش ماتورى", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ئىنكاسنى داۋاملاشتۇرۇش", "Continue with {{provider}}": "{{provider}} داۋاملاشتۇرۇش", "Continue with Email": "ئېلخەت بىلەن داۋاملاشتۇرۇش", @@ -493,6 +543,7 @@ "Create new secret key": "يېڭى مەخپىي ئاچقۇچ قۇرۇش", "Create note": "", "Create Note": "خاتىرە قۇرۇش", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "تۆۋەندىكى قوشۇش كۇنۇپكىسىنى چېكىپ بىرىنچى خاتىرىڭىزنى قۇرۇڭ.", "Created at": "قۇرۇلغان ۋاقتى", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "ئۆزلۈك پارامېتىر نامى", "Custom Parameter Value": "ئۆزلۈك پارامېتىر قىممىتى", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "خەۋپلىك رايون", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "سۈكۈتتىكى ھالەت ئىجرا قىلىنىشتىن بۇرۇن بىر قېتىم چاقىرىش قوراللىرى ئارقىلىق تېخىمۇ كەڭ مودېللار بىلەن ئىشلەيدۇ. يەرلىك ھالەت مودېلنىڭ ئىچىگە قورال چاقىرىش ئىقتىدارىنى جارى قىلدۇرىدۇ ، ئەمما مودېلنىڭ بۇ ئىقتىدارنى ئەسلىدىنلا قوللىشىنى تەلەپ قىلىدۇ.", "Default Model": "كۆڭۈلدىكى مودېل", "Default model updated": "كۆڭۈلدىكى مودېل يېڭىلاندى", "Default permissions": "كۆڭۈلدىكى ھوقۇق", @@ -542,6 +593,7 @@ "Default to ALL": "كۆڭۈلدىكى ALL", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "تېخىمۇ مۇناسىپ ۋە مۇھىم مەزمۇن چىقىرىش ئۈچۈن بۆلەكلىك قايتۇرۇش كۆڭۈلدىكى قىلىنغان، كۆپىنچە ئەھۋاللاردا تەۋسىيە قىلىنىدۇ.", "Default User Role": "كۆڭۈلدىكى ئىشلەتكۈچى رولى", + "Default webhook": "", "Defaults": "", "Delete": "ئۆچۈرۈش", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "رەسىم چىقىرىشنى چەكلە", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF دىن رەسىم چىقىرىش چەكلىنىدۇ. LLM ئىشلىتىلسە، رەسىملەر ئاپتوماتىك تېمىغا ئىگە بولىدۇ. كۆڭۈلدىكىچە چەكلەنمەيدۇ.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "چەكلەنگەن", "Disconnect OAuth": "", "Discover a function": "فۇنكسىيە تاپ", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "مودېل ئالدىن تەڭشەكلىرىنى تاپ، چۈشۈر، تەتقىق قىل", "Discussion channel where access is based on groups and permissions": "", "Display": "كۆرسىتىش", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "چاقىرىشتا ئېموجىنى كۆرسىتىش", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "سۆھبەتتە 'سىز' ئورنىغا ئىشلەتكۈچى ئىسمىنى كۆرسىتىش", + "Display the Username Instead of You in the Chat": "سۆھبەتتە 'سىز' ئورنىغا ئىشلەتكۈچى ئىسمىنى كۆرسىتىش", "Displays citations in the response": "ئىنكاستا نەقىللەرنى كۆرسىتىدۇ", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "بىلىمگە چۆمۈلۈڭ", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Docling مۇلازىمېتىر URL زۆرۈر.", "Document": "ھۆججەت", + "Document ID Field": "", "Document Intelligence": "ھۆججەت ئەقىل", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "كۆڭۈلدىكى ھوقۇقلارنى تەھرىرلەش", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "ئەسلەتمە تەھرىرلەش", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "ئىشلەتكۈچى تەھرىرلەش", "Edit User Group": "ئىشلەتكۈچى گۇرۇپپىسى تەھرىرلەش", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "ئېلخەت", + "Email Claim": "", "Embark on adventures": "سەيياھەتنى باشلاڭ", "Embedding": "سىڭدۈرۈش", "Embedding Batch Size": "سىڭدۈرۈش توپ چوڭلۇقى", @@ -707,6 +765,7 @@ "Embedding Model Engine": "سىڭدۈرۈش مودېل ماتورى", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "كود ئىجرا قىلىشننى قوزغىتىش", "Enable Code Interpreter": "كود تەرجىمانىنى قوزغىتىش", "Enable Community Sharing": "جەمئىيەت ھەمبەھىرلىشىشى قوزغىتىش", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "ئىچكى ساقلىغۇچ قۇلۇپلاش (mlock) نى قوزغىتىپ ، مودېل سانلىق مەلۇماتلارنىڭ ئىچكى ساقلىغۇچنىڭ ئالماشتۇرۇلىشىنىڭ ئالدىنى ئالىدۇ. بۇ تاللانما مودېلنىڭ خىزمەت بەتلىرىنى RAM غا قۇلۇپلاپ ، ئۇلارنىڭ دىسكىغا ئالماشتۇرۇلماسلىقىغا كاپالەتلىك قىلىدۇ. بۇ بەتتىكى خاتالىقلاردىن ساقلىنىش ۋە سانلىق مەلۇماتلارنىڭ تېز زىيارەت قىلىنىشىغا كاپالەتلىك قىلىش ئارقىلىق ئىقتىدارنى ساقلاشقا ياردەم بېرىدۇ.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "مودېل سانلىق مەلۇماتىنى يۈكلەش ئۈچۈن Memory Mapping (mmap) قوزغىتىڭ. بۇ تاللاش دىسكىنى RAM غا ئوخشاش ئىشلىتىش ئارقىلىق تېز سانلىق مەلۇمات زىيارىتىنى تەمىنلەيدۇ. ئەمما بارلىق سىستېمىلاردا مۇۋاپىق كەلمەسلىكى ۋە كۆپ دىسكا بوشلۇقى ئىشلىتىشى مۇمكىن.", "Enable Message Queue": "", "Enable Message Rating": "ئۇچۇر باھالاشنى قوزغىتىش", "Enable Mirostat sampling for controlling perplexity.": "Perplexity نى باشقۇرۇش ئۈچۈن Mirostat ئەۋرىشىلىگۈچنى قوزغىتىش", "Enable New Sign Ups": "يېڭى تىزىملىتىشنى قوزغىتىش", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "قوزغىتىلغان", "End Tag": "", + "Endpoint": "", "Endpoint URL": "ئۇلانما URL", "Enforce Temporary Chat": "ۋاقىتلىق سۆھبەتنى مەجبۇرىي قىلىش", "Enhance": "ياخشىلا", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV ھۆججىتىڭىز تۆت تۈردىكى ئۇچۇرنى بۇ تەرتىپتە ئۆز ئىچىگە ئالىدۇ: ئات، ئېلخەت، پارول، رول.", "Enter {{role}} message here": "{{role}} ئۇچۇرنى بۇ يەرگە كىرگۈزۈڭ", - "Enter a detail about yourself for your LLMs to recall": "LLM ىڭىزنىڭ سىزنى ئېسىدە ساقلاش ئۈچۈن ئۆزىڭىز ھەققىدە بىر ئۇچۇر كىرگۈزۈڭ", "Enter a title for the pending user info overlay. Leave empty for default.": "كۈتۈۋاتقان ئىشلەتكۈچى ئۇچۇر قاپلىمىسى ئۈچۈن تېما كىرگۈزۈڭ. كۆڭۈلدىكى ئۈچۈن بوش قالدۇرۇڭ.", "Enter a watermark for the response. Leave empty for none.": "ئىنكاس ئۈچۈن سۇ بەلگىسى كىرگۈزۈڭ. يوق بولسا بوش قالدۇرۇڭ.", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "پارچە قاپلىنىشى كىرگۈزۈڭ", "Enter Chunk Size": "پارچە چوڭلۇقى كىرگۈزۈڭ", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "پۈتتۈر بىلەن ئايرىلغان \"token:bias_value\" جۈپىنى كىرگۈزۈڭ (مەسىلەن: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "كۈتۈۋاتقان ئىشلەتكۈچى ئۇچۇر قاپلىمىسى ئۈچۈن مەزمۇن كىرگۈزۈڭ. كۆڭۈلدىكى ئۈچۈن بوش قالدۇرۇڭ.", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter URL كىرگۈزۈڭ", "Enter Kagi Search API Key": "Kagi ئىزدەش API ئاچقۇچى كىرگۈزۈڭ", "Enter Key Behavior": "ئاچقۇچ ئىشلىتىش ئۇسۇلى كىرگۈزۈڭ", + "Enter language": "", "Enter language codes": "تىل كودلىرى كىرگۈزۈڭ", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Mistral API ئاچقۇچى كىرگۈزۈڭ", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "ۋاكالەتچى URL كىرگۈزۈڭ (مەسىلەن: https://user:password@host:port)", "Enter reasoning effort": "چۈشەندۈرۈش كۈچى كىرگۈزۈڭ", + "Enter Redirect URI": "", "Enter Score": "باھا كىرگۈزۈڭ", "Enter SearchApi API Key": "SearchApi API ئاچقۇچى كىرگۈزۈڭ", "Enter SearchApi Engine": "SearchApi ماتورى كىرگۈزۈڭ", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API ئاچقۇچى كىرگۈزۈڭ", "Enter SerpApi Engine": "SerpApi ماتورى كىرگۈزۈڭ", "Enter Serper API Key": "Serper API ئاچقۇچى كىرگۈزۈڭ", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API ئاچقۇچى كىرگۈزۈڭ", "Enter Serpstack API Key": "Serpstack API ئاچقۇچى كىرگۈزۈڭ", "Enter server host": "مۇلازىمېتىر ئادرېسى كىرگۈزۈڭ", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Tika مۇلازىمېتىر URL كىرگۈزۈڭ", "Enter timeout in seconds": "ۋاقىت چەكلىمىسى كىرگۈزۈڭ (سېكۇنت)", "Enter to Send": "يوللاش ئۈچۈن Enter ئاساسىڭ", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K كىرگۈزۈڭ", "Enter Top K Reranker": "Top K قايتا تەرتىپلەش كىرگۈزۈڭ", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL كىرگۈزۈڭ (مەسىلەن: http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "باھالاشلار", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API ئاچقۇچى", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "مەسىلەن: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "مەسىلەن: ALL", "Example: mail": "مەسىلەن: mail", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CSV غا چىقىرىش", "Export Tools": "", "Export Users": "", "External": "سىرتقى", + "External connection not found.": "", "External Document Loader URL required.": "سىرتقى ھۆججەت يۈكلىگۈچ URL زۆرۈر.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "سىرتقى ۋەزىپە مودېلى", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "سىرتقى تور يۈكلىگۈچ API ئاچقۇچى", "External Web Loader URL": "سىرتقى تور يۈكلىگۈچ URL", "External Web Search API Key": "سىرتقى تور ئىزدەش API ئاچقۇچى", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API ئاچقۇچى قۇرۇش مەغلۇپ بولدى.", "Failed to delete calendar": "", "Failed to delete note": "خاتىرە ئۆچۈرۈش مەغلۇپ بولدى", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "مودېللارنى ئېلىش مەغلۇپ بولدى", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "چاپلاش تاختىسى مەزمۇنىنى ئوقۇش مەغلۇپ بولدى", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "مودېل تەڭشەكلىرىنى ساقلاش مەغلۇپ بولدى", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "تەڭشەكلەرنى يېڭىلاش مەغلۇپ بولدى", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "ھۆججەت چىقىرىش مەغلۇپ بولدى.", "Features": "ئىقتىدارلار", "Features Permissions": "ئىقتىدار ھوقۇقى", @@ -987,6 +1075,8 @@ "File uploaded successfully": "ھۆججەت مۇۋەپپەقىيەتلىك چىقىرىلدى", "Filename": "", "Files": "ھۆججەتلەر", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "سۈزگۈچ ھازىر بارلىق سىستېمىدا چەكلەندى", "Filter is now globally enabled": "سۈزگۈچ ھازىر بارلىق سىستېمىدا قوزغىتىلدى", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "داۋامى", "Follow Up Generation": "داۋاملاشتۇرۇش ھاسىل قىلىش", "Follow Up Generation Prompt": "داۋاملاشتۇرۇش ھاسىل قىلىش تۈرتكەسى", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "فۇنكسىيە ھازىر بارلىق سىستېمىدا قوزغىتىلدى", "Function Name": "فۇنكسىيە نامى", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "فۇنكسىيە مۇۋەپپەقىيەتلىك يېڭىلاندى", "Functions": "فۇنكسىيەلەر", "Functions allow arbitrary code execution.": "فۇنكسىيەلەر خالىغان كود ئىجرا قىلىشقا يول قويىدۇ.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "گۇرۇپپا مۇۋەپپەقىيەتلىك قۇرۇلدى", "Group deleted successfully": "گۇرۇپپا مۇۋەپپەقىيەتلىك ئۆچۈرۈلدى", "Group Description": "گۇرۇپپا چۈشەندۈرۈشى", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "ئىجابىي ئۇقتۇرۇش", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox فورمىلارغا ئىجازەت", "iframe Sandbox Allow Same Origin": "iframe Sandbox بىر مەنبەلىككە ئىجازەت", @@ -1138,6 +1236,7 @@ "Import From Link": "ئۇلانمىدىن ئىمپورت قىلىش", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "مۇھىم يېڭىلانىش", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "يانتاختىدا ساقلا", "Key": "ئاچقۇچ", "Key is required": "", - "Keyboard shortcuts": "تىزلەتمىلەر", "Keyboard Shortcuts": "", "Knowledge": "بىلىم", "Knowledge Access": "بىلىم زىيارىتى", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "بىلىمنى ئاممىغا ھەمبەھىرلەش", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "بىلىم مۇۋەپپەقىيەتلىك يېڭىلاندى", "Kokoro.js (Browser)": "Kokoro.js (تور كۆرگۈچ)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "ئاخىرقى ئىنكاس", "LDAP": "LDAP", - "LDAP server updated": "LDAP مۇلازىمېتىر يېڭىلاندى", "Leaderboard": "توردىكى رېتىڭ", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "كېنىشكا", + "Lifecycle JSON": "", "Lift List": "", "Light": "نۇر", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "ئورۇن زىيارىتىغا ئىجازەت يوق", "Lost": "يوقاپ كەتتى", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR (سولدىن ئوڭغا)", "Made by Open WebUI Community": "Open WebUI جەمئىيىتى تەرىپىدىن قۇرۇلغان", "Make password visible in the user interface": "ئىشلەتكۈچى ئۈستىلىدە پارول كۆرسىتىش", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "جەريانلارنى باشقۇرۇش", "Manage Tool Servers": "قورال مۇلازىمېتىرلىرى باشقۇرۇش", "Manage your account information.": "", + "Mapped Source": "", "March": "مارت", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "ئەسلەتمە مۇۋەپپەقىيەتلىك تازىلاندى", "Memory deleted successfully": "ئەسلەتمە مۇۋەپپەقىيەتلىك ئۆچۈرۈلدى", "Memory updated successfully": "ئەسلەتمە مۇۋەپپەقىيەتلىك يېڭىلاندى", + "Merge Accounts by Email": "", "Merge Responses": "ئىنكاسلارنى بىرلەشتۈرۈش", "Merged Response": "بىرلەشتۈرۈلگەن ئىنكاس", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "ئۇلانما قۇرغاندىن كېيىن يوللىغان ئۇچۇرلار ھەمبەھىرلەنمەيدۇ. URL غا ئىگە ئىشلەتكۈچىلەر ھەمبەھىرلەنگەن سۆھبەتنى كۆرەلەيدۇ.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (شەخسىي)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (خىزمەت/مەكتىپ)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Mojeek ئىزدەش API ئاچقۇچى", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "تېخىمۇ كۆپ", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "بىلىم ئاساسى نامىنى كىرگۈزۈڭ", "Name, prompt, and model are required": "", "Native": "يەرلىك", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "ئارىلىق ئۇچۇرى يوق", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "ھۆججەت تاللانمىدى", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "نەتىجە تېپىلمىدى", "No results found": "نەتىجە تېپىلمىدى", "No search query generated": "ئىزدەش سۇئالى ھاسىل قىلىنمىدى", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "يوق", + "Not configured": "", "Not factually correct": "ھەقىقى بولمىغان", "Not helpful": "پايدىسى يوق", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "ئۇقتۇرۇشلار", "November": "نويابىر", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "ئۆكتەبىر", "Off": "تاقالغان", "Okay, Let's Go!": "ماقۇل، باشلايلى!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED قاراڭغۇ", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API تەڭشەكلىرى يېڭىلاندى", "Ollama Cloud API Key": "", "Ollama Version": "Ollama نەشرى", + "Omit": "", "On": "قوزغىتىلغان", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "پارول", "Passwords do not match.": "", "Paste Large Text as File": "چوڭ تېكستنى ھۆججەت قىلىپ چاپلا", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF ھۆججىتى (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "كۈتۈۋاتىدۇ", "Pending": "كۈتۈۋاتىدۇ", + "Pending Accounts": "", "Pending User Overlay Content": "كۈتۈۋاتقان ئىشلەتكۈچى قاپلام مەزمۇنى", "Pending User Overlay Title": "كۈتۈۋاتقان ئىشلەتكۈچى قاپلام تېمىسى", "Permission denied when accessing media devices": "كۆپ-ۋاستە ئۈسكۈنىلىرىگە كىرىش چەكلەندى", "Permission denied when accessing microphone": "مىكروفونغا كىرىش چەكلەندى", "Permission denied when accessing microphone: {{error}}": "مىكروفونغا كىرىش چەكلەندى: {{error}}", "Permissions": "ھوقۇق", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API ئاچقۇچى", "Perplexity Model": "Perplexity مودېلى", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "Perplexity ئىزدەش مۇھىتى ئىشلىتىش", "Persistent": "", "Personalization": "شەخسىيلاشتۇرۇش", + "Picture Claim": "", "Pin": "مۇقىملا", "Pin to Sidebar": "", "Pinned": "مۇقىملاندى", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "بارلىق رايونلارنى تولدۇرۇڭ.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "ئالدى بىلەن مودېل تاللاڭ.", "Please select a model.": "مودېل تاللاڭ.", "Please select a reason": "سەۋەب تاللاڭ", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "ئېغىز", "Ports": "", "Positive attitude": "ئىجابىي پوزىتسىيە", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "تۈرتكە ئاممىغا ھەمبەھىرلەش", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "ئاممىۋى", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com دىن \"{{searchValue}}\" نى تارتىش", "Pull a model from Ollama.com": "Ollama.com دىن مودېل تارتىش", @@ -1687,21 +1811,29 @@ "Read": "ئوقۇش", "Read Aloud": "ئوقۇپ ئېيتىش", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "سەۋەب", "Reasoning Effort": "چۈشەندۈرۈش كۈچى", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "خاتىرىلەش", "Record voice": "ئاۋاز خاتىرىلەش", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Open WebUI جەمئىيىتىگە يوللاندى", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "ئاساسسىز ئىنكاس چىقىرىشىنىڭ ئېھتىماللىقىنى ئازايتىدۇ. چوڭ قىممەت (مەسىلەن: 100) كۆپ خىل ئىنكاس، كىچىك قىممەت (مەسىلەن: 10) تېخىمۇ مۇقىم ئىنكاس بېرىدۇ.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "ئۆزىڭىزنى \"ئىشلەتكۈچى\" دەپ ئاتىڭ (مەسىلەن: \"ئىشلەتكۈچى ئىسپانچە ئۆگىنىۋاتىدۇ\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "رەت قىلماسلىق كېرەك ئىدى", "Regenerate": "قايتا ھاسىل قىلىش", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "مودېللارنى قايتا تەرتىپلەش", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "تارماقتا ئىنكاس قايتۇرۇش", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "قايتا تەرتىپلەش ماتورى", "Reranking Model": "قايتا تەرتىپلەش مودېلى", + "Research Knowledge": "", "Reset": "قايتا تەڭشەش", "Reset All Models": "بارلىق مودېللارنى قايتا تەڭشەش", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "سۈرەتنى ئەسلىگە قايتۇر", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "چىقىرىش قىسقۇچىنى قايتا تەڭشەش", "Reset Vector Storage/Knowledge": "ۋېكتور ساقلاش/بىلىمنى قايتا تەڭشەش", "Reset view": "كۆرۈنۈشنى قايتا تەڭشەش", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "سۆھبەت ئۈچۈن مول تېكست كىرگۈزۈش", "Role": "رول", + "Roles Claim": "", "RTL": "RTL (ئوڭدىن سولغا)", "Run": "ئىجرا قىلىش", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "پاراڭ خاتىرىسىنى بىۋاسىتە توركۆرگۈڭىزنىڭ ساقلىشىغا ساقلىغىلى بولمايدۇ. بىر ئاز ۋاقىت چىقىرىپ ئاستىدىكى كۇنۇپكىنى بېسىپ پاراڭ خاتىرىڭىزنى چۈشۈرۈڭ ۋە ئۆچۈرۈڭ. ئەنسىرىمەڭ ، پاراڭ خاتىرىڭىزنى ئارقا سۇپىغا قايتا ئەكىرىسىز", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "تارماق ئۆزگەرسە ئېكران يۆتكىلىدۇ", "Scroll to Top": "", "Search": "ئىزدەش", "Search a model": "مودېل ئىزدەش", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "سۆھبەت ئىزدەش", "Search Collection": "توپلام ئىزدەش", "Search Files": "", + "Search filters": "", "Search Filters": "سۈزگۈچ ئىزدەش", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "مودېللارنى ئىزدەش", "Search Notes": "", "Search options": "ئىزدەش تاللاشلىرى", + "Search or add pattern": "", "Search Prompts": "تۈرتكە ئىزدەش", "Search Result Count": "ئىزدەش نەتىجىسى سانى", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "تور ئىزدەش", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "قوراللارنى ئىزدەش", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API ئاچقۇچى", "SearchApi Engine": "SearchApi ماتورى", @@ -1834,7 +1980,6 @@ "Seed": "ئۇرۇق", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "ئاساسىي مودېل تاللاڭ", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "ماتور تاللاڭ", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "يوللاش", "Send a Message": "ئۇچۇر يوللاڭ", + "Send events for": "", "Send message": "ئۇچۇر يوللاڭ", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "تەلەپكە `stream_options: { include_usage: true }` يوللايدۇ.\nقوللايدىغان تەمىنلىگۈچى ئىنكاستا ئىم ئىشلىتىش ئۇچۇرى قايتۇرىدۇ.", "September": "سېنتەبىر", "SerpApi API Key": "SerpApi API ئاچقۇچى", "SerpApi Engine": "SerpApi ماتورى", "Serper API Key": "Serper API ئاچقۇچى", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API ئاچقۇچى", "Serpstack API Key": "Serpstack API ئاچقۇچى", "Server connection failed": "", "Server connection verified": "مۇلازىمېتىر ئۇلىنىشى جەزملەندى", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "كۆڭۈلدىكى قىلىش", "Set as Production": "", "Set embedding model": "سىڭدۈرۈش مودېلى تەڭشەش", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Open WebUI جەمئىيىتىگە ھەمبەھىرلەش", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "ھەمبەھىرلەش ھوقۇقى", "Show": "كۆرسىتىش", - "Show \"What's New\" modal on login": "كىرىشتە \"يېڭىلىق\" مودىلىنى كۆرسىتىش", + "Show \"What's New\" Modal on Login": "كىرىشتە \"يېڭىلىق\" مودىلىنى كۆرسىتىش", "Show Admin Details in Account Pending Overlay": "ھېسابات كۈتۈۋاتقان قاپلىماسىدا باشقۇرغۇچى تەپسىلاتىنى كۆرسىتىش", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "مودېل كۆرسىتىش", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou ئىزدەش API sID", "Sougou Search API SK": "Sougou ئىزدەش API SK", "Source": "مەنبە", + "Specific users or groups": "", "Speech Playback Speed": "ئاۋاز قۇيۇش تېزلىكى", "Speech recognition error: {{error}}": "ئاۋازنى تونۇش خاتالىقى: {{error}}", "Speech-to-Text": "ئاۋازدىن تېكستكە", @@ -1999,6 +2154,7 @@ "STT Settings": "STT تەڭشەكلىرى", "Stylized PDF Export": "ئۇسلۇبلۇق PDF چىقىرىش", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "سىستېما", + "System events only": "", "System Instructions": "سىستېما كۆرسىتىلمىسى", "System Prompt": "سىستېما تۈرتكەسى", + "Table": "", "Tag": "", "Tags": "تەغلەر", "Tags Generation": "تەغ ھاسىل قىلىش", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "تېكست بۆلگۈچ", "Text-to-Speech": "تېكستتىن ئاۋازغا", "Text-to-Speech Engine": "تېكست ئاۋاز ماتورى", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "كىرگۈزۈش ئاۋاز تىلى. ISO-639-1 (مەسىلەن: en) بويىچە كىرگۈزسىڭىز دەلىقلىقى ۋە تېزلىكى يۇقىرى بولىدۇ. بوش قالدۇرساڭىز ئاپتوماتىك بايقىتىدۇ.", "The LDAP attribute that maps to the mail that users use to sign in.": "ئىشلەتكۈچى كىرىش ئۈچۈن ئىشلىتىدىغان LDAP ئېلخەت خاسلىقى.", "The LDAP attribute that maps to the username that users use to sign in.": "ئىشلەتكۈچى كىرىش ئۈچۈن ئىشلىتىدىغان LDAP ئىسمى خاسلىقى.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "رېتىڭ تىزىملىكى ھازىر بەتا. ئالگورىتمنى ياخشىلىغاندا باھا ھېسابلىنىشى ئۆزگەرتىلىشى مۇمكىن.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "ھۆججەتنىڭ ئەڭ چوڭ چوڭلۇقى (MB). چەكتىن ئېشىپ كەتسى، چىقىرىلمىيدۇ.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "سۆھبەتتە بىرى ۋاقىتتا ئىشلىتىشكە بولىدىغان ھۆججەت ئەڭ كۆپ سانى. چەكتىن ئېشىپ كەتسى، چىقىرىلمىيدۇ.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "تېكست چىقىرىش قېلىپى. 'json', 'markdown', ياكى 'html' بولىدۇ. كۆڭۈلدىكى 'markdown'.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "بۇ تاجرىبىلىك ئىقتىدار، ناتوقرا ئىشلەش ياكى خالىغان ۋاقىتتا ئۆزگىرىشى مۇمكىن.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "بۇ مودېل ئاممىغا ئېلان قىلىنمىغان. باشقا مودېل تاللاڭ.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "بۇ تاللاش مودېل تەلەپتىن كېيىن ئەسلەتكۈچتە قانچىلىك ساقلىنىدىغانلىقىنى باشقۇرىدۇ (كۆڭۈلدىكى: 5 مىنۇت)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "بۇ تاللاش مەزمۇن يېڭىلانغاندا قانچە ئىم ساقلىنىدىغانلىقىنى بەلگىلەيدۇ. مەسىلەن، 2 بولسا، سۆھبەتنىڭ ئاخىرقى 2 ئىمىنى ساقلايدۇ. مۇھىت ساقلىش سۆھبەتنىڭ ئۇلاشقىلىقلىقىغا پايدىلىق، بىراق يېڭى تېمىغا ئىنكاس كۈچىنى ئازايتىدۇ.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "ئىشلىتىشكە بولىدىغان ئۇلانمىلار ھەققىدە تېخىمۇ كۆپ بىلىش ئۈچۈن قوللانمىمىزغا قاراڭ.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "بۇ يەردىن قورال تاللاش ئۈچۈن ئالدى بىلەن \"قورال\" ئىشخانىغا قوشۇڭ.", - "Toast notifications for new updates": "يېڭىلىق ئۇقتۇرۇشى (toast)", + "Toast Notifications for New Updates": "يېڭىلىق ئۇقتۇرۇشى (toast)", "Today": "بۈگۈن", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "ھازىرقى ئۇلىنىشنىڭ ئاكتىپ ياكى ئەمەسلىكىنى ئالماشتۇرۇش.", "Token": "ئىم", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "بەك ئۇزۇن", @@ -2184,14 +2350,19 @@ "Unpin": "مۇقىملانمىغان قىلىش", "Unpin from Sidebar": "", "Unravel secrets": "سىرنى ئاچ", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "تەغسىز", "Untitled": "تېماسىز", "Update": "يېڭىلاش", "Update and Copy Link": "يېڭىلاش ۋە ئۇلانما كۆچۈرۈش", + "Update Email": "", "Update for the latest features and improvements.": "ئەڭ يېڭى ئىقتىدار ۋە ياخشىلاشلار ئۈچۈن يېڭىلاڭ.", + "Update Name": "", "Update password": "پارول يېڭىلاش", + "Update Picture": "", "Update your status": "", "Updated": "يېڭىلاندى", "Updated at": "يېڭىلانغان ۋاقتى", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "بىلىمىڭىزنى يوللاش ئۈچۈن تۈرتكە كىرگۈزۈشىدە '#' ئىشلەتسىڭىز بولىدۇ.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "LLM ئىشلىتىش", "Use no proxy to fetch page contents.": "ۋاكالەتچىسىز بەت مەزمۇنىنى ئېلىش.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "http_proxy ۋە https_proxy مۇھىت ئۆزگەرگۈچ بويىچە بەت مەزمۇنى ئېلىش.", + "Use Web Search?": "", "user": "ئىشلەتكۈچى", "User": "ئىشلەتكۈچى", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "ئىشلەتكۈچى ئورنى مۇۋەپپەقىيەتلىك ئېلىندى.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "ئىشلەتكۈچى Webhookلىرى", "Username": "ئىشلەتكۈچى نامى", + "Username Claim": "", "users": "", "Users": "ئىشلەتكۈچىلەر", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "كرانلار يېڭىلاندى", "Valves updated successfully": "كرانلار مۇۋەپپەقىيەتلىك يېڭىلاندى", "variable": "ئۆزگەرگۈچ", + "Vector Field": "", "Verify Connection": "ئۇلىنىشنى جەزملەش", "Verify SSL Certificate": "SSL كىنىشكىسىنى جەزملەش", "Version": "نەشر", @@ -2276,11 +2454,14 @@ "Web API": "تور API", "Web Loader Engine": "تور يۈكلىگۈچ ماتورى", "Web Search": "تور ئىزدەش", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "تور ئىزدەش ماتورى", "Web Search in Chat": "سۆھبەتتە تور ئىزدەش", "Web Search Query Generation": "تور ئىزدەش سۇئالى ھاسىل قىلىش", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI تەڭشەكلىرى", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "تۈنۈگۈن", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "سىز", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "تۆلەم پۇلىڭىز بىۋاسىتە قىستۇرما تەرەققىياتچىسىغا بېرىلىدۇ؛ Open WebUI ھېچقانداق پىرسېنت ئالمايدۇ. بىراق تاللانغان مالىيە پلاتفورمىسىنىڭ ئۆزىنىڭ ھەققى بولۇشى مۇمكىن.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube تىلى", diff --git a/src/lib/i18n/locales/uk-UA/translation.json b/src/lib/i18n/locales/uk-UA/translation.json index ce630d0396..9280e3ef16 100644 --- a/src/lib/i18n/locales/uk-UA/translation.json +++ b/src/lib/i18n/locales/uk-UA/translation.json @@ -18,6 +18,14 @@ "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_few": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_many": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_few": "", + "{{count}} filters_many": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_few": "", + "{{count}} groups_many": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} прихованих рядків", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -31,12 +39,18 @@ "{{count}} selected_many": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_few": "", + "{{count}} users_many": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -44,8 +58,10 @@ "{{user}}'s Chats": "Чати {{user}}а", "{{webUIName}} Backend Required": "Необхідно підключення бекенду {{webUIName}}", "*Prompt node ID(s) are required for image generation": "*Для генерації зображення потрібно вказати ідентифікатор(и) вузла(ів)", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -63,6 +79,7 @@ "Access Control": "Контроль доступу", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Доступно всім користувачам", "Account": "Обліковий запис", @@ -78,6 +95,7 @@ "Activity": "", "Add": "Додати", "Add a model ID": "Додайти ID моделі", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Додайте короткий опис того, що робить ця модель", "Add a tag": "Додайти тег", "Add a tag...": "", @@ -90,8 +108,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Додати файли", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -106,6 +126,7 @@ "Add to favorites": "", "Add User": "Додати користувача", "Add User Group": "Додати групу користувачів", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -118,7 +139,9 @@ "Admin": "Адмін", "Admin Contact Email": "", "Admin Panel": "Адмін-панель", + "Admin Roles": "", "Admin Settings": "Адмін-панель", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Адміністратори мають доступ до всіх інструментів у будь-який час; користувачам потрібні інструменти, призначені для кожної моделі в робочій області.", "Advanced": "", "Advanced Parameters": "Розширені параметри", @@ -129,16 +152,21 @@ "All": "Усі", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Усі моделі видалені успішно", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Дозволити керування чатом", "Allow Chat Delete": "Дозволити видалення чату", "Allow Chat Edit": "Дозволити редагування чату", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -158,9 +186,11 @@ "Allow User Location": "Доступ до місцезнаходження", "Allow Voice Interruption in Call": "Дозволити переривання голосу під час виклику", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Дозволені кінцеві точки", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Вже є обліковий запис?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Альтернатива top_p, що спрямована на забезпечення балансу між якістю та різноманітністю. Параметр p представляє мінімальну ймовірність для врахування токена відносно ймовірності найбільш ймовірного токена. Наприклад, при p=0.05 і ймовірності найбільш ймовірного токена 0.9, логіти зі значенням менше 0.045 відфільтровуються.", "Always": "Завжди", @@ -179,6 +209,7 @@ "API Base URL": "URL-адреса API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Ключ API", + "API Key / Token": "", "API Key created.": "Ключ API створено.", "API Key Endpoint Restrictions": "Обмеження кінцевої точки ключа API", "API keys": "Ключі API", @@ -208,13 +239,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Ви впевнені, що хочете видалити це повідомлення?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Ви впевнені, що хочете розархівувати усі архівовані чати?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Моделі Arena", "Artifacts": "Артефакти", "Asc": "", "Ask": "Запитати", "Ask a question": "Задати питання", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Асистент", "Async Embedding Processing": "", "At time of event": "", @@ -229,14 +265,20 @@ "Audio": "Аудіо", "August": "Серпень", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Автентифікувати", "Authentication": "Аутентифікація", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Автокопіювання відповіді в буфер обміну", - "Auto-playback response": "Автоматичне відтворення відповіді", + "Auto-Create Groups": "", + "Auto-Playback Response": "Автоматичне відтворення відповіді", "Autocomplete Generation": "Генерація автозаповнення", "Autocomplete Generation Input Max Length": "Максимальна довжина введення для генерації автозаповнення", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Рядок авторизації API", "AUTOMATIC1111 Base URL": "URL-адреса AUTOMATIC1111", @@ -254,6 +296,7 @@ "Available Skills": "", "Available Tools": "", "available users": "доступні користувачі", + "Available variables": "", "available!": "доступно!", "Away": "Відсутній", "Awful": "Жахливо", @@ -264,16 +307,17 @@ "Bad Response": "Неправильна відповідь", "Banners": "Прапори", "Base Model (From)": "Базова модель (від)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "до того, як", "Being lazy": "Не поспішати", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Точка доступу Bing Search V7", "Bing Search V7 Subscription Key": "Ключ підписки Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Ключ API пошуку Bocha", "Bold": "", @@ -330,7 +374,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Напрям чату", + "Chat Direction": "Напрям чату", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -402,6 +446,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Згорнути", "Collection": "Колекція", + "Collection Field": "", "Collections": "", "Color": "Колір", "ComfyUI": "ComfyUI", @@ -411,12 +456,14 @@ "ComfyUI Workflow": "ComfyUI Workflow", "ComfyUI Workflow Nodes": "Вузли Workflow в ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Команда", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Завершення", "Compress Images in Channels": "", @@ -440,6 +487,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Підключіться до своїх власних API-ендпоінтів, сумісних з OpenAI.", "Connect to your own OpenAPI compatible external tool servers.": "Підключіться до своїх власних зовнішніх серверів інструментів, сумісних з OpenAPI.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -452,8 +500,16 @@ "Contact Admin for WebUI Access": "Зверніться до адміна для отримання доступу до WebUI", "Content": "Зміст", "Content Extraction Engine": "Рушій вилучення контенту", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Продовжити відповідь", "Continue with {{provider}}": "Продовжити з {{provider}}", "Continue with Email": "Продовжити з електронною поштою", @@ -501,6 +557,7 @@ "Create new secret key": "Створити новий секретний ключ", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Створено у", @@ -518,6 +575,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Зона небезпеки", @@ -540,7 +598,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Режим за замовчуванням працює з ширшим діапазоном моделей, викликаючи інструменти один раз перед виконанням. Рідний режим використовує вбудовані можливості виклику інструментів моделі, але вимагає, щоб модель спочатку підтримувала цю функцію.", "Default Model": "Модель за замовчуванням", "Default model updated": "Модель за замовчуванням оновлено", "Default permissions": "Дозволи за замовчуванням", @@ -550,6 +607,7 @@ "Default to ALL": "За замовчуванням — УСІ.", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "За замовчуванням використовувати сегментований пошук для зосередженого та релевантного вилучення контенту, це рекомендується у більшості випадків.", "Default User Role": "Роль користувача за замовчуванням", + "Default webhook": "", "Defaults": "", "Delete": "Видалити", "Delete {{name}}": "", @@ -610,6 +668,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Вимкнено", "Disconnect OAuth": "", "Discover a function": "Знайдіть функцію", @@ -624,10 +684,10 @@ "Discover, download, and explore model presets": "Знайдіть, завантажте та досліджуйте налаштування моделей", "Discussion channel where access is based on groups and permissions": "", "Display": "Відображення", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Відображати емодзі у викликах", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Показувати ім'я користувача замість 'Ви' в чаті", + "Display the Username Instead of You in the Chat": "Показувати ім'я користувача замість 'Ви' в чаті", "Displays citations in the response": "Показує посилання у відповіді", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Зануртесь у знання", @@ -638,6 +698,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Потрібна URL-адреса сервера Docling.", "Document": "Документ", + "Document ID Field": "", "Document Intelligence": "Інтелект документа", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -693,12 +754,14 @@ "Edit Default Permissions": "Редагувати дозволи за замовчуванням", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Редагувати пам'ять", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Редагувати користувача", "Edit User Group": "Редагувати групу користувачів", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -707,6 +770,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Ел. пошта", + "Email Claim": "", "Embark on adventures": "Вирушайте в пригоди", "Embedding": "Вбудовування", "Embedding Batch Size": "Розмір пакету під час вбудовування", @@ -715,6 +779,7 @@ "Embedding Model Engine": "Рушій моделі вбудовування ", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -722,22 +787,27 @@ "Enable Code Execution": "Увімкнути виконання коду", "Enable Code Interpreter": "Увімкнути інтерпретатор коду", "Enable Community Sharing": "Увімкнути спільний доступ", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Увімкнути блокування пам'яті (mlock), щоб запобігти виведенню даних моделі з оперативної пам'яті. Цей параметр блокує робочий набір сторінок моделі в оперативній пам'яті, гарантуючи, що вони не будуть виведені на диск. Це може допомогти підтримувати продуктивність, уникати помилок сторінок та забезпечувати швидкий доступ до даних.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Увімкнути відображення пам'яті (mmap) для завантаження даних моделі. Цей параметр дозволяє системі використовувати дискове сховище як розширення оперативної пам'яті, трактуючи файли на диску, як ніби вони знаходяться в RAM. Це може покращити продуктивність моделі, дозволяючи швидший доступ до даних. Однак, він може не працювати коректно на всіх системах і може споживати значну кількість дискового простору.", "Enable Message Queue": "", "Enable Message Rating": "Увімкнути оцінку повідомлень", "Enable Mirostat sampling for controlling perplexity.": "Увімкнути вибірку Mirostat для контролю перплексії.", "Enable New Sign Ups": "Дозволити нові реєстрації", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Увімкнено", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "Застосувати тимчасовий чат", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Переконайтеся, що ваш CSV-файл містить 4 колонки в такому порядку: Ім'я, Email, Пароль, Роль.", "Enter {{role}} message here": "Введіть повідомлення {{role}} тут", - "Enter a detail about yourself for your LLMs to recall": "Введіть відомості про себе для запам'ятовування вашими LLM.", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -754,6 +824,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Введіть перекриття фрагменту", "Enter Chunk Size": "Введіть розмір фрагменту", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Введіть пари \"токен:значення_зміщення\", розділені комами (напр.: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -791,8 +863,11 @@ "Enter Jupyter URL": "Введіть URL Jupyter", "Enter Kagi Search API Key": "Введіть ключ API Kagi Search", "Enter Key Behavior": "Введіть поведінку клавіші", + "Enter language": "", "Enter language codes": "Введіть мовні коди", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -812,6 +887,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Введіть URL проксі (напр., https://user:password@host:port)", "Enter reasoning effort": "Введіть зусилля на міркування", + "Enter Redirect URI": "", "Enter Score": "Введіть бал", "Enter SearchApi API Key": "Введіть ключ API для SearchApi", "Enter SearchApi Engine": "Введіть SearchApi рушія", @@ -821,6 +897,7 @@ "Enter SerpApi API Key": "Введіть ключ API для SerpApi", "Enter SerpApi Engine": "Введіть рушій SerpApi", "Enter Serper API Key": "Введіть ключ API Serper", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Введіть ключ API Serply", "Enter Serpstack API Key": "Введіть ключ API Serpstack", "Enter server host": "Введіть хост сервера", @@ -841,6 +918,8 @@ "Enter Tika Server URL": "Введіть URL-адресу сервера Tika", "Enter timeout in seconds": "Введіть тайм-аут у секундах", "Enter to Send": "Введіть для відправки", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Введіть Top K", "Enter Top K Reranker": "Введіть Top K Реранкер", "Enter URL (e.g. http://127.0.0.1:7860/)": "Введіть URL-адресу (напр., http://127.0.0.1:7860/)", @@ -881,11 +960,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Оцінювання", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API ключ", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Приклад: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Приклад: УСІ", "Example: mail": "Приклад: пошта", @@ -913,12 +996,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Експорт в CSV", "Export Tools": "", "Export Users": "", "External": "Зовнішній", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -936,6 +1025,7 @@ "Failed to create API Key.": "Не вдалося створити API ключ.", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -943,6 +1033,7 @@ "Failed to fetch models": "Не вдалося отримати моделі", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -952,6 +1043,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Не вдалося прочитати вміст буфера обміну", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -960,9 +1052,11 @@ "Failed to save models configuration": "Не вдалося зберегти конфігурацію моделей", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Не вдалося оновити налаштування", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Не вдалося завантажити файл.", "Features": "Особливості", "Features Permissions": "Дозволи функцій", @@ -995,6 +1089,8 @@ "File uploaded successfully": "Файл успішно завантажено", "Filename": "", "Files": "Файли", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Фільтр глобально вимкнено", "Filter is now globally enabled": "Фільтр увімкнено глобально", @@ -1017,6 +1113,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1047,6 +1144,7 @@ "Function is now globally enabled": "Функція зараз глобально увімкнена ", "Function Name": "Назва функції", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Функцію успішно оновлено", "Functions": "Функції", "Functions allow arbitrary code execution.": "Функції дозволяють виконання довільного коду.", @@ -1079,7 +1177,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Групу успішно створено", "Group deleted successfully": "Групу успішно видалено", "Group Description": "Опис групи", @@ -1091,6 +1192,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Тактильний зворотній зв'язок", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1121,6 +1223,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1146,6 +1250,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Важливе оновлення", @@ -1203,7 +1308,6 @@ "Keep in Sidebar": "", "Key": "Ключ", "Key is required": "", - "Keyboard shortcuts": "Клавіатурні скорочення", "Keyboard Shortcuts": "", "Knowledge": "Знання", "Knowledge Access": "Доступ до знань", @@ -1216,6 +1320,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Публічний обмін знаннями", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Знання успішно оновлено", "Kokoro.js (Browser)": "Kokoro.js (Браузер)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1232,7 +1338,6 @@ "Last ran": "", "Last reply": "Остання відповідь", "LDAP": "LDAP", - "LDAP server updated": "Сервер LDAP оновлено", "Leaderboard": "Таблиця лідерів", "Learn more": "", "Learn More": "", @@ -1254,6 +1359,7 @@ "Legacy": "", "lexical": "", "License": "Ліцензія", + "Lifecycle JSON": "", "Lift List": "", "Light": "Світла", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1277,6 +1383,7 @@ "Location access not allowed": "Доступ до місцезнаходження не дозволено", "Lost": "Втрачене", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Зроблено спільнотою OpenWebUI", "Make password visible in the user interface": "", @@ -1293,6 +1400,7 @@ "Manage Pipelines": "Керування конвеєрами", "Manage Tool Servers": "Керувати серверами інструментів", "Manage your account information.": "", + "Mapped Source": "", "March": "Березень", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1320,6 +1428,7 @@ "Memory cleared successfully": "Пам'ять успішно очищено", "Memory deleted successfully": "Пам'ять успішно видалено", "Memory updated successfully": "Пам'ять успішно оновлено", + "Merge Accounts by Email": "", "Merge Responses": "Об'єднати відповіді", "Merged Response": "Об'єднана відповідь", "Message": "", @@ -1330,9 +1439,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Повідомлення, які ви надішлете після створення посилання, не будуть доступні для інших. Користувачі, які мають URL, зможуть переглядати спільний чат.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1385,6 +1497,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "API ключ для пошуку Mojeek", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Більше", @@ -1402,6 +1515,7 @@ "Name your knowledge base": "Назвіть вашу базу знань", "Name, prompt, and model are required": "", "Native": "Рідний", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1431,6 +1545,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1443,8 +1558,10 @@ "No data": "", "No data found": "", "No distance available": "Відстань недоступна", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Файл не обрано", "No files found": "", @@ -1472,6 +1589,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Не знайдено жодного результату", "No results found": "Не знайдено жодного результату", "No search query generated": "Пошуковий запит не сформовано", @@ -1491,6 +1609,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Нема", + "Not configured": "", "Not factually correct": "Не відповідає дійсності", "Not helpful": "Не корисно", "Not Registered": "", @@ -1506,20 +1625,25 @@ "Notifications": "Сповіщення", "November": "Листопад", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Жовтень", "Off": "Вимк", "Okay, Let's Go!": "Гаразд, давайте почнемо!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "Темний OLED", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Налаштування Ollama API оновлено", "Ollama Cloud API Key": "", "Ollama Version": "Версія Ollama", + "Omit": "", "On": "Увімк", "Once": "", "OneDrive": "OneDrive", @@ -1590,6 +1714,7 @@ "Password": "Пароль", "Passwords do not match.": "", "Paste Large Text as File": "Вставити великий текст як файл", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF документ (.pdf)", @@ -1598,18 +1723,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "на розгляді", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Відмовлено в доступі до медіапристроїв", "Permission denied when accessing microphone": "Відмовлено у доступі до мікрофона", "Permission denied when accessing microphone: {{error}}": "Доступ до мікрофона заборонено: {{error}}", "Permissions": "Дозволи", + "Permissions reset to defaults": "", "Perplexity API Key": "Ключ API для Perplexity", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Персоналізація", + "Picture Claim": "", "Pin": "Зачепити", "Pin to Sidebar": "", "Pinned": "Зачеплено", @@ -1642,13 +1770,13 @@ "Please fill in all fields.": "Будь ласка, заповніть усі поля.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Будь ласка, спочатку виберіть модель.", "Please select a model.": "Будь ласка, виберіть модель.", "Please select a reason": "Будь ласка, виберіть причину", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Порт", "Ports": "", "Positive attitude": "Позитивне ставлення", @@ -1678,6 +1806,8 @@ "Prompts Public Sharing": "Публічний обмін промтами", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Публічний", "Pull \"{{searchValue}}\" from Ollama.com": "Завантажити \"{{searchValue}}\" з Ollama.com", "Pull a model from Ollama.com": "Завантажити модель з Ollama.com", @@ -1695,21 +1825,31 @@ "Read": "Читати", "Read Aloud": "Читати вголос", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Зусилля на міркування", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Записати голос", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Перенаправляємо вас до спільноти OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Зменшує ймовірність генерування нісенітниць. Вищий показник (напр., 100) забезпечить більше різноманітних відповідей, тоді як нижчий показник (напр., 10) буде більш обережним.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Називайте себе \"Користувач\" (напр., \"Користувач вивчає іспанську мову\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_few": "", + "Refresh requested: {{count}} terminal(s)_many": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Відмовив, коли не мав би", "Regenerate": "Регенерувати", "Regenerate Menu": "", @@ -1745,19 +1885,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Переставити моделі", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Відповісти в потоці", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Модель переранжування", + "Research Knowledge": "", "Reset": "Скидання", "Reset All Models": "Скинути усі моделі", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Скинути зображення", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Скинути каталог завантажень", "Reset Vector Storage/Knowledge": "Скинути векторне сховище/Знання", "Reset view": "Скинути вигляд", @@ -1779,6 +1926,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Ввід тексту з форматуванням для чату", "Role": "Роль", + "Roles Claim": "", "RTL": "RTL", "Run": "Запустити", "Run All": "", @@ -1797,10 +1945,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Збереження журналів чату безпосередньо в сховище вашого браузера більше не підтримується. Будь ласка, завантажте та видаліть журнали чату, натиснувши кнопку нижче. Не хвилюйтеся, ви можете легко повторно імпортувати журнали чату до бекенду через", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Пошук", "Search a model": "Шукати модель", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1810,6 +1960,7 @@ "Search Chats": "Пошук в чатах", "Search Collection": "Шукати колекцію", "Search Files": "", + "Search filters": "", "Search Filters": "Фільтри пошуку", "search for archived chats": "", "search for folders": "", @@ -1824,13 +1975,16 @@ "Search Models": "Пошук моделей", "Search Notes": "", "Search options": "Опції пошуку", + "Search or add pattern": "", "Search Prompts": "Пошук промтів", "Search Result Count": "Кількість результатів пошуку", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Шукати в інтернеті", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Пошуку інструментів", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Ключ API для SearchApi", "SearchApi Engine": "Рушій SearchApi", @@ -1846,7 +2000,6 @@ "Seed": "Сід", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Обрати базову модель", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Оберіть рушій", @@ -1884,18 +2037,25 @@ "semantic": "", "Send": "Надіслати", "Send a Message": "Надіслати повідомлення", + "Send events for": "", "Send message": "Надіслати повідомлення", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Відправляє `stream_options: { include_usage: true }` у запиті.\nПідтримувані постачальники повернуть інформацію про використання токену у відповіді, якщо вона встановлена.", "September": "Вересень", "SerpApi API Key": "Ключ API SerpApi", "SerpApi Engine": "Рушій SerpApi", "Serper API Key": "Ключ API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Ключ API Serply", "Serpstack API Key": "Ключ API Serpstack", "Server connection failed": "", "Server connection verified": "З'єднання з сервером підтверджено", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Встановити за замовчуванням", "Set as Production": "", "Set embedding model": "Встановити модель вбудовування", @@ -1923,15 +2083,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Поділитися зі спільнотою OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Дозволи на обмін", "Show": "Показати", - "Show \"What's New\" modal on login": "Показати модальне вікно \"Що нового\" під час входу", + "Show \"What's New\" Modal on Login": "Показати модальне вікно \"Що нового\" під час входу", "Show Admin Details in Account Pending Overlay": "Відобразити дані адміна у вікні очікування облікового запису", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Показати модель", @@ -1975,6 +2137,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Джерело", + "Specific users or groups": "", "Speech Playback Speed": "Швидкість відтворення мовлення", "Speech recognition error: {{error}}": "Помилка розпізнавання мови: {{error}}", "Speech-to-Text": "", @@ -2013,6 +2176,7 @@ "STT Settings": "Налаштування STT", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2037,8 +2201,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Система", + "System events only": "", "System Instructions": "Системні інструкції", "System Prompt": "Системний промт", + "Table": "", "Tag": "", "Tags": "Теги", "Tags Generation": "Генерація тегів", @@ -2059,6 +2225,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Роздільник тексту", "Text-to-Speech": "", "Text-to-Speech Engine": "Система синтезу мови", @@ -2074,7 +2246,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP-атрибут, який відповідає за пошту, яку користувачі використовують для входу.", "The LDAP attribute that maps to the username that users use to sign in.": "LDAP-атрибут, який відповідає за ім'я користувача, яке використовують користувачі для входу.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Таблиця лідерів наразі в бета-версії, і ми можемо коригувати розрахунки рейтингів у міру вдосконалення алгоритму.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Максимальний розмір файлу в МБ. Якщо розмір файлу перевищує цей ліміт, файл не буде завантажено.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Максимальна кількість файлів, які можна використати одночасно в чаті. Якщо кількість файлів перевищує цей ліміт, файли не будуть завантажені.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2096,6 +2267,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Це експериментальна функція, вона може працювати не так, як очікувалося, і може бути змінена в будь-який час.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Ця опція контролює, скільки токенів зберігається при оновленні контексту. Наприклад, якщо встановити значення 2, останні 2 токени контексту розмови будуть збережені. Збереження контексту допомагає підтримувати послідовність розмови, але може зменшити здатність реагувати на нові теми.", @@ -2136,7 +2308,7 @@ "To learn more about available endpoints, visit our documentation.": "Щоб дізнатися більше про доступні кінцеві точки, відвідайте нашу документацію.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Щоб обрати тут набори інструментів, спочатку додайте їх до робочої області \"Інструменти\".", - "Toast notifications for new updates": "Сповіщення Toast про нові оновлення", + "Toast Notifications for New Updates": "Сповіщення Toast про нові оновлення", "Today": "Сьогодні", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2150,6 +2322,8 @@ "Toggle whether current connection is active.": "", "Token": "Токен", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Занадто докладно", @@ -2198,14 +2372,19 @@ "Unpin": "Відчепити", "Unpin from Sidebar": "", "Unravel secrets": "Розплутуйте секрети", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Без тегів", "Untitled": "", "Update": "Оновлення", "Update and Copy Link": "Оновлення та копіювання посилання", + "Update Email": "", "Update for the latest features and improvements.": "Оновіть програми для нових функцій та покращень.", + "Update Name": "", "Update password": "Оновити пароль", + "Update Picture": "", "Update your status": "", "Updated": "Оновлено", "Updated at": "Оновлено на", @@ -2232,13 +2411,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Використовуйте '#' у полі введення підказки, щоб завантажити та включити свої знання.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "користувач", "User": "Користувач", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Місцезнаходження користувача успішно знайдено.", @@ -2248,6 +2432,7 @@ "User Status": "", "User Webhooks": "Вебхуки користувача", "Username": "Ім'я користувача", + "Username Claim": "", "users": "", "Users": "Користувачі", "Uses DefaultAzureCredential to authenticate": "", @@ -2261,6 +2446,7 @@ "Valves updated": "Клапани оновлено", "Valves updated successfully": "Клапани успішно оновлено", "variable": "змінна", + "Vector Field": "", "Verify Connection": "Перевірити з'єднання", "Verify SSL Certificate": "", "Version": "Версія", @@ -2290,11 +2476,14 @@ "Web API": "Веб-API", "Web Loader Engine": "", "Web Search": "Веб-Пошук", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Веб-пошукова система", "Web Search in Chat": "Пошук в інтернеті в чаті", "Web Search Query Generation": "Генерація запиту для пошуку в мережі", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Налаштування WebUI", @@ -2337,6 +2526,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Вчора", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Ви", @@ -2366,6 +2556,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Весь ваш внесок піде безпосередньо розробнику плагіна; Open WebUI не бере жодних відсотків. Однак, обрана платформа фінансування може мати свої власні збори.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Мова YouTube", diff --git a/src/lib/i18n/locales/ur-PK/translation.json b/src/lib/i18n/locales/ur-PK/translation.json index 2172954db3..5c826f7dbe 100644 --- a/src/lib/i18n/locales/ur-PK/translation.json +++ b/src/lib/i18n/locales/ur-PK/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{ صارف }} کی بات چیت", "{{webUIName}} Backend Required": "{{webUIName}} بیک اینڈ درکار ہے", "*Prompt node ID(s) are required for image generation": "تصویر کی تخلیق کے لیے *پرومپٹ نوڈ آئی ڈی(ز) کی ضرورت ہے", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "", "Account": "اکاؤنٹ", @@ -72,6 +83,7 @@ "Activity": "", "Add": "شامل", "Add a model ID": "", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "اس ماڈل کے کام کے بارے میں ایک مختصر وضاحت شامل کریں", "Add a tag": "ٹیگ شامل کریں", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "فائلیں شامل کریں", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "صارف شامل کریں", "Add User Group": "", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "ایڈمن", "Admin Contact Email": "", "Admin Panel": "ایڈمن پینل", + "Admin Roles": "", "Admin Settings": "ایڈمن ترتیبات", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "ایڈمنز کو ہر وقت تمام ٹولز تک رسائی حاصل ہوتی ہے؛ صارفین کو ورک سپیس میں ماڈل کے حساب سے ٹولز تفویض کرنے کی ضرورت ہوتی ہے", "Advanced": "", "Advanced Parameters": "پیشرفتہ پیرا میٹرز", @@ -123,16 +140,21 @@ "All": "", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "", "Allow Chat Delete": "", "Allow Chat Edit": "", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "صارف کی مقام کی اجازت دیں", "Allow Voice Interruption in Call": "کال میں آواز کی مداخلت کی اجازت دیں", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "کیا پہلے سے اکاؤنٹ موجود ہے؟", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "", @@ -173,6 +197,7 @@ "API Base URL": "API بنیادی URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "اے پی آئی کلید", + "API Key / Token": "", "API Key created.": "اے پی آئی کلید بنائی گئی", "API Key Endpoint Restrictions": "", "API keys": "API کیز", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "ارینا ماڈلز", "Artifacts": "نوادرات", "Asc": "", "Ask": "", "Ask a question": "سوال پوچھیں", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "اسسٹنٹ", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "آڈیو", "August": "اگست", "Auth": "", + "Auth Mode": "", + "Auth required": "", "Authenticate": "", "Authentication": "", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "جواب خودکار طور پر کلپ بورڈ پر کاپی ہو گیا", - "Auto-playback response": "آٹو پلے بیک جواب", + "Auto-Create Groups": "", + "Auto-Playback Response": "آٹو پلے بیک جواب", "Autocomplete Generation": "", "Autocomplete Generation Input Max Length": "", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "آٹو میٹک1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 ایپلی کیشن کا تصدیقی سلسلہ", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 بنیادی URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "", "available users": "دستیاب صارفین", + "Available variables": "", "available!": "دستیاب!", "Away": "غیر حاضر", "Awful": "", @@ -258,16 +295,17 @@ "Bad Response": "غلط جواب", "Banners": "بینرز", "Base Model (From)": "بیس ماڈل (سے)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "پہلے", "Being lazy": "سستی کر رہا ہے", - "Beta": "", "Bing": "", "Bing Search V7 Endpoint": "", "Bing Search V7 Subscription Key": "", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "چیٹ کی سمت", + "Chat Direction": "چیٹ کی سمت", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "", "Collection": "کلیکشن", + "Collection Field": "", "Collections": "", "Color": "", "ComfyUI": "کومفی یو آئی", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "کومفی یو آئی ورک فلو", "ComfyUI Workflow Nodes": "کومفی یو آئی ورک فلو نوڈز", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "کمانڈ", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "تکمیل", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "ویب یو آئی رسائی کے لیے ایڈمن سے رابطہ کریں", "Content": "مواد", "Content Extraction Engine": "", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "ردعمل جاری رکھیں", "Continue with {{provider}}": "{{provider}} کے ساتھ جاری رکھیں", "Continue with Email": "", @@ -493,6 +543,7 @@ "Create new secret key": "نیا خفیہ کلید بنائیں", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "پر بنایا گیا", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "ڈیفالٹ ماڈل", "Default model updated": "ڈیفالٹ ماڈل اپ ڈیٹ ہو گیا", "Default permissions": "", @@ -542,6 +593,7 @@ "Default to ALL": "", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "ڈیفالٹ صارف کا کردار", + "Default webhook": "", "Defaults": "", "Delete": "حذف کریں", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "غیر فعال", "Disconnect OAuth": "", "Discover a function": "ایک فنکشن دریافت کریں", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "دریافت کریں، ڈاؤن لوڈ کریں، اور ماڈل پریسیٹس کو دریافت کریں", "Discussion channel where access is based on groups and permissions": "", "Display": "", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "کال میں ایموجی دکھائیں", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "چیٹ میں \"آپ\" کے بجائے صارف نام دکھائیں", + "Display the Username Instead of You in the Chat": "چیٹ میں \"آپ\" کے بجائے صارف نام دکھائیں", "Displays citations in the response": "", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "", "Document": "دستاویز", + "Document ID Field": "", "Document Intelligence": "", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "یادداشت میں ترمیم کریں", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "صارف میں ترمیم کریں", "Edit User Group": "", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "الیون لیبز", "Email": "ای میل", + "Email Claim": "", "Embark on adventures": "", "Embedding": "", "Embedding Batch Size": "بیچ سائز شامل کرنا", @@ -707,6 +765,7 @@ "Embedding Model Engine": "ایمبیڈنگ ماڈل انجن", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "", "Enable Code Interpreter": "", "Enable Community Sharing": "کمیونٹی شیئرنگ فعال کریں", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", "Enable Message Queue": "", "Enable Message Rating": "پیغام کی درجہ بندی فعال کریں", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "نئے سائن اپس کو فعال کریں", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "فعال کردیا گیا ہے", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "یقینی بنائیں کہ آپ کی CSV فائل میں 4 کالم اس ترتیب میں شامل ہوں: نام، ای میل، پاس ورڈ، کردار", "Enter {{role}} message here": "یہاں {{کردار}} پیغام درج کریں", - "Enter a detail about yourself for your LLMs to recall": "اپنی ذات کے بارے میں کوئی تفصیل درج کریں تاکہ آپ کے LLMs اسے یاد رکھ سکیں", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "چنک اوورلیپ درج کریں", "Enter Chunk Size": "چنک سائز درج کریں", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "", "Enter Kagi Search API Key": "", "Enter Key Behavior": "", + "Enter language": "", "Enter language codes": "زبان کے کوڈ درج کریں", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", + "Enter Redirect URI": "", "Enter Score": "درجہ درج کریں", "Enter SearchApi API Key": "تلاش API کلید داخل کریں", "Enter SearchApi Engine": "تلاش انجن درج کریں", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", "Enter Serper API Key": "سرپر API کلید داخل کریں", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "سیرپلی API کلید درج کریں", "Enter Serpstack API Key": "سرپ اسٹیک API کلید درج کریں", "Enter server host": "", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "ٹیکا سرور یو آر ایل درج کریں", "Enter timeout in seconds": "", "Enter to Send": "", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "اوپر کے K درج کریں", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "یو آر ایل درج کریں (جیسے کہ http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "تشخیصات", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "", "Example: ALL": "", "Example: mail": "", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "", "Export Tools": "", "Export Users": "", "External": "", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API کلید بنانے میں ناکام", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "کلپ بورڈ مواد کو پڑھنے میں ناکام", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "ترتیبات کی تازہ کاری ناکام رہی", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "فائل اپلوڈ کرنے میں ناکامی ہوئی", "Features": "", "Features Permissions": "", @@ -987,6 +1075,8 @@ "File uploaded successfully": "", "Filename": "", "Files": "فائلز", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "فلٹر اب عالمی طور پر غیر فعال ہے", "Filter is now globally enabled": "فلٹر اب عالمی طور پر فعال ہے", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "فنکشن اب عالمی طور پر فعال ہے", "Function Name": "", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "فنکشن کو کامیابی سے اپ ڈیٹ کر دیا گیا", "Functions": "افعال", "Functions allow arbitrary code execution.": "افعال صوابدیدی کوڈ کے اجرا کی اجازت دیتے ہیں", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "", "Group deleted successfully": "", "Group Description": "", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "ہاپٹک فیڈ بیک", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "شناخت", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1138,6 +1236,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "اہم اپ ڈیٹ", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "", "Key is required": "", - "Keyboard shortcuts": "کی بورڈ شارٹ کٹس", "Keyboard Shortcuts": "", "Knowledge": "علم", "Knowledge Access": "", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "علم کامیابی سے تازہ کر دیا گیا ہے", "Kokoro.js (Browser)": "", "Kokoro.js Dtype": "", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "", "LDAP": "", - "LDAP server updated": "", "Leaderboard": "لیڈر بورڈ", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "", + "Lifecycle JSON": "", "Lift List": "", "Light": "روشنی", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "", "Lost": "گم شدہ", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "بائیں سے دائیں", "Made by Open WebUI Community": "اوپن ویب یو آئی کمیونٹی کی جانب سے تیار کردہ", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "پائپ لائنز کا نظم کریں", "Manage Tool Servers": "", "Manage your account information.": "", + "Mapped Source": "", "March": "مارچ", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "یادداشت کامیابی سے صاف ہوگئی", "Memory deleted successfully": "میموری کامیابی سے حذف ہوگئی", "Memory updated successfully": "حافظہ کامیابی سے اپ ڈیٹ کر دیا گیا", + "Merge Accounts by Email": "", "Merge Responses": "جوابات کو یکجا کریں", "Merged Response": "مرکب جواب", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "آپ کے لنک بنانے کے بعد بھیجے گئے پیغامات شیئر نہیں کیے جائیں گے یو آر ایل والے صارفین شیئر کیا گیا چیٹ دیکھ سکیں گے", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "مزید", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "", "Name, prompt, and model are required": "", "Native": "", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "فاصلہ دستیاب نہیں ہے", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "کوئی فائل منتخب نہیں کی گئی", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "کوئی نتائج نہیں ملے", "No results found": "کوئی نتائج نہیں ملے", "No search query generated": "کوئی تلاش کی درخواست نہیں بنائی گئی", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "کوئی نہیں", + "Not configured": "", "Not factually correct": "حقیقت کے مطابق نہیں ہے", "Not helpful": "مددگار نہیں ہے", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "اطلاعات", "November": "نومبر", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth آئی ڈی", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "اکتوبر", "Off": "بند", "Okay, Let's Go!": "ٹھیک ہے، چلیں!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "او ایل ای ڈی ڈارک", "Ollama": "اولامہ", "Ollama API": "اولامہ API", "Ollama API settings updated": "", "Ollama Cloud API Key": "", "Ollama Version": "اولاما ورژن", + "Omit": "", "On": "چالو", "Once": "", "OneDrive": "", @@ -1582,6 +1700,7 @@ "Password": "پاس ورڈ", "Passwords do not match.": "", "Paste Large Text as File": "", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "پی ڈی ایف دستاویز (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "زیر التواء", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "میڈیا آلات تک رسائی کے وقت اجازت مسترد کر دی گئی", "Permission denied when accessing microphone": "مائیکروفون تک رسائی کی اجازت نہیں دی گئی", "Permission denied when accessing microphone: {{error}}": "مائیکروفون تک رسائی کے دوران اجازت مسترد: {{error}}", "Permissions": "", + "Permissions reset to defaults": "", "Perplexity API Key": "", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "شخصی ترتیبات", + "Picture Claim": "", "Pin": "پن", "Pin to Sidebar": "", "Pinned": "پن کیا گیا", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "براہ کرم تمام فیلڈز مکمل کریں", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "", "Please select a model.": "", "Please select a reason": "براہ کرم ایک وجہ منتخب کریں", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "", "Ports": "", "Positive attitude": "مثبت رویہ", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com سے \"{{searchValue}}\" کو کھینچیں", "Pull a model from Ollama.com": "Ollama.com سے ماڈل حاصل کریں", @@ -1687,21 +1811,29 @@ "Read": "", "Read Aloud": "بُلند آواز میں پڑھیں", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "صوت ریکارڈ کریں", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "آپ کو اوپن ویب یو آئی کمیونٹی کی طرف ری ڈائریکٹ کیا جا رہا ہے", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "خود کو \"صارف\" کے طور پر حوالہ دیں (جیسے، \"صارف ہسپانوی سیکھ رہا ہے\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "جب انکار نہیں ہونا چاہیے تھا، انکار کر دیا", "Regenerate": "دوبارہ تخلیق کریں", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "دوبارہ درجہ بندی کا ماڈل", + "Research Knowledge": "", "Reset": "ری سیٹ", "Reset All Models": "", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "تصویر ری سیٹ کریں", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "اپلوڈ ڈائریکٹری کو ری سیٹ کریں", "Reset Vector Storage/Knowledge": "ویكٹر اسٹوریج/علم کو ری سیٹ کریں", "Reset view": "", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "چیٹ کے لیے رچ ٹیکسٹ ان پٹ", "Role": "کردار", + "Roles Claim": "", "RTL": "آر ٹی ایل", "Run": "چلائیں", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "براہ کرم اپنے براؤزر کے اسٹوریج میں چیٹ لاگز کو محفوظ کرنا اب تعاون یافتہ نہیں ہے براہ کرم نیچے دیئے گئے بٹن پر کلک کرکے اپنے چیٹ لاگز کو ڈاؤن لوڈ اور حذف کریں فکر نہ کریں، آپ اپنے چیٹ لاگز کو بیک اینڈ میں دوبارہ آسانی سے درآمد کر سکتے ہیں", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "تلاش کریں", "Search a model": "ماڈل تلاش کریں", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "چیٹس تلاش کریں", "Search Collection": "مجموعہ تلاش کریں", "Search Files": "", + "Search filters": "", "Search Filters": "", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "ماڈلز تلاش کریں", "Search Notes": "", "Search options": "", + "Search or add pattern": "", "Search Prompts": "تلاش کے اشارے", "Search Result Count": "تلاش کا نتیجہ شمار ", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "تلاش کے اوزار", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "سرچ اے پی آئی کی API کلید", "SearchApi Engine": "تلاش انجن API", @@ -1834,7 +1980,6 @@ "Seed": "بیج", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "ایک بنیادی ماڈل منتخب کریں", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "ایک انجن منتخب کریں", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "بھیجیں", "Send a Message": "پیغام بھیجیں", + "Send events for": "", "Send message": "پیغام بھیجیں", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "درخواست میں `stream_options: { include_usage: true }` بھیجتا ہے\nمعاون فراہم کنندگان، جب سیٹ کیا جاتا ہے تو، جواب میں ٹوکن کے استعمال کی معلومات واپس کر دیں گے", "September": "ستمبر", "SerpApi API Key": "", "SerpApi Engine": "", "Serper API Key": "سرپر API کلید", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "سرپلی API کی کلید", "Serpstack API Key": "سرپ اسٹیک اے پی آئی کلید", "Server connection failed": "", "Server connection verified": "سرور کنکشن تصدیق شدہ ہے", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "بطور ڈیفالٹ سیٹ کریں", "Set as Production": "", "Set embedding model": "", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "اوپن ویب یوآئی کمیونٹی کے ساتھ شیئر کریں\n", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "", "Show": "دکھائیں", - "Show \"What's New\" modal on login": "", + "Show \"What's New\" Modal on Login": "", "Show Admin Details in Account Pending Overlay": "اکاؤنٹ پینڈنگ اوورلے میں ایڈمن کی تفصیلات دکھائیں", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "ماخذ", + "Specific users or groups": "", "Speech Playback Speed": "تقریر پلے بیک کی رفتار", "Speech recognition error: {{error}}": "تقریر کی پہچان کی خرابی: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "ایس ٹی ٹی ترتیبات", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "سسٹم", + "System events only": "", "System Instructions": "نظام کی ہدایات", "System Prompt": "سسٹم پرومپٹ", + "Table": "", "Tag": "", "Tags": "", "Tags Generation": "", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "متن تقسیم کنندہ", "Text-to-Speech": "", "Text-to-Speech Engine": "ٹیکسٹ ٹو اسپیچ انجن", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "", "The LDAP attribute that maps to the username that users use to sign in.": "", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "لیڈر بورڈ اس وقت بیٹا مرحلے میں ہے، اور جیسے جیسے ہم الگورتھم کو بہتر بنائیں گے ہم ریٹنگ کیلکولیشن کو ایڈجسٹ کرسکتے ہیں", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "زیادہ سے زیادہ فائل سائز ایم بی میں اگر فائل سائز اس حد سے تجاوز کر جاتا ہے، تو فائل اپ لوڈ نہیں ہوگی", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "چیٹ میں ایک وقت میں استعمال ہونے والی فائلوں کی زیادہ سے زیادہ تعداد اگر فائلوں کی تعداد اس حد سے تجاوز کر جائے تو فائلیں اپلوڈ نہیں کی جائیں گی", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "یہ ایک تجرباتی خصوصیت ہے، یہ متوقع طور پر کام نہ کر سکتی ہو اور کسی بھی وقت تبدیل کی جا سکتی ہے", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "یہاں ٹول کٹس منتخب کرنے کے لیے، پہلے انہیں \"ٹولز\" ورک اسپیس میں شامل کریں", - "Toast notifications for new updates": "نئے اپڈیٹس کے لئے ٹوسٹ نوٹیفیکیشنز", + "Toast Notifications for New Updates": "نئے اپڈیٹس کے لئے ٹوسٹ نوٹیفیکیشنز", "Today": "آج", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "ٹوکَن", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "بہت زیادہ طویل", @@ -2184,14 +2350,19 @@ "Unpin": "ان پن کریں", "Unpin from Sidebar": "", "Unravel secrets": "", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "غیر مہر شدہ", "Untitled": "", "Update": "اپ ڈیٹ کریں", "Update and Copy Link": "اپڈیٹ اور لنک کاپی کریں", + "Update Email": "", "Update for the latest features and improvements.": "تازہ ترین خصوصیات اور بہتریوں کے لیے اپ ڈیٹ کریں", + "Update Name": "", "Update password": "پاس ورڈ اپ ڈیٹ کریں", + "Update Picture": "", "Update your status": "", "Updated": "اپ ڈیٹ کیا گیا", "Updated at": "پر تازہ کاری کی گئی ", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "پرامپٹ ان پٹ میں '#' استعمال کریں تاکہ اپنی معلومات کو لوڈ اور شامل کریں", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "صارف", "User": "صارف", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "صارف کا مقام کامیابی سے حاصل کیا گیا", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "", "Username": "", + "Username Claim": "", "users": "", "Users": "صارفین", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "والوز کو اپ ڈیٹ کر دیا گیا", "Valves updated successfully": "والو کامیابی کے ساتھ اپ ڈیٹ ہو گئے", "variable": "متغیر", + "Vector Field": "", "Verify Connection": "", "Verify SSL Certificate": "", "Version": "ورژن", @@ -2276,11 +2454,14 @@ "Web API": "ویب اے پی آئی", "Web Loader Engine": "", "Web Search": "ویب تلاش کریں", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "ویب تلاش انجن", "Web Search in Chat": "", "Web Search Query Generation": "", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "ویب ہُک یو آر ایل", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "ویب UI ترتیبات", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "کل", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "آپ", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "آپ کی پوری شراکت براہ راست پلگ ان ڈیولپر کو جائے گی؛ اوپن ویب یو آئی کوئی فیصد نہیں لیتی تاہم، منتخب کردہ فنڈنگ پلیٹ فارم کی اپنی فیس ہو سکتی ہیں", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "یوٹیوب", "Youtube Language": "", diff --git a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json index b2a1b172d6..8c1dbca8b6 100644 --- a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json +++ b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} та яширин чизиқ", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} нинг чатлари", "{{webUIName}} Backend Required": "{{webUIName}} Баcкенд талаб қилинади", "*Prompt node ID(s) are required for image generation": "*Расм яратиш учун тезкор тугун идентификаторлари талаб қилинади", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Кириш назорати", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Барча фойдаланувчилар учун очиқ", "Account": "Ҳисоб", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Қўшиш", "Add a model ID": "Модел идентификаторини қўшинг", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Ушбу модел нима қилиши ҳақида қисқача тавсиф қўшинг", "Add a tag": "Тег қўшинг", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Файлларни қўшиш", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Фойдаланувчи қўшиш", "Add User Group": "Фойдаланувчилар гуруҳини қўшиш", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Админ", "Admin Contact Email": "", "Admin Panel": "Администратор панели", + "Admin Roles": "", "Admin Settings": "Администратор созламалари", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Администраторлар ҳар доим барча воситалардан фойдаланишлари мумкин; фойдаланувчиларга иш жойида ҳар бир модел учун тайинланган воситалар керак бўлади.", "Advanced": "", "Advanced Parameters": "Кенгайтирилган параметрлар", @@ -123,16 +140,21 @@ "All": "Ҳаммаси", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Барча моделлар муваффақиятли ўчирилди", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Қўнғироққа рухсат бериш", "Allow Chat Controls": "Чат бошқарувига рухсат беринг", "Allow Chat Delete": "Чатни ўчиришга рухсат беринг", "Allow Chat Edit": "Чатни таҳрирлашга рухсат беринг", "Allow Chat Export": "Чат экспортига рухсат беринг", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "Чат алмашишга рухсат беринг", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Фойдаланувчи жойлашувига рухсат бериш", "Allow Voice Interruption in Call": "Қўнғироқда овозли узилишга рухсат беринг", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Рухсат этилган охирги нуқталар", "Allowed File Extensions": "Рухсат этилган файл кенгайтмалари", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Юклаш учун рухсат берилган файл кенгайтмалари. Бир нечта кенгайтмаларни вергул билан ажратинг. Барча файл турлари учун бўш қолдиринг.", + "Allowed Roles": "", "Already have an account?": "Ҳисобингиз борми?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Топ_п га муқобил ва сифат ва хилма-хиллик мувозанатини таъминлашга қаратилган. п параметри токеннинг кўриб чиқилишининг минимал эҳтимолини ифодалайди, бу токеннинг эҳтимолий эҳтимолига нисбатан. Мисол учун, п=0,05 ва энг эҳтимолли токен 0,9 эҳтимолга эга бўлса, қиймати 0,045 дан кам бўлган логитлар филтрланади.", "Always": "Ҳар доим", @@ -173,6 +197,7 @@ "API Base URL": "Дастурий Илова Интерфейси(API) bazaviy URL manzili", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "Дастурий Илова Интерфейси(API) калити", + "API Key / Token": "", "API Key created.": "Дастурий Илова Интерфейси(API) калити яратилди.", "API Key Endpoint Restrictions": "Дастурий Илова Интерфейси(API) калитининг чекловлари", "API keys": "Дастурий Илова Интерфейси(API) калитлари", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Ҳақиқатан ҳам бу хабарни ўчириб ташламоқчимисиз?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Ҳақиқатан ҳам барча архивланган чатларни архивдан чиқармоқчимисиз?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Арена моделлари", "Artifacts": "Артефактлар", "Asc": "", "Ask": "Сўранг", "Ask a question": "Савол беринг", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Ёрдамчи", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Аудио", "August": "август", "Auth": "Автор", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Аутентификация қилиш", "Authentication": "Аутентификация", "Auto": "Автоматик", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Жавобни вақтинчалик хотирага автоматик нусхалаш", - "Auto-playback response": "Автоматик ижро жавоби", + "Auto-Create Groups": "", + "Auto-Playback Response": "Автоматик ижро жавоби", "Autocomplete Generation": "Автотўлдиришни яратиш", "Autocomplete Generation Input Max Length": "Автоматик тўлдириш ишлаб чиқариш киритиш максимал узунлиги", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Автоматик1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 базавий манзил", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Мавжуд асбоблар", "available users": "мавжуд фойдаланувчилар", + "Available variables": "", "available!": "мавжуд!", "Away": "Йўқ", "Awful": "Даҳшатли", @@ -258,16 +295,17 @@ "Bad Response": "Ёмон жавоб", "Banners": "Баннерлар", "Base Model (From)": "Асосий модел (дан бошлаб)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "олдин", "Being lazy": "Дангаса бўлиш", - "Beta": "Бета", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 Endpoint", "Bing Search V7 Subscription Key": "Bing Search V7 Subscription Key", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Bocha Search API Key", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Чат йўналиши", + "Chat Direction": "Чат йўналиши", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Йиқилиш", "Collection": "Тўплам", + "Collection Field": "", "Collections": "", "Color": "Ранг", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI иш жараёни", "ComfyUI Workflow Nodes": "ComfyUI иш оқими тугунлари", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Буйруқ", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Тугаллашлар", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Ўзингизнинг OpenAIга мос келадиган АПИ сўнгги нуқталарига уланинг.", "Connect to your own OpenAPI compatible external tool servers.": "Ўзингизнинг OpenAIга мос келадиган ташқи асбоблар серверларига уланинг.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Уланиш амалга ошмади", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUIга кириш учун администратор билан боғланинг", "Content": "Таркиб", "Content Extraction Engine": "Контентни ажратиб олиш механизми", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Жавоб беришни давом эттириш", "Continue with {{provider}}": "{{provider}} билан давом этинг", "Continue with Email": "Электрон почта орқали давом этинг", @@ -493,6 +543,7 @@ "Create new secret key": "Янги махфий калит яратинг", "Create note": "", "Create Note": "Эслатма яратиш", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Қуйидаги ортиқча тугмасини босиш орқали биринчи қайдингизни яратинг.", "Created at": "Яратилган", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "Махсус параметр номи", "Custom Parameter Value": "Махсус параметр қиймати", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Хавфли зона", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Стандарт модел", "Default model updated": "Стандарт модел янгиланди", "Default permissions": "Бирламчи рухсатлар", @@ -542,6 +593,7 @@ "Default to ALL": "Барчаси учун бирламчи", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Фокусланган ва тегишли контентни ажратиб олиш учун бирламчи сегментланган қидириш, бу кўп ҳолларда тавсия этилади.", "Default User Role": "Стандарт фойдаланувчи роли", + "Default webhook": "", "Defaults": "", "Delete": "Ўчириш", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "Расм чиқаришни ўчириб қўйинг", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDFдан тасвирни ажратиб олишни ўчириб қўйинг. Агар LLM дан фойдаланиш ёқилган бўлса, тасвирларга автоматик сарлавҳа қўйилади. Бирламчи параметрлар False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Ўчирилган", "Disconnect OAuth": "", "Discover a function": "Функцияни кашф қилиш", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Модел созламаларини кашф этинг, юклаб олинг ва ўрганинг", "Discussion channel where access is based on groups and permissions": "", "Display": "Дисплей", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Чақирувда кулгичларни кўрсатиш", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Чатда Сиз ўрнига фойдаланувчи номини кўрсатинг", + "Display the Username Instead of You in the Chat": "Чатда Сиз ўрнига фойдаланувчи номини кўрсатинг", "Displays citations in the response": "Жавобда иқтибосларни кўрсатади", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Билимга шўнғинг", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Доcлинг Сервер URL манзили талаб қилинади.", "Document": "Ҳужжат", + "Document ID Field": "", "Document Intelligence": "Ҳужжат разведкаси", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Стандарт рухсатларни таҳрирлаш", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Хотирани таҳрирлаш", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Фойдаланувчини таҳрирлаш", "Edit User Group": "Фойдаланувчилар гуруҳини таҳрирлаш", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ЭлевенЛабс", "Email": "Электрон почта", + "Email Claim": "", "Embark on adventures": "Саргузаштларга киришинг", "Embedding": "Ўрнатиш", "Embedding Batch Size": "Ўрнатиш тўплами ҳажми", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Двигател моделини ўрнатиш", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Код бажарилишини ёқинг", "Enable Code Interpreter": "Код таржимонини ёқинг", "Enable Community Sharing": "Ҳамжамият билан алмашишни ёқинг", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Модел маълумотларини РАМдан алмаштиришнинг олдини олиш учун Хотирани қулфлашни (mlock) ёқинг. Ушбу параметр моделнинг ишлайдиган саҳифалар тўпламини РАМга блоклайди ва улар дискка алмаштирилмаслигини таъминлайди. Бу саҳифа хатоларидан қочиш ва маълумотларга тезкор киришни таъминлаш орқали ишлашни сақлашга ёрдам беради.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Модел маълумотларини юклаш учун Хотира харитасини (mmap) ёқинг. Ушбу параметр тизимга диск файлларини оператив хотирада бўлганидек даволаш орқали РАМ кенгайтмаси сифатида диск хотирасидан фойдаланиш имконини беради. Бу маълумотларга тезроқ кириш имконини бериш орқали модел иш фаолиятини яхшилаши мумкин. Бироқ, у барча тизимлар билан тўғри ишламаслиги ва катта ҳажмдаги диск майдонини истеъмол қилиши мумкин.", "Enable Message Queue": "", "Enable Message Rating": "Хабар рейтингини ёқиш", "Enable Mirostat sampling for controlling perplexity.": "Ажабланишни назорат қилиш учун Миростат намунасини ёқинг.", "Enable New Sign Ups": "Янги рўйхатдан ўтишни ёқинг", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Ёқилган", "End Tag": "", + "Endpoint": "", "Endpoint URL": "Охирги нуқта URL", "Enforce Temporary Chat": "Вақтинчалик суҳбатни жорий қилиш", "Enhance": "Яхшилаш", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV файлингиз қуйидаги тартибда 4 та устундан иборатлигига ишонч ҳосил қилинг: Исм, Электрон почта, Парол, Рол.", "Enter {{role}} message here": "Бу ерга {{role}} хабарини киритинг", - "Enter a detail about yourself for your LLMs to recall": "ЛЛМлар эслаб қолишлари учун ўзингиз ҳақингизда маълумот киритинг", "Enter a title for the pending user info overlay. Leave empty for default.": "Кутилаётган фойдаланувчи маълумотлари учун сарлавҳа киритинг. Сукут бўйича бўш қолдиринг.", "Enter a watermark for the response. Leave empty for none.": "Жавоб учун мойбўёқли белгини киритинг. Ҳеч ким учун бўш қолдиринг.", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Chunk Overlap киритинг", "Enter Chunk Size": "Chunk ҳажмини киритинг", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Вергул билан ажратилган \"token:bias_value\" жуфтларини киритинг (мисол: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Кутилаётган фойдаланувчи маълумотлари қопламаси учун таркибни киритинг. Сукут бўйича бўш қолдиринг.", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupiter УРЛ манзилини киритинг", "Enter Kagi Search API Key": "Kagi Search АПИ калитини киритинг", "Enter Key Behavior": "Асосий хатти-ҳаракатни киритинг", + "Enter language": "", "Enter language codes": "Тил кодларини киритинг", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Mistral АПИ калитини киритинг", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Прокси-сервернинг УРЛ манзилини киритинг (масалан, ҳттпс://усер:пассwорд@ҳост:порт)", "Enter reasoning effort": "Фикрлаш ҳаракатини киритинг", + "Enter Redirect URI": "", "Enter Score": "Бални киритинг", "Enter SearchApi API Key": "SearchApi АПИ калитини киритинг", "Enter SearchApi Engine": "SearchApi тизимига киринг", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi АПИ калитини киритинг", "Enter SerpApi Engine": "SerpApi двигателига киринг", "Enter Serper API Key": "Serper АПИ калитини киритинг", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply АПИ калитини киритинг", "Enter Serpstack API Key": "Serpstack АПИ калитини киритинг", "Enter server host": "Сервер хостига киринг", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Тика Сервер УРЛ манзилини киритинг", "Enter timeout in seconds": "Вақт тугашини сонияларда киритинг", "Enter to Send": "Юбориш учун киринг", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Топ К.га киринг", "Enter Top K Reranker": "Топ К Реранкер-га киринг", "Enter URL (e.g. http://127.0.0.1:7860/)": "УРЛ манзилини киритинг (масалан, ҳттп://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Баҳолар", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa АПИ калити", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Мисол: (&(обжеcтCласс=инетОргПерсон)(уид=%с))", "Example: ALL": "Мисол: АЛЛ", "Example: mail": "Мисол: почта", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CSV га экспорт қилиш", "Export Tools": "", "Export Users": "", "External": "Ташқи", + "External connection not found.": "", "External Document Loader URL required.": "Ташқи ҳужжат юкловчи УРЛ манзили талаб қилинади.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Ташқи вазифа модели", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Ташқи Wеб Лоадер АПИ калити", "External Web Loader URL": "Ташқи веб юкловчи УРЛ манзили", "External Web Search API Key": "Ташқи веб-қидирув АПИ калити", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "АПИ калитини яратиб бўлмади.", "Failed to delete calendar": "", "Failed to delete note": "Қайдни ўчириб бўлмади", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Моделларни олиб бўлмади", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Буфер таркибини ўқиб бўлмади", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Моделлар конфигурацияси сақланмади", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Созламаларни янгилаб бўлмади", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Файл юкланмади.", "Features": "Хусусиятлари", "Features Permissions": "Хусусиятлар Рухсатлар", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Файл муваффақиятли юкланди", "Filename": "", "Files": "Файллар", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Филтр энди бутун дунё бўйлаб ўчириб қўйилган", "Filter is now globally enabled": "Филтр энди глобал миқёсда ёқилган", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Функция энди глобал миқёсда ёқилган", "Function Name": "Функция номи", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Функция муваффақиятли янгиланди", "Functions": "Функсиялар", "Functions allow arbitrary code execution.": "Функциялар ўзбошимчалик билан кодни бажаришга имкон беради.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Гуруҳ муваффақиятли яратилди", "Group deleted successfully": "Гуруҳ муваффақиятли ўчирилди", "Group Description": "Гуруҳ тавсифи", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Ҳаптик фикр-мулоҳазалар", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ИД", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "ифраме Сандбох рухсат шакллари", "iframe Sandbox Allow Same Origin": "ифраме Сандбох бир хил келиб чиқишига рухсат беради", @@ -1138,6 +1236,7 @@ "Import From Link": "Ҳаволадан импорт қилиш", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Мухим янгиланиш", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Калит", "Key is required": "", - "Keyboard shortcuts": "Клавиатура ёрлиқлари", "Keyboard Shortcuts": "", "Knowledge": "Билим", "Knowledge Access": "Билимга кириш", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Билимларни оммавий алмашиш", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Билим муваффақиятли янгиланди", "Kokoro.js (Browser)": "Кокоро.жс (браузер)", "Kokoro.js Dtype": "Кокоро.жс Д тури", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Охирги жавоб", "LDAP": "LDAP", - "LDAP server updated": "LDAP сервери янгиланди", "Leaderboard": "Пешқадамлар жадвали", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Литсензия", + "Lifecycle JSON": "", "Lift List": "", "Light": "Нур", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Жойлашувга рухсат берилмаган", "Lost": "Йўқотилган", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "ЛТР", "Made by Open WebUI Community": "Опен WебУИ ҳамжамияти томонидан яратилган", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Қувурларни бошқариш", "Manage Tool Servers": "Асбоб серверларини бошқариш", "Manage your account information.": "", + "Mapped Source": "", "March": "Март", "Markdown": "Маркдоwн", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Хотира муваффақиятли тозаланди", "Memory deleted successfully": "Хотира муваффақиятли ўчирилди", "Memory updated successfully": "Хотира муваффақиятли янгиланди", + "Merge Accounts by Email": "", "Merge Responses": "Жавобларни бирлаштириш", "Merged Response": "Бирлаштирилган жавоб", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Ҳаволани яратганингиздан кейин юборган хабарларингиз улашилмайди. УРЛ манзили бўлган фойдаланувчилар умумий чатни кўришлари мумкин бўлади.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft ОнеДриве", "Microsoft OneDrive (personal)": "Microsoft ОнеДриве (шахсий)", "Microsoft OneDrive (work/school)": "Microsoft ОнеДриве (иш/мактаб)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Можеэк қидирув АПИ калити", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Кўпроқ", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Билимлар базасини номланг", "Name, prompt, and model are required": "", "Native": "Маҳаллий", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Масофа мавжуд эмас", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Ҳеч қандай файл танланмаган", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Ҳеч қандай натижа топилмади", "No results found": "Ҳеч қандай натижа топилмади", "No search query generated": "Ҳеч қандай қидирув сўрови яратилмади", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Йўқ", + "Not configured": "", "Not factually correct": "Аслида тўғри эмас", "Not helpful": "Фойдали эмас", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Билдиришномалар", "November": "ноябр", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ОАутҳ ИД", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "октябр", "Off": "Ўчирилган", "Okay, Let's Go!": "Майли, кетайлик!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "ОЛЕД қоронғи", "Ollama": "Ollama", "Ollama API": "Ollama АПИ", "Ollama API settings updated": "Ollama АПИ созламалари янгиланди", "Ollama Cloud API Key": "", "Ollama Version": "Ollama версияси", + "Omit": "", "On": "Ёниқ", "Once": "", "OneDrive": "ОнеДриве", @@ -1582,6 +1700,7 @@ "Password": "Парол", "Passwords do not match.": "", "Paste Large Text as File": "Катта матнни файл сифатида жойлаштиринг", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "ПДФ ҳужжат (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "кутилмоқда", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "Кутилаётган фойдаланувчи Оверлай контенти", "Pending User Overlay Title": "Кутилаётган фойдаланувчи сарлавҳаси", "Permission denied when accessing media devices": "Медиа қурилмаларга киришда рухсат рад этилди", "Permission denied when accessing microphone": "Микрофонга киришда рухсат берилмади", "Permission denied when accessing microphone: {{error}}": "Микрофонга киришда рухсат рад этилди: {{error}}", "Permissions": "Рухсатлар", + "Permissions reset to defaults": "", "Perplexity API Key": "Қийинчилик АПИ калити", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Шахсийлаштириш", + "Picture Claim": "", "Pin": "Пин", "Pin to Sidebar": "", "Pinned": "Қадалган", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Илтимос, барча майдонларни тўлдиринг.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Илтимос, аввал моделни танланг.", "Please select a model.": "Илтимос, моделни танланг.", "Please select a reason": "Сабабини танланг", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Порт", "Ports": "", "Positive attitude": "Ижобий муносабат", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Умумий алмашишни таклиф қилади", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Оммавий", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.cом сайтидан “{{сеарчВалуе}}”ни тортинг", "Pull a model from Ollama.com": "Ollama.cом дан моделни тортинг", @@ -1687,21 +1811,29 @@ "Read": "Ўқинг", "Read Aloud": "Овоз чиқариб ўқинг", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Мулоҳаза юритиш ҳаракатлари", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Ёзиб олиш", "Record voice": "Овозни ёзиб олинг", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Сизни Опен WебУИ ҳамжамиятига йўналтирмоқда", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Бемаъни нарсаларни яратиш эҳтимолини камайтиради. Юқори қиймат (масалан, 100) турли хил жавоблар беради, пастроқ қиймат (масалан, 10) эса консерватив бўлади.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Ўзингизни \"Фойдаланувчи\" деб кўрсатинг (масалан, \"Фойдаланувчи испан тилини ўрганмоқда\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Бўлмаслиги керак бўлганда рад этилди", "Regenerate": "Қайта тиклаш", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Моделларни қайта тартиблаш", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Мавзуда жавоб беринг", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Двигателни қайта тартиблаш", "Reranking Model": "Қайта тартиблаш модели", + "Research Knowledge": "", "Reset": "Қайта тиклаш", "Reset All Models": "Барча моделларни қайта ўрнатиш", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Расмни қайта тиклаш", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Юклаш каталогини тиклаш", "Reset Vector Storage/Knowledge": "Вектор хотираси/билимини қайта ўрнатиш", "Reset view": "Кўринишни тиклаш", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Чат учун бой матн киритиш", "Role": "Рол", + "Roles Claim": "", "RTL": "RTL", "Run": "Ишга тушириш", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Чат журналларини бевосита браузерингиз хотирасига сақлаш энди қўллаб-қувватланмайди. Қуйидаги тугмани босиш орқали суҳбат журналларингизни юклаб олинг ва ўчиринг. Хавотир олманг, сиз чат журналларини баcкенд орқали осонгина қайта импорт қилишингиз мумкин", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Филиални ўзгартириш бўйича айлантиринг", "Scroll to Top": "", "Search": "Қидирув", "Search a model": "Моделни қидиринг", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Чатларни қидириш", "Search Collection": "Тўпламни қидириш", "Search Files": "", + "Search filters": "", "Search Filters": "Қидирув филтрлари", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Моделларни қидириш", "Search Notes": "", "Search options": "Қидирув вариантлари", + "Search or add pattern": "", "Search Prompts": "Қидирув кўрсатмалари", "Search Result Count": "Қидирув натижалари сони", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Интернетда қидиринг", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Қидирув воситалари", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi АПИ калити", "SearchApi Engine": "SearchApi механизми", @@ -1834,7 +1980,6 @@ "Seed": "Дастлабки маълумот", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Асосий моделни танланг", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Двигателни танланг", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Юбориш", "Send a Message": "Хабар юбориш", + "Send events for": "", "Send message": "Хабар юбориш", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Сўровда ъстреам_оптионс: { инcлуде_усаге: труе }ъ юборади.\nҚўллаб-қувватланадиган провайдерлар ўрнатилганда жавобда токен фойдаланиш маълумотларини қайтаради.", "September": "сентябр", "SerpApi API Key": "SerpApi АПИ калити", "SerpApi Engine": "SerpApi двигатели", "Serper API Key": "Serper АПИ калити", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply АПИ калити", "Serpstack API Key": "Serpstack АПИ калити", "Server connection failed": "", "Server connection verified": "Сервер уланиши тасдиқланди", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Стандарт сифатида ўрнатинг", "Set as Production": "", "Set embedding model": "Ўрнатиш моделини ўрнатинг", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Опен WебУИ ҳамжамиятига улашинг", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Рухсатларни алмашиш", "Show": "Кўрсатиш", - "Show \"What's New\" modal on login": "Киришда \"Янги нарсалар\" модалини кўрсатинг", + "Show \"What's New\" Modal on Login": "Киришда \"Янги нарсалар\" модалини кўрсатинг", "Show Admin Details in Account Pending Overlay": "Ҳисоб кутилаётган қатламда администратор маълумотларини кўрсатиш", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Моделни кўрсатиш", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Сеарч АПИ сИД", "Sougou Search API SK": "Sougou Сеарч АПИ СК", "Source": "Манба", + "Specific users or groups": "", "Speech Playback Speed": "Нутқни ижро этиш тезлиги", "Speech recognition error: {{error}}": "Нутқни аниқлашда хатолик: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "СТТ созламалари", "Stylized PDF Export": "Услубий PDF экспорти", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Тизим", + "System events only": "", "System Instructions": "Тизим кўрсатмалари", "System Prompt": "Тизим сўрови", + "Table": "", "Tag": "", "Tags": "Теглар", "Tags Generation": "Теглар яратиш", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Матн ажратувчи", "Text-to-Speech": "", "Text-to-Speech Engine": "Матнни нутққа айлантириш механизми", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Кириш аудиосининг тили. Кириш тилини ISO-639-1 (масалан, en) форматида тақдим этиш аниқлик ва кечикишни яхшилайди. Тилни автоматик аниқлаш учун бўш қолдиринг.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP атрибути фойдаланувчиларнинг тизимга киришда фойдаланадиган почта манзилига мос келади.", "The LDAP attribute that maps to the username that users use to sign in.": "Фойдаланувчилар тизимга кириш учун фойдаланадиган фойдаланувчи номига мос келадиган LDAP атрибути.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Пешқадамлар жадвали ҳозирда бета-версияда ва биз алгоритмни такомиллаштириш жараёнида рейтинг ҳисоб-китобларини созлашимиз мумкин.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Файлнинг максимал ҳажми МБ. Агар файл ҳажми ушбу чегарадан ошса, файл юкланмайди.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Чатда бир вақтнинг ўзида ишлатилиши мумкин бўлган максимал файллар сони. Агар файллар сони ушбу чегарадан ошса, файллар юкланмайди.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Матн учун чиқиш формати. \"жсон\", \"маркдоwн\" ёки \"ҳтмл\" бўлиши мумкин. Бирламчи \"маркдоwн\" учун.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Бу экспериментал хусусият бўлиб, у кутилганидек ишламаслиги ва исталган вақтда ўзгариши мумкин.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Ушбу модел ҳамма учун очиқ эмас. Илтимос, бошқа моделни танланг.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Ушбу параметр контекстни янгилашда қанча токенлар сақланишини назорат қилади. Масалан, агар 2 га ўрнатилган бўлса, суҳбат контекстининг охирги 2 та белгиси сақланиб қолади. Контекстни сақлаш суҳбатнинг узлуксизлигини сақлашга ёрдам беради, лекин бу янги мавзуларга жавоб бериш қобилиятини камайтириши мумкин.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Мавжуд сўнгги нуқталар ҳақида кўпроқ билиш учун ҳужжатларимизга ташриф буюринг.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Бу ерда асбоблар тўпламини танлаш учун аввал уларни “Асбоблар” иш майдонига қўшинг.", - "Toast notifications for new updates": "Янги янгиланишлар ҳақида билдиришномалар", + "Toast Notifications for New Updates": "Янги янгиланишлар ҳақида билдиришномалар", "Today": "Бугун", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Токен", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Жуда батафсил", @@ -2184,14 +2350,19 @@ "Unpin": "Ечиш", "Unpin from Sidebar": "", "Unravel secrets": "Сирларни очинг", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Белгиланмаган", "Untitled": "Сарлавҳасиз", "Update": "Янгилаш", "Update and Copy Link": "Ҳаволани янгилаш ва нусхалаш", + "Update Email": "", "Update for the latest features and improvements.": "Энг янги хусусиятлар ва яхшиланишлар учун янгиланг.", + "Update Name": "", "Update password": "Паролни янгиланг", + "Update Picture": "", "Update your status": "", "Updated": "Янгиланган", "Updated at": "Янгиланган", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Ўз билимларингизни юклаш ва киритиш учун сўровномада \"#\" дан фойдаланинг.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "ЛЛМ дан фойдаланинг", "Use no proxy to fetch page contents.": "Саҳифа мазмунини олиш учун прокси-сервердан фойдаланманг.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Саҳифа мазмунини олиш учун http_proxy ва https_proxy муҳит ўзгарувчилари томонидан белгиланган прокси-сервердан фойдаланинг.", + "Use Web Search?": "", "user": "фойдаланувчи", "User": "Фойдаланувчи", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Фойдаланувчи жойлашуви муваффақиятли олинди.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Фойдаланувчи веб-ҳуклари", "Username": "Фойдаланувчи номи", + "Username Claim": "", "users": "", "Users": "Фойдаланувчилар", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Ёқиш/Ўчириш параметрлари янгиланди", "Valves updated successfully": "Ёқиш/Ўчириш параметрлари муваффақиятли янгиланди", "variable": "ўзгарувчи ", + "Vector Field": "", "Verify Connection": "Уланишни текширинг", "Verify SSL Certificate": "SSL сертификатини текширинг", "Version": "Версия", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "Web Loader Engine", "Web Search": "Веб-қидирув", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Веб қидирув тизими", "Web Search in Chat": "Чатда веб-қидирув", "Web Search Query Generation": "Веб-қидирув сўровларини яратиш", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook УРЛ манзили", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI созламалари", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Кеча", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Сиз", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Сизнинг барча ҳиссангиз тўғридан-тўғри плагин ишлаб чиқарувчисига ўтади; Open WebUI ҳеч қандай фоизни олмайди. Бироқ, танланган молиялаштириш платформаси ўз тўловларига эга бўлиши мумкин.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube тили", diff --git a/src/lib/i18n/locales/uz-Latn-Uz/translation.json b/src/lib/i18n/locales/uz-Latn-Uz/translation.json index bdaf45cd65..7834f77560 100644 --- a/src/lib/i18n/locales/uz-Latn-Uz/translation.json +++ b/src/lib/i18n/locales/uz-Latn-Uz/translation.json @@ -16,6 +16,10 @@ "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_one": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_one": "", + "{{count}} filters_other": "", + "{{count}} groups_one": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} ta yashirin chiziq", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_one": "", @@ -25,12 +29,16 @@ "{{count}} selected_one": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_one": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -38,8 +46,10 @@ "{{user}}'s Chats": "{{user}} ning chatlari", "{{webUIName}} Backend Required": "{{webUIName}} Backend talab qilinadi", "*Prompt node ID(s) are required for image generation": "*Rasm yaratish uchun tezkor tugun identifikatorlari talab qilinadi", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -57,6 +67,7 @@ "Access Control": "Kirish nazorati", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Barcha foydalanuvchilar uchun ochiq", "Account": "Hisob", @@ -72,6 +83,7 @@ "Activity": "", "Add": "Qo'shish", "Add a model ID": "Model identifikatorini qo'shing", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Ushbu model nima qilishi haqida qisqacha tavsif qo'shing", "Add a tag": "Teg qo'shing", "Add a tag...": "", @@ -84,8 +96,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Fayllarni qo'shish", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -100,6 +114,7 @@ "Add to favorites": "", "Add User": "Foydalanuvchi qo'shish", "Add User Group": "Foydalanuvchilar guruhini qo'shish", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -112,7 +127,9 @@ "Admin": "Admin", "Admin Contact Email": "", "Admin Panel": "Administrator paneli", + "Admin Roles": "", "Admin Settings": "Administrator sozlamalari", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Administratorlar har doim barcha vositalardan foydalanishlari mumkin; foydalanuvchilarga ish joyida har bir model uchun tayinlangan vositalar kerak bo'ladi.", "Advanced": "", "Advanced Parameters": "Kengaytirilgan parametrlar", @@ -123,16 +140,21 @@ "All": "Hammasi", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Barcha modellar muvaffaqiyatli o'chirildi", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "Qo'ng'iroqqa ruxsat berish", "Allow Chat Controls": "Chat boshqaruviga ruxsat bering", "Allow Chat Delete": "Chatni oʻchirishga ruxsat bering", "Allow Chat Edit": "Chatni tahrirlashga ruxsat bering", "Allow Chat Export": "Chat eksportiga ruxsat bering", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "Chat almashishga ruxsat bering", "Allow Chat System Prompt": "", @@ -152,9 +174,11 @@ "Allow User Location": "Foydalanuvchi joylashuviga ruxsat berish", "Allow Voice Interruption in Call": "Qo'ng'iroqda ovozli uzilishga ruxsat bering", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Ruxsat etilgan oxirgi nuqtalar", "Allowed File Extensions": "Ruxsat etilgan fayl kengaytmalari", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Yuklash uchun ruxsat berilgan fayl kengaytmalari. Bir nechta kengaytmalarni vergul bilan ajrating. Barcha fayl turlari uchun bo'sh qoldiring.", + "Allowed Roles": "", "Already have an account?": "Hisobingiz bormi?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Top_p ga muqobil va sifat va xilma-xillik muvozanatini ta'minlashga qaratilgan. p parametri tokenning ko'rib chiqilishining minimal ehtimolini ifodalaydi, bu tokenning ehtimoliy ehtimoliga nisbatan. Misol uchun, p=0,05 va eng ehtimolli token 0,9 ehtimolga ega bo'lsa, qiymati 0,045 dan kam bo'lgan logitlar filtrlanadi.", "Always": "Har doim", @@ -173,6 +197,7 @@ "API Base URL": "API bazasi URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API kaliti", + "API Key / Token": "", "API Key created.": "API kaliti yaratildi.", "API Key Endpoint Restrictions": "API kalit so'nggi nuqta cheklovlari", "API keys": "API kalitlari", @@ -202,13 +227,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Haqiqatan ham bu xabarni oʻchirib tashlamoqchimisiz?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Haqiqatan ham barcha arxivlangan chatlarni arxivdan chiqarmoqchimisiz?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Arena modellari", "Artifacts": "Artefaktlar", "Asc": "", "Ask": "So'rang", "Ask a question": "Savol bering", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Yordamchi", "Async Embedding Processing": "", "At time of event": "", @@ -223,14 +253,20 @@ "Audio": "Audio", "August": "avgust", "Auth": "Avtor", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Autentifikatsiya qilish", "Authentication": "Autentifikatsiya", "Auto": "Avtomatik", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Javobni vaqtinchalik xotiraga avtomatik nusxalash", - "Auto-playback response": "Avtomatik ijro javobi", + "Auto-Create Groups": "", + "Auto-Playback Response": "Avtomatik ijro javobi", "Autocomplete Generation": "Avtoto'ldirishni yaratish", "Autocomplete Generation Input Max Length": "Avtomatik toʻldirish ishlab chiqarish kiritish maksimal uzunligi", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Avtomatik 1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api Auth String", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 asosiy URL", @@ -248,6 +284,7 @@ "Available Skills": "", "Available Tools": "Mavjud asboblar", "available users": "mavjud foydalanuvchilar", + "Available variables": "", "available!": "mavjud!", "Away": "Uzoqda", "Awful": "Dahshatli", @@ -258,16 +295,17 @@ "Bad Response": "Yomon javob", "Banners": "Bannerlar", "Base Model (From)": "Asosiy model (dan boshlab)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "oldin", "Being lazy": "Dangasa bo'lish", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Bing Search V7 Endpoint", "Bing Search V7 Subscription Key": "Bing Search V7 obuna kaliti", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Bocha qidiruv API kaliti", "Bold": "", @@ -324,7 +362,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Chat yo'nalishi", + "Chat Direction": "Chat yo'nalishi", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -396,6 +434,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Yiqilish", "Collection": "To'plam", + "Collection Field": "", "Collections": "", "Color": "Rang", "ComfyUI": "ComfyUI", @@ -405,12 +444,14 @@ "ComfyUI Workflow": "ComfyUI ish jarayoni", "ComfyUI Workflow Nodes": "ComfyUI ish oqimi tugunlari", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Buyruq", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Tugallashlar", "Compress Images in Channels": "", @@ -432,6 +473,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "O'zingizning OpenAI-ga mos keladigan API so'nggi nuqtalariga ulaning.", "Connect to your own OpenAPI compatible external tool servers.": "O'zingizning OpenAPI-ga mos keladigan tashqi asboblar serverlariga ulaning.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Ulanish amalga oshmadi", "Connection lost. Reconnecting...": "", @@ -444,8 +486,16 @@ "Contact Admin for WebUI Access": "WebUI-ga kirish uchun administrator bilan bog'laning", "Content": "Tarkib", "Content Extraction Engine": "Kontentni ajratib olish mexanizmi", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Javob berishni davom ettirish", "Continue with {{provider}}": "{{provider}} bilan davom eting", "Continue with Email": "Elektron pochta orqali davom eting", @@ -493,6 +543,7 @@ "Create new secret key": "Yangi maxfiy kalit yarating", "Create note": "", "Create Note": "Eslatma yaratish", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "Quyidagi ortiqcha tugmasini bosish orqali birinchi qaydingizni yarating.", "Created at": "Yaratilgan", @@ -510,6 +561,7 @@ "Custom Gender": "", "Custom Parameter Name": "Maxsus parametr nomi", "Custom Parameter Value": "Maxsus parametr qiymati", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Xavfli zona", @@ -532,7 +584,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "", "Default Model": "Standart model", "Default model updated": "Standart model yangilandi", "Default permissions": "Birlamchi ruxsatlar", @@ -542,6 +593,7 @@ "Default to ALL": "ALL uchun birlamchi", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Fokuslangan va tegishli kontentni ajratib olish uchun birlamchi segmentlangan qidirish, bu koʻp hollarda tavsiya etiladi.", "Default User Role": "Odatiy foydalanuvchi roli", + "Default webhook": "", "Defaults": "", "Delete": "Oʻchirish", "Delete {{name}}": "", @@ -602,6 +654,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "Rasm chiqarishni o'chirib qo'ying", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "PDF-dan tasvirni ajratib olishni o'chirib qo'ying. Agar LLM dan foydalanish yoqilgan boʻlsa, tasvirlarga avtomatik sarlavha qoʻyiladi. Birlamchi parametrlar False.", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "O'chirilgan", "Disconnect OAuth": "", "Discover a function": "Funktsiyani kashf qilish", @@ -616,10 +670,10 @@ "Discover, download, and explore model presets": "Model sozlamalarini kashf eting, yuklab oling va o'rganing", "Discussion channel where access is based on groups and permissions": "", "Display": "Displey", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Chaqiruvda kulgichlarni ko‘rsatish", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Chatda Siz o'rniga foydalanuvchi nomini ko'rsating", + "Display the Username Instead of You in the Chat": "Chatda Siz o'rniga foydalanuvchi nomini ko'rsating", "Displays citations in the response": "Javobda iqtiboslarni ko'rsatadi", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Bilimga sho'ng'ing", @@ -630,6 +684,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Docling Server URL manzili talab qilinadi.", "Document": "Hujjat", + "Document ID Field": "", "Document Intelligence": "Hujjat razvedkasi", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -685,12 +740,14 @@ "Edit Default Permissions": "Standart ruxsatlarni tahrirlash", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Xotirani tahrirlash", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Foydalanuvchini tahrirlash", "Edit User Group": "Foydalanuvchilar guruhini tahrirlash", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -699,6 +756,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Elektron pochta", + "Email Claim": "", "Embark on adventures": "Sarguzashtlarga kirishing", "Embedding": "Oʻrnatish", "Embedding Batch Size": "O'rnatish to'plami hajmi", @@ -707,6 +765,7 @@ "Embedding Model Engine": "Dvigatel modelini o'rnatish", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -714,22 +773,27 @@ "Enable Code Execution": "Kod bajarilishini yoqing", "Enable Code Interpreter": "Kod tarjimonini yoqing", "Enable Community Sharing": "Hamjamiyat bilan almashishni yoqing", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Model ma'lumotlarini RAMdan almashtirishning oldini olish uchun Xotirani qulflashni (mlock) yoqing. Ushbu parametr modelning ishlaydigan sahifalar to'plamini RAMga bloklaydi va ular diskka almashtirilmasligini ta'minlaydi. Bu sahifa xatolaridan qochish va ma'lumotlarga tezkor kirishni ta'minlash orqali ishlashni saqlashga yordam beradi.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Model ma'lumotlarini yuklash uchun Xotira xaritasini (mmap) yoqing. Ushbu parametr tizimga disk fayllarini operativ xotirada bo'lganidek davolash orqali RAM kengaytmasi sifatida disk xotirasidan foydalanish imkonini beradi. Bu maʼlumotlarga tezroq kirish imkonini berish orqali model ish faoliyatini yaxshilashi mumkin. Biroq, u barcha tizimlar bilan to'g'ri ishlamasligi va katta hajmdagi disk maydonini iste'mol qilishi mumkin.", "Enable Message Queue": "", "Enable Message Rating": "Xabar reytingini yoqish", "Enable Mirostat sampling for controlling perplexity.": "Ajablanishni nazorat qilish uchun Mirostat namunasini yoqing.", "Enable New Sign Ups": "Yangi ro'yxatdan o'tishni yoqing", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Yoqilgan", "End Tag": "", + "Endpoint": "", "Endpoint URL": "Oxirgi nuqta URL", "Enforce Temporary Chat": "Vaqtinchalik suhbatni joriy qilish", "Enhance": "Yaxshilash", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV faylingiz quyidagi tartibda 4 ta ustundan iboratligiga ishonch hosil qiling: Ism, Elektron pochta, Parol, Rol.", "Enter {{role}} message here": "Bu yerga {{role}} xabarini kiriting", - "Enter a detail about yourself for your LLMs to recall": "LLMlar eslab qolishlari uchun oʻzingiz haqingizda maʼlumot kiriting", "Enter a title for the pending user info overlay. Leave empty for default.": "Kutilayotgan foydalanuvchi maʼlumotlari uchun sarlavha kiriting. Sukut bo'yicha bo'sh qoldiring.", "Enter a watermark for the response. Leave empty for none.": "Javob uchun moybo'yoqli belgini kiriting. Hech kim uchun bo'sh qoldiring.", "Enter additional headers in JSON format": "", @@ -746,6 +810,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Chunk Overlap-ni kiriting", "Enter Chunk Size": "Chunk hajmini kiriting", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Vergul bilan ajratilgan \"token:bias_value\" juftlarini kiriting (misol: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Kutilayotgan foydalanuvchi ma'lumotlari qoplamasi uchun tarkibni kiriting. Sukut bo'yicha bo'sh qoldiring.", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -783,8 +849,11 @@ "Enter Jupyter URL": "Jupyter URL manzilini kiriting", "Enter Kagi Search API Key": "Kagi Search API kalitini kiriting", "Enter Key Behavior": "Asosiy xatti-harakatni kiriting", + "Enter language": "", "Enter language codes": "Til kodlarini kiriting", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Mistral API kalitini kiriting", @@ -804,6 +873,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Proksi-serverning URL manzilini kiriting (masalan, https://user:password@host:port)", "Enter reasoning effort": "Fikrlash harakatini kiriting", + "Enter Redirect URI": "", "Enter Score": "Balni kiriting", "Enter SearchApi API Key": "SearchApi API kalitini kiriting", "Enter SearchApi Engine": "SearchApi tizimiga kiring", @@ -813,6 +883,7 @@ "Enter SerpApi API Key": "SerpApi API kalitini kiriting", "Enter SerpApi Engine": "SerpApi dvigateliga kiring", "Enter Serper API Key": "Serper API kalitini kiriting", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Serply API kalitini kiriting", "Enter Serpstack API Key": "Serpstack API kalitini kiriting", "Enter server host": "Server xostiga kiring", @@ -833,6 +904,8 @@ "Enter Tika Server URL": "Tika Server URL manzilini kiriting", "Enter timeout in seconds": "Vaqt tugashini soniyalarda kiriting", "Enter to Send": "Yuborish uchun kiring", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Top K.ga kiring", "Enter Top K Reranker": "Top K Reranker-ga kiring", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL manzilini kiriting (masalan, http://127.0.0.1:7860/)", @@ -873,11 +946,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Baholar", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Exa API kaliti", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Misol: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Misol: ALL", "Example: mail": "Misol: pochta", @@ -905,12 +982,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "CSV ga eksport qilish", "Export Tools": "", "Export Users": "", "External": "Tashqi", + "External connection not found.": "", "External Document Loader URL required.": "Tashqi hujjat yuklovchi URL manzili talab qilinadi.", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "Tashqi vazifa modeli", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "Tashqi Web Loader API kaliti", "External Web Loader URL": "Tashqi veb yuklovchi URL manzili", "External Web Search API Key": "Tashqi veb-qidiruv API kaliti", @@ -928,6 +1011,7 @@ "Failed to create API Key.": "API kalitini yaratib bo‘lmadi.", "Failed to delete calendar": "", "Failed to delete note": "Qaydni o‘chirib bo‘lmadi", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -935,6 +1019,7 @@ "Failed to fetch models": "Modellarni olib bo‘lmadi", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -944,6 +1029,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Bufer tarkibini o‘qib bo‘lmadi", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -952,9 +1038,11 @@ "Failed to save models configuration": "Modellar konfiguratsiyasi saqlanmadi", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Sozlamalarni yangilab bo‘lmadi", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Fayl yuklanmadi.", "Features": "Xususiyatlari", "Features Permissions": "Xususiyatlar Ruxsatlar", @@ -987,6 +1075,8 @@ "File uploaded successfully": "Fayl muvaffaqiyatli yuklandi", "Filename": "", "Files": "Fayllar", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Filtr endi butun dunyo bo'ylab o'chirib qo'yilgan", "Filter is now globally enabled": "Filtr endi global miqyosda yoqilgan", @@ -1009,6 +1099,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1039,6 +1130,7 @@ "Function is now globally enabled": "Funktsiya endi global miqyosda yoqilgan", "Function Name": "Funktsiya nomi", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Funktsiya muvaffaqiyatli yangilandi", "Functions": "Funksiyalar", "Functions allow arbitrary code execution.": "Funktsiyalar o'zboshimchalik bilan kodni bajarishga imkon beradi.", @@ -1071,7 +1163,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Guruh muvaffaqiyatli yaratildi", "Group deleted successfully": "Guruh muvaffaqiyatli oʻchirildi", "Group Description": "Guruh tavsifi", @@ -1083,6 +1178,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Haptik fikr-mulohazalar", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1113,6 +1209,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "iframe Sandbox ruxsat shakllari", "iframe Sandbox Allow Same Origin": "iframe Sandbox bir xil kelib chiqishiga ruxsat beradi", @@ -1138,6 +1236,7 @@ "Import From Link": "Havoladan import qilish", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Muhim yangilanish", @@ -1195,7 +1294,6 @@ "Keep in Sidebar": "", "Key": "Kalit", "Key is required": "", - "Keyboard shortcuts": "Klaviatura yorliqlari", "Keyboard Shortcuts": "", "Knowledge": "Bilim", "Knowledge Access": "Bilimga kirish", @@ -1208,6 +1306,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Bilimlarni ommaviy almashish", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Bilim muvaffaqiyatli yangilandi", "Kokoro.js (Browser)": "Kokoro.js (brauzer)", "Kokoro.js Dtype": "Kokoro.js D turi", @@ -1224,7 +1324,6 @@ "Last ran": "", "Last reply": "Oxirgi javob", "LDAP": "LDAP", - "LDAP server updated": "LDAP serveri yangilandi", "Leaderboard": "Peshqadamlar jadvali", "Learn more": "", "Learn More": "", @@ -1246,6 +1345,7 @@ "Legacy": "", "lexical": "", "License": "Litsenziya", + "Lifecycle JSON": "", "Lift List": "", "Light": "Nur", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1269,6 +1369,7 @@ "Location access not allowed": "Joylashuvga ruxsat berilmagan", "Lost": "Yo'qotilgan", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Open WebUI hamjamiyati tomonidan yaratilgan", "Make password visible in the user interface": "", @@ -1285,6 +1386,7 @@ "Manage Pipelines": "Quvurlarni boshqarish", "Manage Tool Servers": "Asbob serverlarini boshqarish", "Manage your account information.": "", + "Mapped Source": "", "March": "Mart", "Markdown": "Markdown", "Markdown Header Text Splitter": "", @@ -1312,6 +1414,7 @@ "Memory cleared successfully": "Xotira muvaffaqiyatli tozalandi", "Memory deleted successfully": "Xotira muvaffaqiyatli oʻchirildi", "Memory updated successfully": "Xotira muvaffaqiyatli yangilandi", + "Merge Accounts by Email": "", "Merge Responses": "Javoblarni birlashtirish", "Merged Response": "Birlashtirilgan javob", "Message": "", @@ -1322,9 +1425,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Havolani yaratganingizdan keyin yuborgan xabarlaringiz ulashilmaydi. URL manzili bo'lgan foydalanuvchilar umumiy chatni ko'rishlari mumkin bo'ladi.", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive (shaxsiy)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive (ish/maktab)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1377,6 +1483,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Mojeek qidiruv API kaliti", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Ko'proq", @@ -1394,6 +1501,7 @@ "Name your knowledge base": "Bilimlar bazasini nomlang", "Name, prompt, and model are required": "", "Native": "Mahalliy", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1423,6 +1531,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1435,8 +1544,10 @@ "No data": "", "No data found": "", "No distance available": "Masofa mavjud emas", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Hech qanday fayl tanlanmagan", "No files found": "", @@ -1464,6 +1575,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Hech qanday natija topilmadi", "No results found": "Hech qanday natija topilmadi", "No search query generated": "Hech qanday qidiruv soʻrovi yaratilmadi", @@ -1483,6 +1595,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Yo'q", + "Not configured": "", "Not factually correct": "Aslida to'g'ri emas", "Not helpful": "Foydali emas", "Not Registered": "", @@ -1498,20 +1611,25 @@ "Notifications": "Bildirishnomalar", "November": "noyabr", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "oktyabr", "Off": "Oʻchirilgan", "Okay, Let's Go!": "Mayli, ketaylik!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED qorong'i", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API sozlamalari yangilandi", "Ollama Cloud API Key": "", "Ollama Version": "Ollama versiyasi", + "Omit": "", "On": "Yoniq", "Once": "", "OneDrive": "OneDrive", @@ -1582,6 +1700,7 @@ "Password": "Parol", "Passwords do not match.": "", "Paste Large Text as File": "Katta matnni fayl sifatida joylashtiring", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "PDF hujjat (.pdf)", @@ -1590,18 +1709,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "kutilmoqda", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "Kutilayotgan foydalanuvchi Overlay kontenti", "Pending User Overlay Title": "Kutilayotgan foydalanuvchi sarlavhasi", "Permission denied when accessing media devices": "Media qurilmalarga kirishda ruxsat rad etildi", "Permission denied when accessing microphone": "Mikrofonga kirishda ruxsat berilmadi", "Permission denied when accessing microphone: {{error}}": "Mikrofonga kirishda ruxsat rad etildi: {{error}}", "Permissions": "Ruxsatlar", + "Permissions reset to defaults": "", "Perplexity API Key": "Qiyinchilik API kaliti", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Shaxsiylashtirish", + "Picture Claim": "", "Pin": "Pin", "Pin to Sidebar": "", "Pinned": "Qadalgan", @@ -1634,13 +1756,13 @@ "Please fill in all fields.": "Iltimos, barcha maydonlarni toʻldiring.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Iltimos, avval modelni tanlang.", "Please select a model.": "Iltimos, modelni tanlang.", "Please select a reason": "Sababini tanlang", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Port", "Ports": "", "Positive attitude": "Ijobiy munosabat", @@ -1670,6 +1792,8 @@ "Prompts Public Sharing": "Umumiy almashishni taklif qiladi", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Ommaviy", "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com saytidan “{{searchValue}}”ni torting", "Pull a model from Ollama.com": "Ollama.com dan modelni torting", @@ -1687,21 +1811,29 @@ "Read": "O'qing", "Read Aloud": "Ovoz chiqarib o'qing", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Mulohaza yuritish harakatlari", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "Yozib olish", "Record voice": "Ovozni yozib oling", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Sizni Open WebUI hamjamiyatiga yoʻnaltirmoqda", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Bema'ni narsalarni yaratish ehtimolini kamaytiradi. Yuqori qiymat (masalan, 100) turli xil javoblar beradi, pastroq qiymat (masalan, 10) esa konservativ bo'ladi.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "O'zingizni \"Foydalanuvchi\" deb ko'rsating (masalan, \"Foydalanuvchi ispan tilini o'rganmoqda\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_one": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Bo'lmasligi kerak bo'lganda rad etildi", "Regenerate": "Qayta tiklash", "Regenerate Menu": "", @@ -1735,19 +1867,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Modellarni qayta tartiblash", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Mavzuda javob bering", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "Dvigatelni qayta tartiblash", "Reranking Model": "Qayta tartiblash modeli", + "Research Knowledge": "", "Reset": "Qayta tiklash", "Reset All Models": "Barcha modellarni qayta o'rnatish", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Rasmni qayta tiklash", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Yuklash katalogini tiklash", "Reset Vector Storage/Knowledge": "Vektor xotirasi/bilimini qayta o'rnatish", "Reset view": "Ko'rinishni tiklash", @@ -1767,6 +1906,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Chat uchun boy matn kiritish", "Role": "Rol", + "Roles Claim": "", "RTL": "RTL", "Run": "Yugurish", "Run All": "", @@ -1785,10 +1925,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Chat jurnallarini bevosita brauzeringiz xotirasiga saqlash endi qo‘llab-quvvatlanmaydi. Quyidagi tugmani bosish orqali suhbat jurnallaringizni yuklab oling va oʻchiring. Xavotir olmang, siz chat jurnallarini backend orqali osongina qayta import qilishingiz mumkin", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "Filialni o'zgartirish bo'yicha aylantiring", "Scroll to Top": "", "Search": "Qidiruv", "Search a model": "Modelni qidiring", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1798,6 +1940,7 @@ "Search Chats": "Chatlarni qidirish", "Search Collection": "To'plamni qidirish", "Search Files": "", + "Search filters": "", "Search Filters": "Qidiruv filtrlari", "search for archived chats": "", "search for folders": "", @@ -1812,13 +1955,16 @@ "Search Models": "Modellarni qidirish", "Search Notes": "", "Search options": "Qidiruv variantlari", + "Search or add pattern": "", "Search Prompts": "Qidiruv ko'rsatmalari", "Search Result Count": "Qidiruv natijalari soni", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Internetda qidiring", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Qidiruv vositalari", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "SearchApi API kaliti", "SearchApi Engine": "SearchApi mexanizmi", @@ -1834,7 +1980,6 @@ "Seed": "Urug'", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Asosiy modelni tanlang", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Dvigatelni tanlang", @@ -1872,18 +2017,25 @@ "semantic": "", "Send": "Yuborish", "Send a Message": "Xabar yuborish", + "Send events for": "", "Send message": "Xabar yuborish", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "So‘rovda `stream_options: { include_usage: true }` yuboradi.\nQo'llab-quvvatlanadigan provayderlar o'rnatilganda javobda token foydalanish ma'lumotlarini qaytaradi.", "September": "sentyabr", "SerpApi API Key": "SerpApi API kaliti", "SerpApi Engine": "SerpApi dvigateli", "Serper API Key": "Serper API kaliti", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API kaliti", "Serpstack API Key": "Serpstack API kaliti", "Server connection failed": "", "Server connection verified": "Server ulanishi tasdiqlandi", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Standart sifatida o'rnating", "Set as Production": "", "Set embedding model": "O'rnatish modelini o'rnating", @@ -1911,15 +2063,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Open WebUI hamjamiyatiga ulashing", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Ruxsatlarni almashish", "Show": "Ko'rsatish", - "Show \"What's New\" modal on login": "Kirishda \"Yangi narsalar\" modalini ko'rsating", + "Show \"What's New\" Modal on Login": "Kirishda \"Yangi narsalar\" modalini ko'rsating", "Show Admin Details in Account Pending Overlay": "Hisob kutilayotgan qatlamda administrator ma’lumotlarini ko‘rsatish", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Modelni ko'rsatish", @@ -1963,6 +2117,7 @@ "Sougou Search API sID": "Sougou Search API sID", "Sougou Search API SK": "Sougou Search API SK", "Source": "Manba", + "Specific users or groups": "", "Speech Playback Speed": "Nutqni ijro etish tezligi", "Speech recognition error: {{error}}": "Nutqni aniqlashda xatolik: {{error}}", "Speech-to-Text": "", @@ -1999,6 +2154,7 @@ "STT Settings": "STT sozlamalari", "Stylized PDF Export": "Stillashtirilgan PDF eksporti", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2023,8 +2179,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Tizim", + "System events only": "", "System Instructions": "Tizim ko'rsatmalari", "System Prompt": "Tizim so'rovi", + "Table": "", "Tag": "", "Tags": "Teglar", "Tags Generation": "Teglar yaratish", @@ -2045,6 +2203,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Matn ajratuvchi", "Text-to-Speech": "", "Text-to-Speech Engine": "Matnni nutqqa aylantirish mexanizmi", @@ -2060,7 +2224,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "Kirish audiosining tili. Kirish tilini ISO-639-1 (masalan, en) formatida taqdim etish aniqlik va kechikishni yaxshilaydi. Tilni avtomatik aniqlash uchun bo'sh qoldiring.", "The LDAP attribute that maps to the mail that users use to sign in.": "LDAP atributi foydalanuvchilarning tizimga kirishda foydalanadigan pochta manziliga mos keladi.", "The LDAP attribute that maps to the username that users use to sign in.": "Foydalanuvchilar tizimga kirish uchun foydalanadigan foydalanuvchi nomiga mos keladigan LDAP atributi.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Peshqadamlar jadvali hozirda beta-versiyada va biz algoritmni takomillashtirish jarayonida reyting hisob-kitoblarini sozlashimiz mumkin.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Faylning maksimal hajmi MB. Agar fayl hajmi ushbu chegaradan oshsa, fayl yuklanmaydi.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Chatda bir vaqtning o'zida ishlatilishi mumkin bo'lgan maksimal fayllar soni. Agar fayllar soni ushbu chegaradan oshsa, fayllar yuklanmaydi.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "Matn uchun chiqish formati. \"json\", \"markdown\" yoki \"html\" bo'lishi mumkin. Birlamchi \"markdown\" uchun.", @@ -2082,6 +2245,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Bu eksperimental xususiyat bo'lib, u kutilganidek ishlamasligi va istalgan vaqtda o'zgarishi mumkin.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "Ushbu model hamma uchun ochiq emas. Iltimos, boshqa modelni tanlang.", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Ushbu parametr kontekstni yangilashda qancha tokenlar saqlanishini nazorat qiladi. Masalan, agar 2 ga oʻrnatilgan boʻlsa, suhbat kontekstining oxirgi 2 ta belgisi saqlanib qoladi. Kontekstni saqlash suhbatning uzluksizligini saqlashga yordam beradi, lekin bu yangi mavzularga javob berish qobiliyatini kamaytirishi mumkin.", @@ -2122,7 +2286,7 @@ "To learn more about available endpoints, visit our documentation.": "Mavjud so'nggi nuqtalar haqida ko'proq bilish uchun hujjatlarimizga tashrif buyuring.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Bu yerda asboblar to‘plamini tanlash uchun avval ularni “Asboblar” ish maydoniga qo‘shing.", - "Toast notifications for new updates": "Yangi yangilanishlar haqida bildirishnomalar", + "Toast Notifications for New Updates": "Yangi yangilanishlar haqida bildirishnomalar", "Today": "Bugun", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2136,6 +2300,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Juda batafsil", @@ -2184,14 +2350,19 @@ "Unpin": "Yechish", "Unpin from Sidebar": "", "Unravel secrets": "Sirlarni oching", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Belgilanmagan", "Untitled": "Sarlavhasiz", "Update": "Yangilash", "Update and Copy Link": "Havolani yangilash va nusxalash", + "Update Email": "", "Update for the latest features and improvements.": "Eng yangi xususiyatlar va yaxshilanishlar uchun yangilang.", + "Update Name": "", "Update password": "Parolni yangilang", + "Update Picture": "", "Update your status": "", "Updated": "Yangilangan", "Updated at": "Yangilangan", @@ -2218,13 +2389,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "O'z bilimlaringizni yuklash va kiritish uchun so'rovnomada \"#\" dan foydalaning.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "LLM dan foydalaning", "Use no proxy to fetch page contents.": "Sahifa mazmunini olish uchun proksi-serverdan foydalanmang.", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Sahifa mazmunini olish uchun http_proxy va https_proxy muhit oʻzgaruvchilari tomonidan belgilangan proksi-serverdan foydalaning.", + "Use Web Search?": "", "user": "foydalanuvchi", "User": "Foydalanuvchi", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Foydalanuvchi joylashuvi muvaffaqiyatli olindi.", @@ -2234,6 +2410,7 @@ "User Status": "", "User Webhooks": "Foydalanuvchi veb-huklari", "Username": "Foydalanuvchi nomi", + "Username Claim": "", "users": "", "Users": "Foydalanuvchilar", "Uses DefaultAzureCredential to authenticate": "", @@ -2247,6 +2424,7 @@ "Valves updated": "Vanalar yangilandi", "Valves updated successfully": "Vanalar muvaffaqiyatli yangilandi", "variable": "o'zgaruvchan", + "Vector Field": "", "Verify Connection": "Ulanishni tekshiring", "Verify SSL Certificate": "SSL sertifikatini tekshiring", "Version": "Versiya", @@ -2276,11 +2454,14 @@ "Web API": "Web API", "Web Loader Engine": "Web Loader Engine", "Web Search": "Veb-qidiruv", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Veb qidiruv tizimi", "Web Search in Chat": "Chatda veb-qidiruv", "Web Search Query Generation": "Veb-qidiruv so'rovlarini yaratish", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL manzili", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "WebUI sozlamalari", @@ -2323,6 +2504,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Kecha", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Siz", @@ -2352,6 +2534,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Sizning barcha hissangiz to'g'ridan-to'g'ri plagin ishlab chiqaruvchisiga o'tadi; Open WebUI hech qanday foizni olmaydi. Biroq, tanlangan moliyalashtirish platformasi o'z to'lovlariga ega bo'lishi mumkin.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Youtube tili", diff --git a/src/lib/i18n/locales/vi-VN/translation.json b/src/lib/i18n/locales/vi-VN/translation.json index caa99da54f..d86bf590da 100644 --- a/src/lib/i18n/locales/vi-VN/translation.json +++ b/src/lib/i18n/locales/vi-VN/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "", "{{COUNT}} files": "", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "{{COUNT}} dòng bị ẩn", "{{COUNT}} members": "", "{{count}} of {{total}} accessible_other": "", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "", "{{count}} selected_other": "", "{{COUNT}} Sources": "", + "{{count}} users_other": "", "{{COUNT}} words": "", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", "{{model}} download has been canceled": "", "{{modelName}} profile image": "", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "Các cuộc trò chuyện của {{user}}", "{{webUIName}} Backend Required": "{{webUIName}} Yêu cầu Backend", "*Prompt node ID(s) are required for image generation": "*ID nút Prompt là bắt buộc để tạo ảnh", + "1 group": "", "1 hour before": "", "1 Source": "", + "1 user": "", "10 minutes before": "", "15 minutes before": "", "1m_time_ago": "", @@ -54,6 +61,7 @@ "Access Control": "Kiểm soát truy cập", "Access Grants": "", "Access List": "", + "Access prohibited": "", "Access updated": "", "Accessible to all users": "Truy cập được bởi tất cả người dùng", "Account": "Tài khoản", @@ -69,6 +77,7 @@ "Activity": "", "Add": "Thêm", "Add a model ID": "Thêm ID mô hình", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "Thêm mô tả ngắn về những khả năng của model", "Add a tag": "Thêm thẻ (tag)", "Add a tag...": "", @@ -81,8 +90,10 @@ "Add Custom Prompt": "", "Add description": "", "Add Details": "", + "Add durable context for future chats": "", "Add Files": "Thêm tệp", "Add Image": "", + "Add Knowledge Connection": "", "Add location": "", "Add Member": "", "Add Members": "", @@ -97,6 +108,7 @@ "Add to favorites": "", "Add User": "Thêm người dùng", "Add User Group": "Thêm Nhóm Người dùng", + "Add webhook": "", "Add webpage": "", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "", @@ -109,7 +121,9 @@ "Admin": "Quản trị", "Admin Contact Email": "", "Admin Panel": "Trang Quản trị", + "Admin Roles": "", "Admin Settings": "Cài đặt hệ thống", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Quản trị viên luôn có quyền truy cập vào tất cả các tool; người dùng cần các tools được chỉ định cho mỗi mô hình trong workspace.", "Advanced": "", "Advanced Parameters": "Các tham số Nâng cao", @@ -120,16 +134,21 @@ "All": "Tất cả", "All chats have been unarchived.": "", "All day": "", + "All events": "", "All models are now hidden": "", "All models are now visible": "", "All models deleted successfully": "Tất cả các mô hình đã được xóa thành công", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "", "All Users": "", + "All users and system events": "", "Allow Call": "", "Allow Chat Controls": "Cho phép Điều khiển Chat", "Allow Chat Delete": "Cho phép Xóa Chat", "Allow Chat Edit": "Cho phép Chỉnh sửa Chat", "Allow Chat Export": "", + "Allow Chat Import": "", "Allow Chat Params": "", "Allow Chat Share": "", "Allow Chat System Prompt": "", @@ -149,9 +168,11 @@ "Allow User Location": "Cho phép sử dụng vị trí người dùng", "Allow Voice Interruption in Call": "Cho phép gián đoạn giọng nói trong cuộc gọi", "Allow Web Upload": "", + "Allowed Domains": "", "Allowed Endpoints": "Các Endpoint được phép", "Allowed File Extensions": "", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed Roles": "", "Already have an account?": "Bạn đã có tài khoản?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "Thay thế cho top_p, nhằm đảm bảo cân bằng giữa chất lượng và sự đa dạng. Tham số p đại diện cho xác suất tối thiểu để một token được xem xét, tương đối so với xác suất của token có khả năng cao nhất. Ví dụ: với p=0.05 và token có khả năng cao nhất có xác suất 0.9, các logit có giá trị nhỏ hơn 0.045 sẽ bị lọc ra.", "Always": "Luôn luôn", @@ -170,6 +191,7 @@ "API Base URL": "Đường dẫn tới API (API Base URL)", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", "API Key": "API Key", + "API Key / Token": "", "API Key created.": "Khóa API đã tạo", "API Key Endpoint Restrictions": "Hạn chế Endpoint Khóa API", "API keys": "API Keys", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "", "Are you sure you want to delete this message?": "Bạn có chắc chắn muốn xóa tin nhắn này không?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "Bạn có chắc chắn muốn bỏ lưu trữ tất cả các cuộc trò chuyện đã lưu trữ không?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "Các Mô hình Arena", "Artifacts": "Kết quả tạo ra", "Asc": "", "Ask": "Hỏi", "Ask a question": "Đặt câu hỏi", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "Trợ lý", "Async Embedding Processing": "", "At time of event": "", @@ -220,14 +247,20 @@ "Audio": "Âm thanh", "August": "Tháng 8", "Auth": "Xác thực", + "Auth Mode": "", + "Auth required": "", "Authenticate": "Xác thực", "Authentication": "Xác thực", "Auto": "", "Auto (Random)": "", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "Tự động Sao chép Phản hồi vào clipboard", - "Auto-playback response": "Tự động phát lại phản hồi (Auto-playback)", + "Auto-Create Groups": "", + "Auto-Playback Response": "Tự động phát lại phản hồi (Auto-playback)", "Autocomplete Generation": "Tạo Tự động Hoàn thành", "Autocomplete Generation Input Max Length": "Độ dài tối đa đầu vào Tạo Tự động Hoàn thành", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "Chuỗi xác thực API AUTOMATIC1111", "AUTOMATIC1111 Base URL": "Đường dẫn kết nối tới AUTOMATIC1111 (Base URL)", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "Công cụ có sẵn", "available users": "người dùng khả dụng", + "Available variables": "", "available!": "có sẵn!", "Away": "Vắng mặt", "Awful": "Tệ", @@ -255,16 +289,17 @@ "Bad Response": "Trả lời KHÔNG tốt", "Banners": "Biểu ngữ", "Base Model (From)": "Mô hình cơ sở (từ)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "", "Bearer": "", "before": "trước", "Being lazy": "Lười biếng", - "Beta": "Beta", "Bing": "", "Bing Search V7 Endpoint": "Endpoint Bing Search V7", "Bing Search V7 Subscription Key": "Khóa đăng ký Bing Search V7", "Bio": "", "Birth Date": "", + "Blocked Groups": "", "BM25 Weight": "", "Bocha Search API Key": "Khóa API Bocha Search", "Bold": "", @@ -321,7 +356,7 @@ "Chat Completions": "", "Chat Conversation": "", "Chat deleted.": "", - "Chat direction": "Hướng chat", + "Chat Direction": "Hướng chat", "Chat exported successfully": "", "Chat History": "", "Chat ID": "", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "", "Collapse": "Thu gọn", "Collection": "Tổng hợp mọi tài liệu", + "Collection Field": "", "Collections": "", "Color": "Màu sắc", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "Quy trình làm việc ComfyUI", "ComfyUI Workflow Nodes": "Các nút Quy trình làm việc ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "", "Command": "Lệnh", "Comment": "", "Commit Message": "", "Community Reviews": "", + "Compacting context": "", "Comparing with knowledge base...": "", "Completions": "Hoàn thành", "Compress Images in Channels": "", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", "Connect to your own OpenAI compatible API endpoints.": "Kết nối với các điểm cuối API tương thích OpenAI của riêng bạn.", "Connect to your own OpenAPI compatible external tool servers.": "Kết nối với các máy chủ công cụ bên ngoài tương thích OpenAPI của riêng bạn.", + "Connected": "", "Connected ({{type}})": "", "Connection failed": "Kết nối thất bại", "Connection lost. Reconnecting...": "", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "Liên hệ với Quản trị viên để được cấp quyền truy cập", "Content": "Nội dung", "Content Extraction Engine": "Engine Trích xuất Nội dung", + "Content Field": "", "Content lengths (character counts only)": "", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "", + "Continue": "", "Continue Response": "Tiếp tục trả lời", "Continue with {{provider}}": "Tiếp tục với {{provider}}", "Continue with Email": "Tiếp tục với Email", @@ -489,6 +536,7 @@ "Create new secret key": "Tạo key bí mật mới", "Create note": "", "Create Note": "", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "", "Create your first note by clicking on the plus button below.": "", "Created at": "Được tạo vào lúc", @@ -506,6 +554,7 @@ "Custom Gender": "", "Custom Parameter Name": "", "Custom Parameter Value": "", + "Custom range": "", "Daily": "", "Daily Messages": "", "Danger Zone": "Vùng Nguy hiểm", @@ -528,7 +577,6 @@ "Default Features": "", "Default Filters": "", "Default Group": "", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Chế độ mặc định hoạt động với nhiều loại mô hình hơn bằng cách gọi các công cụ một lần trước khi thực thi. Chế độ gốc tận dụng khả năng gọi công cụ tích hợp sẵn của mô hình, nhưng yêu cầu mô hình phải hỗ trợ tính năng này vốn có.", "Default Model": "Model mặc định", "Default model updated": "Mô hình mặc định đã được cập nhật", "Default permissions": "Quyền mặc định", @@ -538,6 +586,7 @@ "Default to ALL": "Mặc định là TẤT CẢ", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "Mặc định truy xuất phân đoạn để trích xuất nội dung tập trung và phù hợp, điều này được khuyến nghị cho hầu hết các trường hợp.", "Default User Role": "Vai trò mặc định", + "Default webhook": "", "Defaults": "", "Delete": "Xóa", "Delete {{name}}": "", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "Đã tắt", "Disconnect OAuth": "", "Discover a function": "Khám phá function", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "Tìm kiếm, tải về và khám phá thêm các model presets", "Discussion channel where access is based on groups and permissions": "", "Display": "Hiển thị", - "Display chat title in tab": "", + "Display Chat Title in Tab": "", "Display Emoji in Call": "Hiển thị Emoji trong cuộc gọi", "Display Multi-model Responses in Tabs": "", - "Display the username instead of You in the Chat": "Hiển thị tên người sử dụng thay vì 'Bạn' trong nội dung chat", + "Display the Username Instead of You in the Chat": "Hiển thị tên người sử dụng thay vì 'Bạn' trong nội dung chat", "Displays citations in the response": "Hiển thị trích dẫn trong phản hồi", "Displays status updates (e.g., web search progress) in the response": "", "Dive into knowledge": "Đi sâu vào kiến thức", @@ -626,6 +677,7 @@ "Docling Parameters": "", "Docling Server URL required.": "Yêu cầu URL Máy chủ Docling.", "Document": "Tài liệu", + "Document ID Field": "", "Document Intelligence": "Trí tuệ Tài liệu", "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", @@ -681,12 +733,14 @@ "Edit Default Permissions": "Chỉnh sửa Quyền Mặc định", "Edit Folder": "", "Edit Image": "", + "Edit Knowledge Connection": "", "Edit Last Message": "", "Edit Memory": "Sửa Memory", "Edit Prompt": "", "Edit Terminal Connection": "", "Edit User": "Thay đổi thông tin người sử dụng", "Edit User Group": "Chỉnh sửa Nhóm Người dùng", + "Edit webhook": "", "Edit workflow.json content": "", "edited": "", "Edited": "", @@ -695,6 +749,7 @@ "Eject model": "", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "Bắt đầu những cuộc phiêu lưu", "Embedding": "Embedding", "Embedding Batch Size": "Kích thước Lô Embedding", @@ -703,6 +758,7 @@ "Embedding Model Engine": "Trình xử lý embedding", "Emoji": "", "Emojis": "", + "Empty": "", "Empty message": "", "Enable All": "", "Enable API Keys": "", @@ -710,22 +766,27 @@ "Enable Code Execution": "Bật Thực thi Mã", "Enable Code Interpreter": "Bật Trình thông dịch Mã", "Enable Community Sharing": "Cho phép Chia sẻ Cộng đồng", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "Bật Khóa Bộ nhớ (mlock) để ngăn dữ liệu mô hình bị hoán đổi ra khỏi RAM. Tùy chọn này khóa tập trang làm việc của mô hình vào RAM, đảm bảo rằng chúng sẽ không bị hoán đổi ra đĩa. Điều này có thể giúp duy trì hiệu suất bằng cách tránh lỗi trang và đảm bảo truy cập dữ liệu nhanh chóng.", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "Bật Ánh xạ Bộ nhớ (mmap) để tải dữ liệu mô hình. Tùy chọn này cho phép hệ thống sử dụng bộ nhớ đĩa như một phần mở rộng của RAM bằng cách coi các tệp đĩa như thể chúng ở trong RAM. Điều này có thể cải thiện hiệu suất mô hình bằng cách cho phép truy cập dữ liệu nhanh hơn. Tuy nhiên, nó có thể không hoạt động chính xác với tất cả các hệ thống và có thể tiêu tốn một lượng đáng kể dung lượng đĩa.", "Enable Message Queue": "", "Enable Message Rating": "Cho phép phản hồi, đánh giá", "Enable Mirostat sampling for controlling perplexity.": "Bật lấy mẫu Mirostat để kiểm soát perplexity.", "Enable New Sign Ups": "Cho phép đăng ký mới", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "", "Enabled": "Đã bật", "End Tag": "", + "Endpoint": "", "Endpoint URL": "", "Enforce Temporary Chat": "Bắt buộc Chat nháp", "Enhance": "", "Enrich Hybrid Search Text": "", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Đảm bảo tệp CSV của bạn bao gồm 4 cột theo thứ tự sau: Name, Email, Password, Role.", "Enter {{role}} message here": "Nhập yêu cầu của {{role}} ở đây", - "Enter a detail about yourself for your LLMs to recall": "Nhập chi tiết về bản thân của bạn để LLMs có thể nhớ", "Enter a title for the pending user info overlay. Leave empty for default.": "", "Enter a watermark for the response. Leave empty for none.": "", "Enter additional headers in JSON format": "", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "", "Enter Chunk Overlap": "Nhập Chunk chồng lấn (overlap)", "Enter Chunk Size": "Nhập Kích thước Chunk", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Nhập các cặp \"token:giá_trị_bias\" được phân tách bằng dấu phẩy (ví dụ: 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "", "Enter coordinates (e.g. 51.505, -0.09)": "", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "Nhập URL Jupyter", "Enter Kagi Search API Key": "Nhập Khóa API Kagi Search", "Enter Key Behavior": "Nhập Hành vi phím", + "Enter language": "", "Enter language codes": "Nhập mã ngôn ngữ", "Enter Linkup API Key": "", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", "Enter Mistral API Key": "Nhập Khóa API Mistral", @@ -800,6 +866,7 @@ "Enter prompt here.": "", "Enter proxy URL (e.g. https://user:password@host:port)": "Nhập URL proxy (vd: https://user:password@host:port)", "Enter reasoning effort": "Nhập nỗ lực suy luận", + "Enter Redirect URI": "", "Enter Score": "Nhập Score", "Enter SearchApi API Key": "Nhập Khóa API SearchApi", "Enter SearchApi Engine": "Nhập Engine SearchApi", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "Nhập Khóa API SerpApi", "Enter SerpApi Engine": "Nhập Engine SerpApi", "Enter Serper API Key": "Nhập Serper API Key", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "Nhập Serply API Key", "Enter Serpstack API Key": "Nhập Serpstack API Key", "Enter server host": "Nhập host máy chủ", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "Nhập URL cho Tika Server", "Enter timeout in seconds": "Nhập thời gian chờ tính bằng giây", "Enter to Send": "Enter để Gửi", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "Nhập Top K", "Enter Top K Reranker": "Nhập Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "Nhập URL (vd: http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", "Evaluations": "Đánh giá", + "Event": "", "Event created": "", "Event deleted": "", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "", "Event updated": "", + "Events": "", "Exa API Key": "Khóa API Exa", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Ví dụ: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Ví dụ: TẤT CẢ", "Example: mail": "Ví dụ: mail", @@ -901,12 +975,18 @@ "Export Config": "", "Export Models": "", "Export Prompts": "", + "Export Skills": "", "Export to CSV": "Xuất ra CSV", "Export Tools": "", "Export Users": "", "External": "Bên ngoài", + "External connection not found.": "", "External Document Loader URL required.": "", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "", "External Web Loader URL": "", "External Web Search API Key": "", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "Lỗi khởi tạo API Key", "Failed to delete calendar": "", "Failed to delete note": "", + "Failed to delete webhook": "", "Failed to disconnect": "", "Failed to download image": "", "Failed to extract content from the file: {{error}}": "", @@ -931,6 +1012,7 @@ "Failed to fetch models": "Không thể lấy danh sách mô hình", "Failed to generate title": "", "Failed to import models": "", + "Failed to load chat": "", "Failed to load chat preview": "", "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", @@ -940,6 +1022,7 @@ "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Không thể đọc nội dung clipboard", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "", "Failed to render diagram": "", "Failed to render visualization": "", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "Không thể lưu cấu hình mô hình", "Failed to save policy: {{error}}": "", "Failed to save terminal servers": "", + "Failed to save webhook": "", "Failed to unshare chat.": "", "Failed to update settings": "Lỗi khi cập nhật các cài đặt", "Failed to update status": "", + "Failed to update webhook": "", "Failed to upload file.": "Không thể tải lên tệp.", "Features": "Tính năng", "Features Permissions": "Quyền Tính năng", @@ -983,6 +1068,8 @@ "File uploaded successfully": "Tải tệp lên thành công", "Filename": "", "Files": "Tệp", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "", "Filter is now globally disabled": "Bộ lọc hiện đã bị vô hiệu hóa trên toàn hệ thống", "Filter is now globally enabled": "Bộ lọc hiện được kích hoạt trên toàn hệ thống", @@ -1005,6 +1092,7 @@ "Folder options": "", "Folder updated successfully": "", "Folders": "", + "Folders Sharing": "", "Follow up": "", "Follow Up Generation": "", "Follow Up Generation Prompt": "", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "Function đã được kích hoạt trên toàn hệ thống", "Function Name": "Tên Function", "Function Name Filter List": "", + "Function starter": "", "Function updated successfully": "Function được cập nhật thành công", "Functions": "Functions", "Functions allow arbitrary code execution.": "Các Function cho phép thực thi mã tùy ý.", @@ -1067,7 +1156,10 @@ "Gravatar": "", "Grid": "", "Grokipedia": "", + "group": "", + "Group": "", "Group Channel": "", + "Group Claim": "", "Group created successfully": "Đã tạo nhóm thành công", "Group deleted successfully": "Đã xóa nhóm thành công", "Group Description": "Mô tả Nhóm", @@ -1079,6 +1171,7 @@ "H2": "", "H3": "", "Haptic Feedback": "Phản hồi xúc giác", + "Header variables": "", "Headers": "", "Headers must be a valid JSON object": "", "Height": "", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "", "ID copied to clipboard": "", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "", "iframe Sandbox Allow Forms": "", "iframe Sandbox Allow Same Origin": "", @@ -1134,6 +1229,7 @@ "Import From Link": "", "Import Models": "", "Import Prompts": "", + "Import Skills": "", "Import successful": "", "Import Tools": "", "Important Update": "Bản cập nhật quan trọng", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "", "Key": "Khóa", "Key is required": "", - "Keyboard shortcuts": "Phím tắt", "Keyboard Shortcuts": "", "Knowledge": "Kiến thức", "Knowledge Access": "Truy cập Kiến thức", @@ -1204,6 +1299,8 @@ "Knowledge Name": "", "Knowledge Public Sharing": "Chia sẻ Công khai Kiến thức", "Knowledge Sharing": "", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "Đã cập nhật kiến thức thành công", "Kokoro.js (Browser)": "Kokoro.js (Trình duyệt)", "Kokoro.js Dtype": "Kiểu dữ liệu Kokoro.js", @@ -1220,7 +1317,6 @@ "Last ran": "", "Last reply": "Trả lời cuối", "LDAP": "LDAP", - "LDAP server updated": "Đã cập nhật máy chủ LDAP", "Leaderboard": "Bảng xếp hạng", "Learn more": "", "Learn More": "", @@ -1242,6 +1338,7 @@ "Legacy": "", "lexical": "", "License": "Giấy phép", + "Lifecycle JSON": "", "Lift List": "", "Light": "Sáng", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", @@ -1265,6 +1362,7 @@ "Location access not allowed": "Không cho phép truy cập vị trí", "Lost": "Thua", "Low": "", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "LTR", "Made by Open WebUI Community": "Được tạo bởi Cộng đồng OpenWebUI", "Make password visible in the user interface": "", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "Quản lý Pipelines", "Manage Tool Servers": "Quản lý Máy chủ Công cụ", "Manage your account information.": "", + "Mapped Source": "", "March": "Tháng 3", "Markdown": "", "Markdown Header Text Splitter": "", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "Memory đã bị xóa", "Memory deleted successfully": "Memory đã bị loại bỏ", "Memory updated successfully": "Memory đã cập nhật thành công", + "Merge Accounts by Email": "", "Merge Responses": "Hợp nhất các phản hồi", "Merged Response": "Phản hồi Hợp nhất", "Message": "", @@ -1318,9 +1418,12 @@ "messages": "", "Messages": "", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Tin nhắn bạn gửi sau khi tạo liên kết sẽ không được chia sẻ. Người dùng có URL sẽ có thể xem cuộc trò chuyện được chia sẻ.", + "Metadata Field": "", "Microsoft OneDrive": "", "Microsoft OneDrive (personal)": "", "Microsoft OneDrive (work/school)": "", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "", "MinerU": "", "MinerU API Key required for Cloud API mode.": "", @@ -1373,6 +1476,7 @@ "Models Sharing": "", "Mojeek": "", "Mojeek Search API Key": "Khóa API Mojeek Search", + "Monday – Friday": "", "Month": "", "Monthly": "", "More": "Thêm", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "Đặt tên cho cơ sở kiến thức của bạn", "Name, prompt, and model are required": "", "Native": "Gốc", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "", "New": "", "New Automation": "", @@ -1419,6 +1524,7 @@ "Next run": "", "No access grants. Private to you.": "", "No activity data": "", + "No additional headers are sent unless configured.": "", "No authentication": "", "No automations found": "", "No chats found": "", @@ -1431,8 +1537,10 @@ "No data": "", "No data found": "", "No distance available": "Không có khoảng cách khả dụng", + "No event webhooks configured.": "", "No execution logs available yet": "", "No expiration can pose security risks.": "", + "No external knowledge sources configured.": "", "No feedback found": "", "No file selected": "Chưa có tệp nào được chọn", "No files found": "", @@ -1460,6 +1568,7 @@ "No output items": "", "No pinned messages": "", "No prompts found": "", + "No Repeat": "", "No results": "Không tìm thấy kết quả", "No results found": "Không tìm thấy kết quả", "No search query generated": "Không có truy vấn tìm kiếm nào được tạo ra", @@ -1479,6 +1588,7 @@ "No webhooks yet": "", "Node Ids": "", "None": "Không ai", + "Not configured": "", "Not factually correct": "Không chính xác so với thực tế", "Not helpful": "Không hữu ích", "Not Registered": "", @@ -1494,20 +1604,25 @@ "Notifications": "Thông báo trên máy tính (Notification)", "November": "Tháng 11", "OAuth": "", + "OAuth / OIDC": "", "OAuth 2.1": "", "OAuth 2.1 (Static)": "", "OAuth ID": "ID OAuth", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "", "OAuth session disconnected": "", "October": "Tháng 10", "Off": "Tắt", "Okay, Let's Go!": "Được rồi, Bắt đầu thôi!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED Dark", "Ollama": "Ollama", "Ollama API": "API Ollama", "Ollama API settings updated": "Đã cập nhật cài đặt API Ollama", "Ollama Cloud API Key": "", "Ollama Version": "Phiên bản Ollama", + "Omit": "", "On": "Bật", "Once": "", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "Mật khẩu", "Passwords do not match.": "", "Paste Large Text as File": "Dán Văn bản Lớn dưới dạng Tệp", + "Path": "", "Path copied": "", "Paused": "", "PDF document (.pdf)": "Tập tin PDF (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "đang chờ phê duyệt", "Pending": "", + "Pending Accounts": "", "Pending User Overlay Content": "", "Pending User Overlay Title": "", "Permission denied when accessing media devices": "Quyền truy cập các thiết bị đa phương tiện bị từ chối", "Permission denied when accessing microphone": "Quyền truy cập micrô bị từ chối", "Permission denied when accessing microphone: {{error}}": "Quyền truy cập micrô bị từ chối: {{error}}", "Permissions": "Quyền", + "Permissions reset to defaults": "", "Perplexity API Key": "Khóa API Perplexity", "Perplexity Model": "", "Perplexity Search API URL": "", "Perplexity Search Context Usage": "", "Persistent": "", "Personalization": "Cá nhân hóa", + "Picture Claim": "", "Pin": "Ghim", "Pin to Sidebar": "", "Pinned": "Đã ghim", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "Vui lòng điền vào tất cả các trường.", "Please register the OAuth client": "", "Please save the connection to persist the OAuth client information and do not change the ID": "", - "Please select a model first.": "Vui lòng chọn một mô hình trước.", "Please select a model.": "Vui lòng chọn một mô hình.", "Please select a reason": "Vui lòng chọn một lý do", "Please select a valid JSON file": "", "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Policy ID": "", + "Policy ID is required": "", "Port": "Cổng", "Ports": "", "Positive attitude": "Thái độ tích cực", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "Chia sẻ Công khai Prompt", "Prompts Sharing": "", "Provider": "", + "Provider Name": "", + "Provider URL": "", "Public": "Công khai", "Pull \"{{searchValue}}\" from Ollama.com": "Tải \"{{searchValue}}\" từ Ollama.com", "Pull a model from Ollama.com": "Tải mô hình từ Ollama.com", @@ -1683,21 +1804,28 @@ "Read": "Đọc", "Read Aloud": "Đọc ra loa", "Read more →": "", + "Read only": "", "Read Only": "", "Read-Only Access": "", "Reason": "", "Reasoning Effort": "Nỗ lực Suy luận", "Reasoning Tags": "", "Reasoning text...": "", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "", "Reconnected": "", "Record": "", "Record voice": "Ghi âm", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "Đang chuyển hướng bạn đến Cộng đồng OpenWebUI", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "Giảm xác suất tạo ra nội dung vô nghĩa. Giá trị cao hơn (ví dụ: 100) sẽ cho câu trả lời đa dạng hơn, trong khi giá trị thấp hơn (ví dụ: 10) sẽ thận trọng hơn.", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Hãy coi bản thân mình như \"Người dùng\" (ví dụ: \"Người dùng đang học Tiếng Tây Ban Nha\")", "Reference Chats": "", "Refresh": "", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "Từ chối trả lời mà nhẽ không nên làm vậy", "Regenerate": "Tạo sinh lại câu trả lời", "Regenerate Menu": "", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "", "Render Markdown in User Messages": "", "Reorder Models": "Sắp xếp lại Mô hình", + "Repeat": "", "Repeats": "", "Reply": "", "Reply in Thread": "Trả lời trong Luồng", "Reply to thread...": "", "Replying to {{NAME}}": "", + "Require users to confirm before using Web Search.": "", "required": "", "Reranking Batch Size": "", "Reranking Engine": "", "Reranking Model": "Reranking Model", + "Research Knowledge": "", "Reset": "Xóa toàn bộ", "Reset All Models": "Đặt lại Tất cả Mô hình", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "Đặt lại hình ảnh", "Reset knowledge base?": "", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "Xóa toàn bộ thư mục Upload", "Reset Vector Storage/Knowledge": "Đặt lại Lưu trữ Vector/Kiến thức", "Reset view": "Đặt lại chế độ xem", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "", "Rich Text Input for Chat": "Nhập Văn bản Đa dạng cho Chat", "Role": "Vai trò", + "Roles Claim": "", "RTL": "RTL", "Run": "Thực hiện", "Run All": "", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Không còn hỗ trợ lưu trữ lịch sử chat trực tiếp vào bộ nhớ trình duyệt của bạn. Vui lòng dành thời gian để tải xuống và xóa lịch sử chat của bạn bằng cách nhấp vào nút bên dưới. Đừng lo lắng, bạn có thể dễ dàng nhập lại lịch sử chat của mình vào backend thông qua", "Schedule": "", "Scheduled time must be in the future": "", + "Scopes": "", "Scroll On Branch Change": "", "Scroll to Top": "", "Search": "Tìm kiếm", "Search a model": "Tìm model", + "Search actions": "", "Search all emojis": "", "Search and manage user memories": "", "Search and view user chat history": "", @@ -1792,6 +1930,7 @@ "Search Chats": "Tìm kiếm các cuộc Chat", "Search Collection": "Tìm kiếm Bộ sưu tập", "Search Files": "", + "Search filters": "", "Search Filters": "Bộ lọc Tìm kiếm", "search for archived chats": "", "search for folders": "", @@ -1806,13 +1945,16 @@ "Search Models": "Tìm model", "Search Notes": "", "Search options": "Tùy chọn tìm kiếm", + "Search or add pattern": "", "Search Prompts": "Tìm prompt", "Search Result Count": "Số kết quả tìm kiếm", + "Search skills": "", "Search Skills": "", - "Search skills...": "", "Search the internet": "Tìm kiếm trên internet", "Search the web and fetch URLs": "", + "Search tools": "", "Search Tools": "Tìm kiếm Tools", + "Search users or groups": "", "Search, view, and manage user notes": "", "SearchApi API Key": "Khóa API SearchApi", "SearchApi Engine": "Engine SearchApi", @@ -1828,7 +1970,6 @@ "Seed": "Seed", "Select": "", "Select {{modelName}} model": "", - "Select a base model": "Chọn một base model", "Select a base model (e.g. llama3, gpt-4o)": "", "Select a conversation to preview": "", "Select a engine": "Chọn dịch vụ", @@ -1866,18 +2007,25 @@ "semantic": "", "Send": "Gửi", "Send a Message": "Gửi yêu cầu", + "Send events for": "", "Send message": "Gửi yêu cầu", "Send now": "", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Gửi `stream_options: { include_usage: true }` trong yêu cầu.\nCác nhà cung cấp được hỗ trợ sẽ trả về thông tin sử dụng token trong phản hồi khi được đặt.", "September": "Tháng 9", "SerpApi API Key": "Khóa API SerpApi", "SerpApi Engine": "Engine SerpApi", "Serper API Key": "Khóa API Serper", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Khóa API Serply", "Serpstack API Key": "Khóa API Serpstack", "Server connection failed": "", "Server connection verified": "Kết nối máy chủ đã được xác minh", + "Service Account": "", "Session": "", + "Session expired. Please sign in again.": "", "Set as default": "Đặt làm mặc định", "Set as Production": "", "Set embedding model": "Đặt mô hình embedding", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Chia sẻ đến Cộng đồng OpenWebUI", "Share your background and interests": "", + "Shared": "", "Shared Chats": "", "Shared with you": "", "Sharing Permissions": "Quyền Chia sẻ", "Show": "Hiển thị", - "Show \"What's New\" modal on login": "Hiển thị cửa sổ \"Có gì mới\" khi đăng nhập", + "Show \"What's New\" Modal on Login": "Hiển thị cửa sổ \"Có gì mới\" khi đăng nhập", "Show Admin Details in Account Pending Overlay": "Hiển thị thông tin của Quản trị viên trên màn hình hiển thị Tài khoản đang chờ xử lý", "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "", "Show image preview": "", "Show Model": "Hiển thị Mô hình", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "", "Sougou Search API SK": "", "Source": "Nguồn", + "Specific users or groups": "", "Speech Playback Speed": "Tốc độ Phát lại Lời nói", "Speech recognition error: {{error}}": "Lỗi nhận dạng giọng nói: {{error}}", "Speech-to-Text": "", @@ -1992,6 +2143,7 @@ "STT Settings": "Cài đặt Nhận dạng Giọng nói", "Stylized PDF Export": "", "Su_day_of_week": "", + "Sub Claim": "", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -2016,8 +2168,10 @@ "Syncing...": "", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "", "System": "Hệ thống", + "System events only": "", "System Instructions": "Hướng dẫn Hệ thống", "System Prompt": "Prompt Hệ thống (System Prompt)", + "Table": "", "Tag": "", "Tags": "Thẻ", "Tags Generation": "Tạo Thẻ", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "", "Terminal": "", "Terminal servers saved": "", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "Bộ chia Văn bản", "Text-to-Speech": "", "Text-to-Speech Engine": "Công cụ Chuyển Văn bản thành Giọng nói", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "", "The LDAP attribute that maps to the mail that users use to sign in.": "Thuộc tính LDAP ánh xạ tới mail mà người dùng sử dụng để đăng nhập.", "The LDAP attribute that maps to the username that users use to sign in.": "Thuộc tính LDAP ánh xạ tới tên người dùng mà người dùng sử dụng để đăng nhập.", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "Bảng xếp hạng hiện đang trong giai đoạn beta và chúng tôi có thể điều chỉnh các tính toán xếp hạng khi chúng tôi tinh chỉnh thuật toán.", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "Kích thước tệp tối đa tính bằng MB. Nếu kích thước tệp vượt quá giới hạn này, tệp sẽ không được tải lên.", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "Số lượng tệp tối đa có thể được sử dụng cùng một lúc trong cuộc trò chuyện. Nếu số lượng tệp vượt quá giới hạn này, các tệp sẽ không được tải lên.", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "", @@ -2075,6 +2234,7 @@ "This folder is empty": "", "This is a default user permission and will remain enabled.": "", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Đây là tính năng thử nghiệm, có thể không hoạt động như mong đợi và có thể thay đổi bất kỳ lúc nào.", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Tùy chọn này kiểm soát số lượng token được bảo tồn khi làm mới ngữ cảnh. Ví dụ: nếu đặt thành 2, 2 token cuối cùng của ngữ cảnh hội thoại sẽ được giữ lại. Bảo tồn ngữ cảnh có thể giúp duy trì tính liên tục của cuộc trò chuyện, nhưng nó có thể làm giảm khả năng phản hồi các chủ đề mới.", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "Để tìm hiểu thêm về các điểm cuối có sẵn, hãy truy cập tài liệu của chúng tôi.", "To select skills here, add them to the \"Skills\" workspace first.": "", "To select toolkits here, add them to the \"Tools\" workspace first.": "Để chọn các tookits, bạn phải thêm chúng vào workspace \"Tools\" trước.", - "Toast notifications for new updates": "Thông báo nhanh cho các cập nhật mới", + "Toast Notifications for New Updates": "Thông báo nhanh cho các cập nhật mới", "Today": "Hôm nay", "Today at": "", "Today at {{LOCALIZED_TIME}}": "", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "", "Tokens": "", "Too verbose": "Quá dài dòng", @@ -2177,14 +2339,19 @@ "Unpin": "Bỏ ghim", "Unpin from Sidebar": "", "Unravel secrets": "Làm sáng tỏ những bí mật", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "", "Unsupported file type.": "", "Untagged": "Chưa gắn thẻ", "Untitled": "", "Update": "Cập nhật", "Update and Copy Link": "Cập nhật và sao chép link", + "Update Email": "", "Update for the latest features and improvements.": "Cập nhật để có các tính năng và cải tiến mới nhất.", + "Update Name": "", "Update password": "Cập nhật mật khẩu", + "Update Picture": "", "Update your status": "", "Updated": "Đã cập nhật", "Updated at": "Cập nhật lúc", @@ -2211,13 +2378,18 @@ "Use": "", "Use '#' in the prompt input to load and include your knowledge.": "Sử dụng '#' trong ô nhập prompt để tải và bao gồm kiến thức của bạn.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "", "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Use Web Search?": "", "user": "Người sử dụng", "User": "Người dùng", + "User Access": "", "User Activity": "", "User Groups": "", "User location successfully retrieved.": "Đã truy xuất thành công vị trí của người dùng.", @@ -2227,6 +2399,7 @@ "User Status": "", "User Webhooks": "Webhook Người dùng", "Username": "Tên đăng nhập", + "Username Claim": "", "users": "", "Users": "Người sử dụng", "Uses DefaultAzureCredential to authenticate": "", @@ -2240,6 +2413,7 @@ "Valves updated": "Đã cập nhật Valves", "Valves updated successfully": "Đã cập nhật Valves thành công", "variable": "biến", + "Vector Field": "", "Verify Connection": "Xác minh Kết nối", "Verify SSL Certificate": "", "Version": "Phiên bản", @@ -2269,11 +2443,14 @@ "Web API": "Web API", "Web Loader Engine": "", "Web Search": "Tìm kiếm Web", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "Chức năng Tìm kiếm Web", "Web Search in Chat": "Tìm kiếm Web trong Chat", "Web Search Query Generation": "Tạo Truy vấn Tìm kiếm Web", + "Webhook deleted": "", "Webhook Name": "", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "", "Webpage URLs": "", "WebUI Settings": "Cài đặt WebUI", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "", "Yandex Web Search config": "", "Yandex Web Search URL": "", + "Yearly": "", "Yesterday": "Hôm qua", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Bạn", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Toàn bộ đóng góp của bạn sẽ được chuyển trực tiếp đến nhà phát triển plugin; Open WebUI không lấy bất kỳ tỷ lệ phần trăm nào. Tuy nhiên, nền tảng được chọn tài trợ có thể có phí riêng.", "Your message text or inputs": "", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "", "YouTube": "Youtube", "Youtube Language": "Ngôn ngữ Youtube", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index a9eff36a47..555388c1f6 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "已提取 {{COUNT}} 行文本", "{{COUNT}} files": "{{COUNT}} 个文件", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "已选择 {{count}} 个文件。仅会上传新增和已修改的文件,已删除的文件将被移除,并将镜像文件夹结构。是否继续?", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "已隐藏 {{COUNT}} 行代码", "{{COUNT}} members": "{{COUNT}} 位成员", "{{count}} of {{total}} accessible_other": "可访问 {{count}}/{{total}}", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "{{COUNT}} 行", "{{count}} selected_other": "已选择 {{count}} 项", "{{COUNT}} Sources": "{{COUNT}} 个引用来源", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} 个字", "{{COUNT}}d_time_ago": "{{COUNT}}天前", "{{COUNT}}h_time_ago": "{{COUNT}}小时前", "{{COUNT}}m_time_ago": "{{COUNT}}分钟前", "{{COUNT}}w_time_ago": "{{COUNT}}周前", "{{COUNT}}y_time_ago": "{{COUNT}}年前", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "已取消模型 {{model}} 的下载", "{{modelName}} profile image": "模型 “{{modelName}}” 的头像", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "{{user}} 的对话记录", "{{webUIName}} Backend Required": "{{webUIName}} 需要后端服务", "*Prompt node ID(s) are required for image generation": "*图片生成需要提示词节点 ID", + "1 group": "", "1 hour before": "提前 1 小时", "1 Source": "1 个引用来源", + "1 user": "", "10 minutes before": "提前 10 分钟", "15 minutes before": "提前 15 分钟", "1m_time_ago": "刚刚", @@ -54,6 +61,7 @@ "Access Control": "访问控制", "Access Grants": "访问授权", "Access List": "访问列表", + "Access prohibited": "", "Access updated": "访问权限已更新", "Accessible to all users": "对所有用户开放", "Account": "账号", @@ -69,6 +77,7 @@ "Activity": "活动", "Add": "添加", "Add a model ID": "添加模型 ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "添加有关该模型能力的简短描述", "Add a tag": "添加标签", "Add a tag...": "添加标签...", @@ -81,8 +90,10 @@ "Add Custom Prompt": "增加自定义提示词", "Add description": "添加描述", "Add Details": "丰富细节", + "Add durable context for future chats": "", "Add Files": "添加文件", "Add Image": "添加图片", + "Add Knowledge Connection": "", "Add location": "添加地点", "Add Member": "添加成员", "Add Members": "添加成员", @@ -97,6 +108,7 @@ "Add to favorites": "添加到收藏", "Add User": "添加用户", "Add User Group": "添加用户组", + "Add webhook": "", "Add webpage": "添加网页", "Add your Open Terminal URL and API key in Settings → Integrations.": "请到“设置 → 集成”中配置 Open Terminal 的地址和密钥。", "Additional Config": "额外配置项", @@ -109,7 +121,9 @@ "Admin": "管理员", "Admin Contact Email": "管理员联系邮箱", "Admin Panel": "管理员面板", + "Admin Roles": "", "Admin Settings": "管理员设置", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理员拥有所有工具的完全访问权限;用户则需在工作空间中为每个模型单独分配工具。", "Advanced": "高级", "Advanced Parameters": "高级参数", @@ -120,16 +134,21 @@ "All": "全部", "All chats have been unarchived.": "已成功取消全部对话的归档状态。", "All day": "全天", + "All events": "", "All models are now hidden": "已隐藏全部模型", "All models are now visible": "已显示全部模型", "All models deleted successfully": "已成功删除全部模型", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "所有时间", "All Users": "所有用户", + "All users and system events": "", "Allow Call": "允许语音通话", "Allow Chat Controls": "允许使用对话高级设置", "Allow Chat Delete": "允许删除对话记录", "Allow Chat Edit": "允许编辑对话记录", "Allow Chat Export": "允许导出对话", + "Allow Chat Import": "", "Allow Chat Params": "允许设置模型高级参数", "Allow Chat Share": "允许分享对话", "Allow Chat System Prompt": "允许设置系统提示词", @@ -149,9 +168,11 @@ "Allow User Location": "获取您的位置", "Allow Voice Interruption in Call": "允许语音通话时打断对话", "Allow Web Upload": "允许从网络上传内容", + "Allowed Domains": "", "Allowed Endpoints": "允许的接口", "Allowed File Extensions": "允许的文件扩展名", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "文件上传允许的扩展名。多个扩展名用逗号分隔。留空以允许所有文件类型。", + "Allowed Roles": "", "Already have an account?": "已拥有账号?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p 的替代方法,旨在平衡生成质量与多样性。参数 p 表示一个 token 被考虑的最低概率,该概率相对于最可能 token 的概率。例如,当 p=0.05 且最可能 token 的概率为 0.9 时,概率值低于 0.045 的 token 将被过滤掉。", "Always": "始终", @@ -170,6 +191,7 @@ "API Base URL": "接口地址", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker 服务的接口地址。默认为:https://www.datalab.to/api/v1/marker", "API Key": "API 密钥", + "API Key / Token": "", "API Key created.": "API 密钥已创建。", "API Key Endpoint Restrictions": "API 密钥端点限制", "API keys": "API 密钥", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "确定要删除这条记忆吗?此操作无法撤销。", "Are you sure you want to delete this message?": "您确认要删除此消息吗?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "您确认要删除此版本吗?其子版本将重新链接到该版本的上一级。", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "确定要删除吗?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "您确认要取消所有已归档的对话吗?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "模型盲测", "Artifacts": "产物", "Asc": "升序", "Ask": "提问", "Ask a question": "提问", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "助手", "Async Embedding Processing": "异步嵌入处理", "At time of event": "事件开始时", @@ -220,14 +247,20 @@ "Audio": "语音", "August": "八月", "Auth": "认证方式", + "Auth Mode": "", + "Auth required": "", "Authenticate": "认证", "Authentication": "身份验证", "Auto": "自动", "Auto (Random)": "随机", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "自动复制回答内容到剪贴板", - "Auto-playback response": "自动朗读回答内容", + "Auto-Create Groups": "", + "Auto-Playback Response": "自动朗读回答内容", "Autocomplete Generation": "输入框内容自动补全", "Autocomplete Generation Input Max Length": "输入框内容自动补全的最大字符数限制", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 接口鉴权字符串", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 接口地址", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "可用工具", "available users": "可用用户", + "Available variables": "", "available!": "版本可用!", "Away": "离开", "Awful": "糟糕", @@ -255,16 +289,17 @@ "Bad Response": "点踩此回答", "Banners": "公告横幅", "Base Model (From)": "基础模型(来自)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "仅在启动或保存设置时获取基础模型列表以提升访问速度,但显示的模型列表可能不是最新的。", "Bearer": "密钥(Bearer)", "before": "之前", "Being lazy": "回答不完整或敷衍了事", - "Beta": "Beta", "Bing": "必应", "Bing Search V7 Endpoint": "Bing 搜索 V7 端点", "Bing Search V7 Subscription Key": "Bing 搜索 V7 订阅密钥", "Bio": "个人简介", "Birth Date": "出生日期", + "Blocked Groups": "", "BM25 Weight": "BM25 混合搜索权重", "Bocha Search API Key": "Bocha Search 接口密钥", "Bold": "粗体", @@ -321,7 +356,7 @@ "Chat Completions": "Chat Completions", "Chat Conversation": "对话内容", "Chat deleted.": "对话已删除。", - "Chat direction": "对话显示方向", + "Chat Direction": "对话显示方向", "Chat exported successfully": "对话已成功导出", "Chat History": "对话历史记录", "Chat ID": "对话 ID", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "成员可加入的协作频道", "Collapse": "折叠", "Collection": "文件集", + "Collection Field": "", "Collections": "文件集", "Color": "颜色", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "ComfyUI 工作流", "ComfyUI Workflow Nodes": "ComfyUI 工作流节点", "Comma separated Node Ids (e.g. 1 or 1,2)": "使用英文逗号分隔的节点 ID(例如 1 或 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "命令", "Command": "命令", "Comment": "注释", "Commit Message": "提交说明", "Community Reviews": "社区评价", + "Compacting context": "", "Comparing with knowledge base...": "正在比对知识库...", "Completions": "续写", "Compress Images in Channels": "压缩频道中的图片", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "连接到 Open Terminal 实例后,所有用户将可以浏览服务器上的文件,并使用终端工具。", "Connect to your own OpenAI compatible API endpoints.": "连接到符合 OpenAI 接口格式的接口", "Connect to your own OpenAPI compatible external tool servers.": "连接到符合 OpenAPI 规范的外部工具服务器", + "Connected": "", "Connected ({{type}})": "已连接({{type}})", "Connection failed": "连接失败", "Connection lost. Reconnecting...": "连接已断开,正在重新连接...", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "请联系管理员以获取访问权限", "Content": "内容", "Content Extraction Engine": "内容提取引擎", + "Content Field": "", "Content lengths (character counts only)": "内容长度(仅统计字符)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "上下文 Token", + "Continue": "", "Continue Response": "继续生成", "Continue with {{provider}}": "使用 {{provider}} 继续", "Continue with Email": "使用邮箱登录", @@ -489,6 +536,7 @@ "Create new secret key": "创建新安全密钥", "Create note": "创建笔记", "Create Note": "创建笔记", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "创建按周期自动执行的提示词任务。", "Create your first note by clicking on the plus button below.": "点击下面的加号按钮创建您的第一个笔记", "Created at": "创建于", @@ -506,6 +554,7 @@ "Custom Gender": "自定义性别", "Custom Parameter Name": "自定义参数名称", "Custom Parameter Value": "自定义参数值", + "Custom range": "", "Daily": "每日", "Daily Messages": "每日消息数", "Danger Zone": "危险区域", @@ -528,7 +577,6 @@ "Default Features": "默认功能", "Default Filters": "默认过滤器", "Default Group": "默认用户组", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "“默认”模式会在请求模型前调用工具,因此能兼容更多模型。“原生”模式则依赖模型本身的工具调用能力,但需要模型本身支持该功能。", "Default Model": "默认模型", "Default model updated": "默认模型已更新", "Default permissions": "默认权限", @@ -538,6 +586,7 @@ "Default to ALL": "默认为:ALL", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "默认进行分段检索以提取重点和相关内容(推荐)", "Default User Role": "默认用户角色", + "Default webhook": "", "Defaults": "默认值", "Delete": "删除", "Delete {{name}}": "删除 {{name}}", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "禁用代码解释器", "Disable Image Extraction": "禁用图像提取", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "禁用从 PDF 中提取图像。若启用“使用大语言模型(LLM)”,图像将自动添加描述。默认为关闭", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "已禁用", "Disconnect OAuth": "断开 OAuth 连接", "Discover a function": "发现更多函数", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "发现、下载并探索更多模型预设", "Discussion channel where access is based on groups and permissions": "由用户组控制的讨论频道", "Display": "显示", - "Display chat title in tab": "在浏览器标签页中显示对话标题", + "Display Chat Title in Tab": "在浏览器标签页中显示对话标题", "Display Emoji in Call": "在通话中显示 Emoji", "Display Multi-model Responses in Tabs": "以标签页的形式展示多个模型的回答", - "Display the username instead of You in the Chat": "在对话中显示用户名而不是“你”", + "Display the Username Instead of You in the Chat": "在对话中显示用户名而不是“你”", "Displays citations in the response": "在回答中显示引用来源", "Displays status updates (e.g., web search progress) in the response": "在回答中显示实时状态信息(例如:网络搜索进度)", "Dive into knowledge": "纵览知识", @@ -626,6 +677,7 @@ "Docling Parameters": "Docling 参数", "Docling Server URL required.": "需要提供 Docling 服务器接口地址", "Document": "文档", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "Document Intelligence 接口地址是必填项。", "Document Intelligence Model": "Document Intelligence 模型", @@ -681,12 +733,14 @@ "Edit Default Permissions": "编辑默认权限", "Edit Folder": "编辑分组", "Edit Image": "图片编辑", + "Edit Knowledge Connection": "", "Edit Last Message": "编辑最后一条消息", "Edit Memory": "编辑记忆", "Edit Prompt": "编辑提示词", "Edit Terminal Connection": "编辑终端连接", "Edit User": "编辑用户", "Edit User Group": "编辑用户组", + "Edit webhook": "", "Edit workflow.json content": "编辑 workflow.json", "edited": "已编辑", "Edited": "已编辑", @@ -695,6 +749,7 @@ "Eject model": "卸载模型", "ElevenLabs": "ElevenLabs", "Email": "电子邮箱", + "Email Claim": "", "Embark on adventures": "破界远航", "Embedding": "嵌入", "Embedding Batch Size": "嵌入层批处理大小 (Embedding Batch Size)", @@ -703,6 +758,7 @@ "Embedding Model Engine": "嵌入模型引擎", "Emoji": "表情符号", "Emojis": "表情符号", + "Empty": "", "Empty message": "(空消息)", "Enable All": "全部启用", "Enable API Keys": "启用接口密钥", @@ -710,22 +766,27 @@ "Enable Code Execution": "启用代码执行", "Enable Code Interpreter": "启用代码解释器", "Enable Community Sharing": "启用分享至社区", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "启用内存锁定 (mlock),防止模型数据被移出内存。此选项将模型的工作集页面锁定在内存中,确保它们不会被交换到磁盘,避免页面错误,确保快速数据访问,从而维持性能。", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "启用内存映射 (mmap) 加载模型数据。此选项将磁盘文件视作内存中的数据,允许系统使用磁盘存储作为内存的扩展,通过更快的数据访问来提高模型性能。然而,它可能无法在所有系统上正常工作,并且可能会消耗大量磁盘空间。", "Enable Message Queue": "启用消息队列", "Enable Message Rating": "启用模型回答结果评价", "Enable Mirostat sampling for controlling perplexity.": "启用 Mirostat 采样以控制困惑度", "Enable New Sign Ups": "允许新用户注册", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "启用、禁用或自定义模型使用的推理过程标签。“启用”表示使用默认标签,“禁用”将不识别推理标签,“自定义”可指定起始和闭合标签。", "Enabled": "已启用", "End Tag": "结束标签", + "Endpoint": "", "Endpoint URL": "接口地址", "Enforce Temporary Chat": "强制临时对话", "Enhance": "润色", "Enrich Hybrid Search Text": "增强混合搜索文本", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "确保您的 CSV 文件按以下顺序包含 4 列:姓名、电子邮箱、密码、角色。", "Enter {{role}} message here": "在此处输入 {{role}} 的对话内容", - "Enter a detail about yourself for your LLMs to recall": "输入关于您的详细信息,以便大语言模型记住这些内容。", "Enter a title for the pending user info overlay. Leave empty for default.": "输入用户待激活界面的标题。留空使用默认", "Enter a watermark for the response. Leave empty for none.": "输入复制水印。留空则不添加", "Enter additional headers in JSON format": "输入 JSON 格式的额外 HTTP 标头", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "输入最小块的目标大小", "Enter Chunk Overlap": "输入块重叠 (Chunk Overlap)", "Enter Chunk Size": "输入块大小 (Chunk Size)", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "输入以逗号分隔的“token:bias_value”对(例如:5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "输入用户待激活界面的内容。留空使用默认", "Enter coordinates (e.g. 51.505, -0.09)": "输入坐标经纬度(例如:51.505, -0.09)", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "输入 Jupyter 接口地址", "Enter Kagi Search API Key": "输入 Kagi Search 接口密钥", "Enter Key Behavior": "Enter 键行为", + "Enter language": "", "Enter language codes": "输入语言代码", "Enter Linkup API Key": "输入 Linkup 接口密钥", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "输入 MinerU 接口密钥", "Enter Mistral API Base URL": "输入 Mistral 接口地址", "Enter Mistral API Key": "输入 Mistral 接口密钥", @@ -800,6 +866,7 @@ "Enter prompt here.": "在此输入提示词。", "Enter proxy URL (e.g. https://user:password@host:port)": "输入代理地址(例如:https://用户名:密码@主机名:端口)", "Enter reasoning effort": "输入推理努力", + "Enter Redirect URI": "", "Enter Score": "输入评分", "Enter SearchApi API Key": "输入 SearchApi 接口密钥", "Enter SearchApi Engine": "输入 SearchApi 引擎", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "输入 SerpApi 接口密钥", "Enter SerpApi Engine": "输入 SerpApi 引擎", "Enter Serper API Key": "输入 Serper 接口密钥", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "输入 Serply 接口密钥", "Enter Serpstack API Key": "输入 Serpstack 接口密钥", "Enter server host": "输入服务器主机名", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "输入 Tika 服务器接口地址", "Enter timeout in seconds": "输入以秒为单位的超时时间", "Enter to Send": "Enter 键发送", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "输入 Top K", "Enter Top K Reranker": "输入 Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "输入 URL(例如:http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "错误:ID 为“{{modelId}}”的模型已存在。请选择不同的模型 ID。", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "错误:模型 ID 不能为空。请输入有效的模型 ID。", "Evaluations": "模型评价", + "Event": "", "Event created": "事件已创建", "Event deleted": "事件已删除", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "事件标题", "Event updated": "事件已更新", + "Events": "", "Exa API Key": "Exa 接口密钥", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "例如:(&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "例如:ALL", "Example: mail": "例如:mail", @@ -901,12 +975,18 @@ "Export Config": "导出配置文件", "Export Models": "导出模型配置", "Export Prompts": "导出提示词", + "Export Skills": "", "Export to CSV": "导出到 CSV", "Export Tools": "导出工具配置", "Export Users": "导出所有用户信息", "External": "外部", + "External connection not found.": "", "External Document Loader URL required.": "需要外部文档加载器接口地址", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "外部任务模型", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "外部网页加载器接口密钥", "External Web Loader URL": "外部网页加载器接口地址", "External Web Search API Key": "外部联网搜索接口密钥", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "创建接口密钥失败", "Failed to delete calendar": "删除日程失败", "Failed to delete note": "删除笔记失败", + "Failed to delete webhook": "", "Failed to disconnect": "断开连接失败", "Failed to download image": "图片下载失败", "Failed to extract content from the file: {{error}}": "文件内容提取失败:{{error}}", @@ -931,6 +1012,7 @@ "Failed to fetch models": "获取模型失败", "Failed to generate title": "生成标题失败", "Failed to import models": "导入模型配置失败", + "Failed to load chat": "", "Failed to load chat preview": "对话预览加载失败", "Failed to load DOCX file. Please try downloading it instead.": "无法加载 DOCX 文件,请尝试下载后查看。", "Failed to load Excel/CSV file. Please try downloading it instead.": "加载 Excel/CSV 文件失败,请尝试直接下载文件。", @@ -940,6 +1022,7 @@ "Failed to move chat": "移动对话失败", "Failed to process URL: {{url}}": "处理链接失败: {{url}}", "Failed to read clipboard contents": "读取剪贴板内容失败", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "移除成员失败", "Failed to render diagram": "图表渲染失败", "Failed to render visualization": "图表渲染失败", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "保存模型配置失败", "Failed to save policy: {{error}}": "保存策略失败:{{error}}", "Failed to save terminal servers": "终端服务器保存失败", + "Failed to save webhook": "", "Failed to unshare chat.": "取消对话分享失败。", "Failed to update settings": "更新设置失败", "Failed to update status": "更新状态失败", + "Failed to update webhook": "", "Failed to upload file.": "上传文件失败", "Features": "功能", "Features Permissions": "功能权限", @@ -983,6 +1068,8 @@ "File uploaded successfully": "文件上传成功", "Filename": "文件名", "Files": "文件", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "过滤", "Filter is now globally disabled": "过滤器已全局禁用", "Filter is now globally enabled": "过滤器已全局启用", @@ -1005,6 +1092,7 @@ "Folder options": "分组选项", "Folder updated successfully": "分组更新成功", "Folders": "分组", + "Folders Sharing": "", "Follow up": "追问", "Follow Up Generation": "追问生成", "Follow Up Generation Prompt": "追问生成提示词", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "函数全局已启用", "Function Name": "函数名称", "Function Name Filter List": "函数名称过滤列表", + "Function starter": "", "Function updated successfully": "函数更新成功", "Functions": "函数", "Functions allow arbitrary code execution.": "注意:函数有权执行任意代码", @@ -1067,7 +1156,10 @@ "Gravatar": "Gravatar 头像", "Grid": "网格", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "群组频道", + "Group Claim": "", "Group created successfully": "用户组创建成功", "Group deleted successfully": "用户组删除成功", "Group Description": "用户组描述", @@ -1079,6 +1171,7 @@ "H2": "二级标题", "H3": "三级标题", "Haptic Feedback": "震动反馈", + "Header variables": "", "Headers": "HTTP 标头", "Headers must be a valid JSON object": "HTTP 标头必须是有效的 JSON 格式", "Height": "高度", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID 中不允许包含 “:” 或 “|” 字符", "ID copied to clipboard": "已复制 ID 到剪贴板", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "无操作超时时间", "iframe Sandbox Allow Forms": "iframe 沙盒允许表单提交", "iframe Sandbox Allow Same Origin": "iframe 沙盒允许同源访问", @@ -1134,6 +1229,7 @@ "Import From Link": "从链接导入", "Import Models": "导入模型配置", "Import Prompts": "导入提示词", + "Import Skills": "", "Import successful": "导入成功", "Import Tools": "导入工具配置", "Important Update": "重要更新", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "保留在侧边栏", "Key": "密匙", "Key is required": "密匙是必填项。", - "Keyboard shortcuts": "键盘快捷键", "Keyboard Shortcuts": "键盘快捷键", "Knowledge": "知识库", "Knowledge Access": "访问知识库", @@ -1204,6 +1299,8 @@ "Knowledge Name": "知识库名称", "Knowledge Public Sharing": "公开分享知识库", "Knowledge Sharing": "分享知识库", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "知识库更新成功", "Kokoro.js (Browser)": "Kokoro.js(运行于用户浏览器)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1220,7 +1317,6 @@ "Last ran": "上次运行", "Last reply": "最后回复", "LDAP": "LDAP", - "LDAP server updated": "LDAP 服务器已更新", "Leaderboard": "排行榜", "Learn more": "了解更多", "Learn More": "了解更多", @@ -1242,6 +1338,7 @@ "Legacy": "旧版", "lexical": "关键词", "License": "授权", + "Lifecycle JSON": "", "Lift List": "上移列表", "Light": "浅色", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "搜索并发数限制。默认为 0(无限制),设置为 1 则以顺序执行(推荐用于具有严格速率限制的接口,如 Brave 免费套餐)。", @@ -1265,6 +1362,7 @@ "Location access not allowed": "不允许访问位置信息", "Lost": "较差", "Low": "低", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "从左至右", "Made by Open WebUI Community": "由 Open WebUI 社区开发", "Make password visible in the user interface": "在用户界面中显示密码", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "管理 Pipeline", "Manage Tool Servers": "管理工具服务器", "Manage your account information.": "管理您的账号信息。", + "Mapped Source": "", "March": "三月", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown 标题文本分割器", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "记忆清除成功", "Memory deleted successfully": "记忆删除成功", "Memory updated successfully": "记忆更新成功", + "Merge Accounts by Email": "", "Merge Responses": "合并回答", "Merged Response": "合并的回答", "Message": "消息", @@ -1318,9 +1418,12 @@ "messages": "条消息", "Messages": "消息", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "创建链接后发送的消息将不会被分享。通过该链接访问的用户可以查看对话记录。", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive(个人账户)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive(工作或学校账户)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "分钟", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "使用 MinerU 云服务模式需要接口密钥。", @@ -1373,6 +1476,7 @@ "Models Sharing": "分享模型", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek Search 接口密钥", + "Monday – Friday": "", "Month": "月", "Monthly": "每月", "More": "更多", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "为您的知识库命名", "Name, prompt, and model are required": "名称、提示词和模型不能为空", "Native": "原生", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "未曾", "New": "最新", "New Automation": "创建自动化任务", @@ -1419,6 +1524,7 @@ "Next run": "下次运行", "No access grants. Private to you.": "未共享给他人,仅你可访问。", "No activity data": "没有活动数据", + "No additional headers are sent unless configured.": "", "No authentication": "无身份验证", "No automations found": "还没有任何自动化任务", "No chats found": "未找到对话记录", @@ -1431,8 +1537,10 @@ "No data": "暂无数据", "No data found": "未找到数据", "No distance available": "没有可用距离", + "No event webhooks configured.": "", "No execution logs available yet": "暂无可用的执行日志", "No expiration can pose security risks.": "未设置 JWT 过期时间会导致安全风险。", + "No external knowledge sources configured.": "", "No feedback found": "未找到反馈", "No file selected": "未选中文件", "No files found": "未找到文件", @@ -1460,6 +1568,7 @@ "No output items": "没有任何输出项", "No pinned messages": "没有置顶消息", "No prompts found": "未找到提示词", + "No Repeat": "", "No results": "未找到结果", "No results found": "未找到结果", "No search query generated": "未生成搜索查询", @@ -1479,6 +1588,7 @@ "No webhooks yet": "没有 Webhook", "Node Ids": "节点 ID", "None": "无", + "Not configured": "", "Not factually correct": "与事实不符", "Not helpful": "没有任何帮助", "Not Registered": "未注册", @@ -1494,20 +1604,25 @@ "Notifications": "桌面通知", "November": "十一月", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1(静态)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "OAuth 服务器地址", "OAuth session disconnected": "OAuth 会话已断开", "October": "十月", "Off": "关闭", "Okay, Let's Go!": "确认,开始使用!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "漆黑", "Ollama": "Ollama", "Ollama API": "Ollama 接口", "Ollama API settings updated": "Ollama 接口设置已更新", "Ollama Cloud API Key": "Ollama Cloud 接口密钥", "Ollama Version": "Ollama 版本", + "Omit": "", "On": "开启", "Once": "单次", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "密码", "Passwords do not match.": "两次输入的密码不一致。", "Paste Large Text as File": "粘贴大文本为文件", + "Path": "", "Path copied": "路径已复制", "Paused": "已暂停", "PDF document (.pdf)": "PDF 文档 (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "待激活", "Pending": "待激活", + "Pending Accounts": "", "Pending User Overlay Content": "待激活用户界面内容", "Pending User Overlay Title": "待激活用户界面标题", "Permission denied when accessing media devices": "申请媒体设备权限被拒绝", "Permission denied when accessing microphone": "申请麦克风权限被拒绝", "Permission denied when accessing microphone: {{error}}": "申请麦克风权限被拒绝:{{error}}", "Permissions": "权限", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity 接口密钥", "Perplexity Model": "Perplexity 模型", "Perplexity Search API URL": "Perplexity 搜索接口地址", "Perplexity Search Context Usage": "Perplexity 搜索上下文用量", "Persistent": "持久化", "Personalization": "个性化", + "Picture Claim": "", "Pin": "置顶", "Pin to Sidebar": "固定到侧边栏", "Pinned": "已置顶", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "请填写所有字段。", "Please register the OAuth client": "请注册 OAuth 客户端", "Please save the connection to persist the OAuth client information and do not change the ID": "请保存连接以保留 OAuth 客户端信息,并确保不要更改 ID", - "Please select a model first.": "请先选择模型", "Please select a model.": "请选择模型。", "Please select a reason": "请选择原因", "Please select a valid JSON file": "请选择合法的 JSON 文件", "Please select at least one user for Direct Message channel.": "请至少选择一个用户以创建私聊频道。", "Please wait until all files are uploaded.": "请等待所有文件上传完毕。", "Policy ID": "策略 ID", + "Policy ID is required": "", "Port": "端口", "Ports": "端口", "Positive attitude": "态度积极", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "提示词公开分享", "Prompts Sharing": "分享提示词", "Provider": "提供商", + "Provider Name": "", + "Provider URL": "", "Public": "公共", "Pull \"{{searchValue}}\" from Ollama.com": "从 Ollama.com 下载 “{{searchValue}}”", "Pull a model from Ollama.com": "从 Ollama.com 下载模型", @@ -1683,21 +1804,28 @@ "Read": "只读", "Read Aloud": "朗读", "Read more →": "了解更多 →", + "Read only": "", "Read Only": "只读", "Read-Only Access": "只读权限", "Reason": "推理", "Reasoning Effort": "推理努力 (Reasoning Effort)", "Reasoning Tags": "推理过程标签", "Reasoning text...": "推理文本...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "最近使用", "Reconnected": "已重新连接", "Record": "录制", "Record voice": "录音", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "正在将您重定向到 Open WebUI 社区", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "降低生成无意义内容的概率。较高的值(如 100)将生成更多样化的回答,而较低的值(如 10)则更加保守。", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "使用\"User\" (用户) 来指代自己(例如:“User 正在学习西班牙语”)", "Reference Chats": "引用其他对话", "Refresh": "刷新", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "拒绝了我的要求", "Regenerate": "重新生成", "Regenerate Menu": "显示重新生成选项菜单", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "在文件和引用预览中渲染 Markdown", "Render Markdown in User Messages": "在用户消息中渲染 Markdown", "Reorder Models": "重新排序模型", + "Repeat": "", "Repeats": "重复", "Reply": "回复", "Reply in Thread": "回复主题", "Reply to thread...": "回复主题...", "Replying to {{NAME}}": "回复 {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "必填", "Reranking Batch Size": "重排序批次大小", "Reranking Engine": "重新排名引擎", "Reranking Model": "重新排名模型", + "Research Knowledge": "", "Reset": "重置", "Reset All Models": "重置所有模型", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "重置图片", "Reset knowledge base?": "确认要重置知识库吗?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "重置上传目录", "Reset Vector Storage/Knowledge": "重置向量存储/知识", "Reset view": "重置视图", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "检索到 1 个引用来源", "Rich Text Input for Chat": "富文本对话框", "Role": "角色", + "Roles Claim": "", "RTL": "从右至左", "Run": "运行", "Run All": "运行全部", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "我们不再支持将对话记录直接保存到浏览器的存储空间。请点击下面的按钮下载并删除您的对话记录。别担心,您可以轻松将对话记录重新导入到后台。", "Schedule": "定时", "Scheduled time must be in the future": "定时时间必须晚于当前时间", + "Scopes": "", "Scroll On Branch Change": "切换对话分支时滚动到最新回答", "Scroll to Top": "回到顶部", "Search": "搜索", "Search a model": "搜索模型", + "Search actions": "", "Search all emojis": "搜索 Emoji", "Search and manage user memories": "搜索和管理用户记忆", "Search and view user chat history": "搜索和查看用户对话历史", @@ -1792,6 +1930,7 @@ "Search Chats": "搜索对话", "Search Collection": "搜索内容", "Search Files": "搜索文件", + "Search filters": "", "Search Filters": "搜索过滤器", "search for archived chats": "搜索已归档的对话", "search for folders": "搜索分组", @@ -1806,13 +1945,16 @@ "Search Models": "搜索模型", "Search Notes": "搜索笔记", "Search options": "搜索选项", + "Search or add pattern": "", "Search Prompts": "搜索提示词", "Search Result Count": "搜索结果数量", + "Search skills": "", "Search Skills": "搜索技能", - "Search skills...": "", "Search the internet": "联网搜索", "Search the web and fetch URLs": "搜索网络并获取网页内容", + "Search tools": "", "Search Tools": "搜索工具", + "Search users or groups": "", "Search, view, and manage user notes": "搜索、查看和管理用户笔记", "SearchApi API Key": "SearchApi 接口密钥", "SearchApi Engine": "SearchApi 引擎", @@ -1828,7 +1970,6 @@ "Seed": "种子 (Seed)", "Select": "选择", "Select {{modelName}} model": "选择模型 “{{modelName}}”", - "Select a base model": "选择一个基础模型", "Select a base model (e.g. llama3, gpt-4o)": "选择一个基础模型(例如:llama3, gpt-4o)", "Select a conversation to preview": "选择对话进行预览", "Select a engine": "选择搜索引擎", @@ -1866,18 +2007,25 @@ "semantic": "语义", "Send": "发送", "Send a Message": "输入消息", + "Send events for": "", "Send message": "发送消息", "Send now": "立即发送", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "在请求中发送 `stream_options: { include_usage: true }`。启用此设置后,支持的提供商将在响应中返回 Token 用量信息。", "September": "九月", "SerpApi API Key": "SerpApi 接口密钥", "SerpApi Engine": "SerpApi 引擎", "Serper API Key": "Serper 接口密钥", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply 接口密钥", "Serpstack API Key": "Serpstack 接口密钥", "Server connection failed": "服务器连接失败", "Server connection verified": "已验证服务器连接", + "Service Account": "", "Session": "用户会话(Session)", + "Session expired. Please sign in again.": "", "Set as default": "设为默认", "Set as Production": "设为当前使用版本", "Set embedding model": "设置嵌入模型", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "分享链接已复制到剪贴板。", "Share to Open WebUI Community": "分享到 Open WebUI 社区", "Share your background and interests": "分享您的经历和兴趣爱好", + "Shared": "", "Shared Chats": "已分享的对话", "Shared with you": "已共享给您", "Sharing Permissions": "共享权限", "Show": "显示", - "Show \"What's New\" modal on login": "版本更新后首次登录时显示“新功能介绍”弹窗", + "Show \"What's New\" Modal on Login": "版本更新后首次登录时显示“新功能介绍”弹窗", "Show Admin Details in Account Pending Overlay": "在待激活用户的界面中显示管理员邮箱等详细信息", "Show All": "显示全部", "Show all ({{COUNT}} characters)": "显示全部(共 {{COUNT}} 字符)", "Show Files": "显示文件", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "显示文本格式工具栏", "Show image preview": "显示图像预览", "Show Model": "显示模型", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "搜狗搜索接口 Secret ID", "Sougou Search API SK": "搜狗搜索接口 Secret 密钥", "Source": "来源", + "Specific users or groups": "", "Speech Playback Speed": "语音播放速度", "Speech recognition error: {{error}}": "语音识别错误:{{error}}", "Speech-to-Text": "语音转文本", @@ -1992,6 +2143,7 @@ "STT Settings": "语音转文本设置", "Stylized PDF Export": "美化 PDF 导出", "Su_day_of_week": "周日", + "Sub Claim": "", "Submit question": "提交问题", "Submit suggestion": "提交建议", "Subtitle": "副标题", @@ -2016,8 +2168,10 @@ "Syncing...": "同步中...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "仅同步自上次同步时间点后有更新的对话;关闭后将重新同步全部对话。", "System": "系统", + "System events only": "", "System Instructions": "系统指令", "System Prompt": "系统提示词", + "Table": "", "Tag": "标签", "Tags": "标签", "Tags Generation": "标签生成", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "默认使用临时对话", "Terminal": "终端", "Terminal servers saved": "终端服务器已保存", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "文本切分器", "Text-to-Speech": "文本转语音", "Text-to-Speech Engine": "文本转语音引擎", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "输入音频的语言。以 ISO-639-1 语言编码格式(例如:en)指定输入语言可提高准确性和响应速度。留空则自动检测语言。", "The LDAP attribute that maps to the mail that users use to sign in.": "映射到用户登录时使用的邮箱的 LDAP 属性。", "The LDAP attribute that maps to the username that users use to sign in.": "映射到用户登录时使用的用户名的 LDAP 属性。", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "排行榜目前处于 Beta 测试阶段,我们可能会在完善算法后调整评分计算方法。", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "最大文件大小 (MB)。如果文件大小超过此限制,则无法上传该文件。", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "在单次对话中可以使用的最大文件数。如果文件数超过此限制,则文件不会上传。", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "文本输出格式。可选 'json', 'markdown' 或 'html'。默认为 'markdown'。", @@ -2075,6 +2234,7 @@ "This folder is empty": "此文件夹为空", "This is a default user permission and will remain enabled.": "此权限已在默认用户配置中启用,当前会始终生效。", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "这是一项实验性功能,可能无法按预期运行,也可能会随时发生变化。", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "此模型未公开。请选择其他模型", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "此选项用于控制模型在收到请求后,保持常驻内存的时长(默认:5 分钟)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "此选项控制刷新上下文时保留多少 Token。例如,如果设置为 2,则将保留对话上下文的最后 2 个 Token。保留上下文有助于保持对话的连续性,但可能会降低响应新主题的能力。", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "如需了解更多关于可用端点的信息,请访问我们的文档", "To select skills here, add them to the \"Skills\" workspace first.": "若要在此选择技能,请先将其添加到“技能”工作空间中", "To select toolkits here, add them to the \"Tools\" workspace first.": "如需在这里选择工具包,请先将其添加到工作空间中的“工具”", - "Toast notifications for new updates": "检测到新版本时显示更新通知", + "Toast Notifications for New Updates": "检测到新版本时显示更新通知", "Today": "今天", "Today at": "今天", "Today at {{LOCALIZED_TIME}}": "今天 {{LOCALIZED_TIME}}", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "切换当前连接的启用状态", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Token 数为估算值,可能与实际接口用量不一致", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Tokens", "Too verbose": "过于冗长", @@ -2177,14 +2339,19 @@ "Unpin": "取消置顶", "Unpin from Sidebar": "从侧边栏取消固定", "Unravel secrets": "冲破奥秘", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "取消分享对话", "Unsupported file type.": "不支持的文件类型", "Untagged": "无标签", "Untitled": "无标题", "Update": "更新", "Update and Copy Link": "更新和复制链接", + "Update Email": "", "Update for the latest features and improvements.": "更新以获取最新功能与优化", + "Update Name": "", "Update password": "更新密码", + "Update Picture": "", "Update your status": "更新您的状态", "Updated": "已更新", "Updated at": "更新于", @@ -2211,13 +2378,18 @@ "Use": "使用", "Use '#' in the prompt input to load and include your knowledge.": "在输入框中输入 '#' 号可加载您需要的知识库内容", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "使用 /v1/chat/completions 接口替换 /v1/audio/transcriptions 以提高准确性。", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "使用 Chat Completions 接口", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "使用用户组来管理用户并分配权限。", "Use LLM": "使用大语言模型(LLM)", "Use no proxy to fetch page contents.": "不使用代理获取页面内容", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "使用由 http_proxy 和 https_proxy 环境变量指定的代理获取页面内容", + "Use Web Search?": "", "user": "用户", "User": "用户", + "User Access": "", "User Activity": "用户动态", "User Groups": "用户组", "User location successfully retrieved.": "成功检索到用户位置", @@ -2227,6 +2399,7 @@ "User Status": "用户状态", "User Webhooks": "用户 Webhook", "Username": "用户名", + "Username Claim": "", "users": "用户", "Users": "用户", "Uses DefaultAzureCredential to authenticate": "使用 DefaultAzureCredential 进行身份验证", @@ -2240,6 +2413,7 @@ "Valves updated": "配置项已更新", "Valves updated successfully": "配置项更新成功", "variable": "变量", + "Vector Field": "", "Verify Connection": "验证连接", "Verify SSL Certificate": "验证 SSL 证书", "Version": "版本", @@ -2269,11 +2443,14 @@ "Web API": "网页 API", "Web Loader Engine": "网页加载引擎", "Web Search": "联网搜索", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "联网搜索引擎", "Web Search in Chat": "在对话时进行联网搜索", "Web Search Query Generation": "联网搜索关键词生成", + "Webhook deleted": "", "Webhook Name": "Webhook 名称", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "Webhook", "Webpage URLs": "网页链接", "WebUI Settings": "WebUI 设置", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "Yandex 网页搜索接口密钥", "Yandex Web Search config": "Yandex 网页搜索配置", "Yandex Web Search URL": "Yandex 网页搜索地址", + "Yearly": "", "Yesterday": "昨天", "Yesterday at {{LOCALIZED_TIME}}": "昨天 {{LOCALIZED_TIME}}", "You": "你", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "您的浏览器不支持播放视频。", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的全部捐款将直接给到插件开发者,Open WebUI 不会收取任何分成。但众筹平台可能会有服务费。", "Your message text or inputs": "您的消息文本或输入", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "已成功同步您的使用统计数据。", "YouTube": "YouTube", "Youtube Language": "Youtube 语言", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index 956b5a3ff7..7c41aef63b 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -15,6 +15,8 @@ "{{COUNT}} extracted lines": "已擷取 {{COUNT}} 行", "{{COUNT}} files": "{{COUNT}} 個檔案", "{{count}} files selected. Only new and modified files will be uploaded. Deleted files will be removed. The folder structure will be mirrored. Continue?_other": "已選取 {{count}} 個檔案。僅會上傳新增與已修改的檔案,已刪除的檔案將被移除,並鏡像資料夾結構。是否繼續?", + "{{count}} filters_other": "", + "{{count}} groups_other": "", "{{COUNT}} hidden lines": "已隱藏 {{COUNT}} 行", "{{COUNT}} members": "{{COUNT}} 位成員", "{{count}} of {{total}} accessible_other": "可存取 {{count}}/{{total}}", @@ -22,12 +24,15 @@ "{{COUNT}} Rows": "{{COUNT}} 行", "{{count}} selected_other": "已選取 {{count}} 項", "{{COUNT}} Sources": "{{COUNT}} 個來源", + "{{count}} users_other": "", "{{COUNT}} words": "{{COUNT}} 個詞", "{{COUNT}}d_time_ago": "{{COUNT}} 天前", "{{COUNT}}h_time_ago": "{{COUNT}} 小時前", "{{COUNT}}m_time_ago": "{{COUNT}} 分鐘前", "{{COUNT}}w_time_ago": "{{COUNT}} 週前", "{{COUNT}}y_time_ago": "{{COUNT}} 年前", + "{{label}} contains invalid JSON": "", + "{{label}} must be a JSON object": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "已取消模型 {{model}} 的下載", "{{modelName}} profile image": "模型「{{modelName}}」的頭像", @@ -35,8 +40,10 @@ "{{user}}'s Chats": "{{user}} 的對話", "{{webUIName}} Backend Required": "需要提供 {{webUIName}} 後端", "*Prompt node ID(s) are required for image generation": "* 產生圖片需要提示詞節點 ID", + "1 group": "", "1 hour before": "提前 1 小時", "1 Source": "1 個來源", + "1 user": "", "10 minutes before": "提前 10 分鐘", "15 minutes before": "提前 15 分鐘", "1m_time_ago": "剛剛", @@ -54,6 +61,7 @@ "Access Control": "存取控制", "Access Grants": "存取授權", "Access List": "存取清單", + "Access prohibited": "", "Access updated": "存取權限已更新", "Accessible to all users": "所有使用者皆可存取", "Account": "帳號", @@ -69,6 +77,7 @@ "Activity": "活動", "Add": "新增", "Add a model ID": "新增模型 ID", + "Add a preference, fact, or instruction about you": "", "Add a short description about what this model does": "新增這個模型的簡短描述", "Add a tag": "新增標籤", "Add a tag...": "新增標籤…", @@ -81,8 +90,10 @@ "Add Custom Prompt": "新增自訂提示詞", "Add description": "新增描述", "Add Details": "豐富細節", + "Add durable context for future chats": "", "Add Files": "新增檔案", "Add Image": "新增圖片", + "Add Knowledge Connection": "", "Add location": "新增地點", "Add Member": "新增成員", "Add Members": "新增成員", @@ -97,6 +108,7 @@ "Add to favorites": "新增至收藏", "Add User": "新增使用者", "Add User Group": "新增使用者群組", + "Add webhook": "", "Add webpage": "新增網頁", "Add your Open Terminal URL and API key in Settings → Integrations.": "請至「設定 → 整合」中設定 Open Terminal 的網址與 API 金鑰。", "Additional Config": "額外設定", @@ -109,7 +121,9 @@ "Admin": "管理員", "Admin Contact Email": "管理員聯絡信箱", "Admin Panel": "管理員控制台", + "Admin Roles": "", "Admin Settings": "管理員設定", + "Admin-managed service account": "", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理員可以隨時使用所有工具;使用者則需在工作區中為每個模型分配工具。", "Advanced": "進階", "Advanced Parameters": "進階參數", @@ -120,16 +134,21 @@ "All": "全部", "All chats have been unarchived.": "已成功將所有對話解除封存。", "All day": "全天", + "All events": "", "All models are now hidden": "已隱藏全部模型", "All models are now visible": "已顯示全部模型", "All models deleted successfully": "成功刪除所有模型", + "All shared chats have been unshared.": "", + "All Sources": "", "All time": "全部時間", "All Users": "所有使用者", + "All users and system events": "", "Allow Call": "允許通話", "Allow Chat Controls": "允許控制對話", "Allow Chat Delete": "允許刪除對話", "Allow Chat Edit": "允許編輯對話", "Allow Chat Export": "允許匯出對話", + "Allow Chat Import": "", "Allow Chat Params": "允許設定模型進階參數", "Allow Chat Share": "允許分享對話", "Allow Chat System Prompt": "允許設定對話系統提示詞", @@ -149,9 +168,11 @@ "Allow User Location": "允許使用者位置", "Allow Voice Interruption in Call": "允許在通話中打斷語音", "Allow Web Upload": "允許從網路上傳內容", + "Allowed Domains": "", "Allowed Endpoints": "允許的端點", "Allowed File Extensions": "允許的檔案副檔名", "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "允許上傳的檔案副檔名。多個副檔名請用逗號分隔,留空則允許所有檔案類型。", + "Allowed Roles": "", "Already have an account?": "已經有帳號了嗎?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "top_p 的替代方案,用於確保品質與多樣性之間的平衡。參數 p 代表一個 Token 被考慮的最低機率,相對於最有可能 Token 的機率。例如,當 p=0.05 且最有可能 Token 的機率為 0.9 時,機率小於 0.045 的 logits 將被過濾掉。", "Always": "總是", @@ -170,6 +191,7 @@ "API Base URL": "API 基礎 URL", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker API 服務的請求 URL。預設為:https://www.datalab.to/api/v1/marker", "API Key": "API 金鑰", + "API Key / Token": "", "API Key created.": "API 金鑰已建立。", "API Key Endpoint Restrictions": "API 金鑰端點限制", "API keys": "API 金鑰", @@ -199,13 +221,18 @@ "Are you sure you want to delete this memory? This action cannot be undone.": "確定要刪除這筆記憶嗎?此操作無法復原。", "Are you sure you want to delete this message?": "您確定要刪除此訊息嗎?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "您確定要刪除此版本嗎?子版本將重新連結至上一層版本。", + "Are you sure you want to delete this webhook? This action cannot be undone.": "", "Are you sure you want to delete this?": "確定要刪除嗎?", + "Are you sure you want to reset all permissions to their default values? You will still need to save to apply the changes.": "", "Are you sure you want to unarchive all archived chats?": "您確定要解除封存所有封存的對話記錄嗎?", + "Are you sure you want to unshare all shared chats? This will remove all share links.": "", "Arena Models": "競技場模型", "Artifacts": "產物", "Asc": "升序", "Ask": "提問", "Ask a question": "提出問題", + "Ask a test question": "", + "Ask this knowledge source a test question": "", "Assistant": "助理", "Async Embedding Processing": "非同步嵌入處理", "At time of event": "活動開始時", @@ -220,14 +247,20 @@ "Audio": "音訊", "August": "8 月", "Auth": "驗證", + "Auth Mode": "", + "Auth required": "", "Authenticate": "驗證", "Authentication": "驗證", "Auto": "自動", "Auto (Random)": "隨機", + "Auto Redirect": "", "Auto-Copy Response to Clipboard": "自動將回應複製到剪貼簿", - "Auto-playback response": "自動播放回應", + "Auto-Create Groups": "", + "Auto-Playback Response": "自動播放回應", "Autocomplete Generation": "自動完成產生", "Autocomplete Generation Input Max Length": "自動完成輸入最大長度", + "Autocomplete Generation Prompt": "", + "Automatic": "", "Automatic1111": "Automatic1111", "AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 API 驗證字串", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 基礎 URL", @@ -245,6 +278,7 @@ "Available Skills": "", "Available Tools": "可用工具", "available users": "可用名額", + "Available variables": "", "available!": "可用!", "Away": "離開", "Awful": "糟糕", @@ -255,16 +289,17 @@ "Bad Response": "回應不佳", "Banners": "橫幅", "Base Model (From)": "基礎模型(來自)", + "Base Model is required.": "", "Base Model List Cache speeds up access by fetching base models only at startup or on settings save—faster, but may not show recent base model changes.": "基礎模型清單快取只會在啟動或儲存設定時才取得基礎模型,以加快存取速度,但可能不會顯示最近的基礎模型變更。", "Bearer": "Bearer", "before": "之前", "Being lazy": "懶惰模式", - "Beta": "測試", "Bing": "Bing", "Bing Search V7 Endpoint": "Bing 搜尋 V7 端點", "Bing Search V7 Subscription Key": "Bing 搜尋 V7 訂閱金鑰", "Bio": "個人簡介", "Birth Date": "生日", + "Blocked Groups": "", "BM25 Weight": "BM25 混合搜尋權重", "Bocha Search API Key": "Bocha 搜尋 API 金鑰", "Bold": "粗體", @@ -321,7 +356,7 @@ "Chat Completions": "對話續寫", "Chat Conversation": "對話內容", "Chat deleted.": "對話已刪除。", - "Chat direction": "對話方向", + "Chat Direction": "對話方向", "Chat exported successfully": "對話已成功匯出", "Chat History": "對話歷史", "Chat ID": "對話 ID", @@ -393,6 +428,7 @@ "Collaboration channel where people join as members": "成員可加入的協作頻道", "Collapse": "摺疊", "Collection": "文件集", + "Collection Field": "", "Collections": "文件集", "Color": "顏色", "ComfyUI": "ComfyUI", @@ -402,12 +438,14 @@ "ComfyUI Workflow": "ComfyUI 工作流程", "ComfyUI Workflow Nodes": "ComfyUI 工作流程節點", "Comma separated Node Ids (e.g. 1 or 1,2)": "使用英文逗號分隔的節點 ID(例如 1 或 1,2)", + "Comma-separated group names": "", "Comma-separated list of file extensions MinerU will handle (e.g. pdf, docx, pptx, xlsx)": "", "command": "命令", "Command": "命令", "Comment": "註解", "Commit Message": "提交說明", "Community Reviews": "社群評價", + "Compacting context": "", "Comparing with knowledge base...": "正在與知識庫比對...", "Completions": "自動完成", "Compress Images in Channels": "壓縮頻道中的圖片", @@ -428,6 +466,7 @@ "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "連接到 Open Terminal 實例後,所有使用者將可瀏覽伺服器上的檔案,並使用終端工具。", "Connect to your own OpenAI compatible API endpoints.": "連線至您自有或其他與 OpenAI API 相容的端點。", "Connect to your own OpenAPI compatible external tool servers.": "連線至您自有或其他與 OpenAPI 相容的外部工具伺服器。", + "Connected": "", "Connected ({{type}})": "已連線({{type}})", "Connection failed": "連線失敗", "Connection lost. Reconnecting...": "連線中斷,正在重新連線...", @@ -440,8 +479,16 @@ "Contact Admin for WebUI Access": "請聯絡管理員以取得 WebUI 存取權限", "Content": "內容", "Content Extraction Engine": "內容擷取引擎", + "Content Field": "", "Content lengths (character counts only)": "內容長度(僅統計字元)", + "Context": "", + "Context compacted": "", + "Context Compaction": "", + "Context compaction failed": "", + "Context Compaction Prompt": "", + "Context Compaction Threshold": "", "Context Tokens": "上下文 Token", + "Continue": "", "Continue Response": "繼續回應", "Continue with {{provider}}": "使用 {{provider}} 繼續", "Continue with Email": "使用 Email 繼續", @@ -489,6 +536,7 @@ "Create new secret key": "建立新的金鑰", "Create note": "建立筆記", "Create Note": "建立筆記", + "Create one read-only Knowledge source per external collection. Test must pass before the source is created.": "", "Create scheduled prompts that run automatically on a recurring basis.": "建立可按固定週期自動執行的提示詞。", "Create your first note by clicking on the plus button below.": "點選下方加號按鈕建立您的第一則筆記。", "Created at": "建立於", @@ -506,6 +554,7 @@ "Custom Gender": "自訂性別", "Custom Parameter Name": "自訂參數名稱", "Custom Parameter Value": "自訂參數值", + "Custom range": "", "Daily": "每日", "Daily Messages": "每日訊息數", "Danger Zone": "危險區域", @@ -528,7 +577,6 @@ "Default Features": "預設功能", "Default Filters": "預設篩選器", "Default Group": "預設群組", - "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "預設模式透過在執行前呼叫工具一次,來與更廣泛的模型相容。原生模式則利用模型內建的工具呼叫能力,但需要模型本身就支援此功能。", "Default Model": "預設模型", "Default model updated": "預設模型已更新", "Default permissions": "預設權限", @@ -538,6 +586,7 @@ "Default to ALL": "預設到所有", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "預設使用分段檢索以提取聚焦且相關的內容,建議用於大多數情況。", "Default User Role": "預設使用者角色", + "Default webhook": "", "Defaults": "預設值", "Delete": "刪除", "Delete {{name}}": "刪除 {{name}}", @@ -598,6 +647,8 @@ "Disable Code Interpreter": "停用程式碼解譯器", "Disable Image Extraction": "停用圖片擷取", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "停用從 PDF 擷取圖片。若啟用「使用 LLM」,圖片將自動新增說明。預設為 False。", + "Disable Image Generation": "", + "Disable Web Search": "", "Disabled": "已停用", "Disconnect OAuth": "中斷 OAuth 連線", "Discover a function": "發掘函式", @@ -612,10 +663,10 @@ "Discover, download, and explore model presets": "發掘、下載及探索模型預設集", "Discussion channel where access is based on groups and permissions": "基於群組權限的討論頻道", "Display": "顯示", - "Display chat title in tab": "在瀏覽器分頁標籤上顯示對話標題", + "Display Chat Title in Tab": "在瀏覽器分頁標籤上顯示對話標題", "Display Emoji in Call": "在通話中顯示表情符號", "Display Multi-model Responses in Tabs": "以標籤頁的形式展示多個模型的回應", - "Display the username instead of You in the Chat": "在對話中顯示使用者名稱,而非「您」", + "Display the Username Instead of You in the Chat": "在對話中顯示使用者名稱,而非「您」", "Displays citations in the response": "在回應中顯示引用", "Displays status updates (e.g., web search progress) in the response": "在回應中顯示進度狀態(例如:網路搜尋進度)", "Dive into knowledge": "挖掘知識", @@ -626,6 +677,7 @@ "Docling Parameters": "Docling 參數", "Docling Server URL required.": "需要提供 Docling 伺服器 URL。", "Document": "檔案", + "Document ID Field": "", "Document Intelligence": "Document Intelligence", "Document Intelligence endpoint required.": "需要提供 Document Intelligence 端點。", "Document Intelligence Model": "Document Intelligence 模型", @@ -681,12 +733,14 @@ "Edit Default Permissions": "編輯預設權限", "Edit Folder": "編輯分組", "Edit Image": "編輯圖片", + "Edit Knowledge Connection": "", "Edit Last Message": "編輯最後一則訊息", "Edit Memory": "編輯記憶", "Edit Prompt": "編輯提示詞", "Edit Terminal Connection": "編輯終端連線", "Edit User": "編輯使用者", "Edit User Group": "編輯使用者群組", + "Edit webhook": "", "Edit workflow.json content": "編輯 workflow.json 內容", "edited": "已編輯", "Edited": "已編輯", @@ -695,6 +749,7 @@ "Eject model": "卸載模型", "ElevenLabs": "ElevenLabs", "Email": "Email", + "Email Claim": "", "Embark on adventures": "展開探險之旅", "Embedding": "嵌入", "Embedding Batch Size": "嵌入批次大小", @@ -703,6 +758,7 @@ "Embedding Model Engine": "嵌入模型引擎", "Emoji": "表情符號", "Emojis": "表情符號", + "Empty": "", "Empty message": "(空消息)", "Enable All": "全部啟用", "Enable API Keys": "啟用 API 金鑰", @@ -710,22 +766,27 @@ "Enable Code Execution": "啟用程式碼執行", "Enable Code Interpreter": "啟用程式碼直譯器", "Enable Community Sharing": "啟用社群分享", + "Enable Group Mapping": "", + "Enable Image Generation": "", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "啟用記憶體鎖定(mlock)以防止模型資料被換出 RAM。此選項會將模型的工作頁面集鎖定在 RAM 中,確保它們不會被換出到磁碟。這可以透過避免頁面錯誤和確保快速資料存取來維持效能。", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "啟用記憶體映射(mmap)以載入模型資料。此選項允許系統使用磁碟儲存作為 RAM 的延伸,透過將磁碟檔案視為在 RAM 中來處理。這可以透過允許更快的資料存取來改善模型效能。然而,它可能無法在所有系統上正常運作,並且可能會消耗大量磁碟空間。", "Enable Message Queue": "啟用訊息佇列", "Enable Message Rating": "啟用訊息評分", "Enable Mirostat sampling for controlling perplexity.": "啟用 Mirostat 取樣以控制 perplexity。", "Enable New Sign Ups": "允許新使用者註冊", + "Enable OAuth Signup": "", + "Enable Role Mapping": "", + "Enable Web Search": "", "Enable, disable, or customize the reasoning tags used by the model. \"Enabled\" uses default tags, \"Disabled\" turns off reasoning tags, and \"Custom\" lets you specify your own start and end tags.": "啟用、停用或自訂模型的推理標籤。「啟用」將使用預設的推理標籤,「停用」則不使用推理標籤,「自訂」允許您指定模型推理過程的起始與結束標籤。", "Enabled": "已啟用", "End Tag": "結束標籤", + "Endpoint": "", "Endpoint URL": "端點 URL", "Enforce Temporary Chat": "強制使用臨時對話", "Enhance": "增強", "Enrich Hybrid Search Text": "增強混合搜尋文字", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "請確認您的 CSV 檔案包含以下 4 個欄位,並按照此順序排列:姓名、電子郵件、密碼、角色。", "Enter {{role}} message here": "在此輸入 {{role}} 訊息", - "Enter a detail about yourself for your LLMs to recall": "輸入有關您的詳細資訊,讓您的大型語言模型可以回想起來", "Enter a title for the pending user info overlay. Leave empty for default.": "為待處理的使用者訊息覆蓋層輸入標題。留空以使用預設值。", "Enter a watermark for the response. Leave empty for none.": "請輸入回應浮水印內容,留空表示不使用浮水印。", "Enter additional headers in JSON format": "請輸入額外的 HTTP 標頭,以 JSON 格式表示", @@ -742,6 +803,8 @@ "Enter Chunk Min Size Target": "輸入最小塊目標大小", "Enter Chunk Overlap": "輸入區塊重疊", "Enter Chunk Size": "輸入區塊大小", + "Enter Client ID": "", + "Enter Client Secret": "", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "輸入逗號分隔的 \"token:bias_value\" 配對 (範例:5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "為待處理的使用者訊息覆蓋層輸入內容。留空以使用預設值。", "Enter coordinates (e.g. 51.505, -0.09)": "輸入座標經緯度(例如:51.505, -0.09)", @@ -779,8 +842,11 @@ "Enter Jupyter URL": "輸入 Jupyter URL", "Enter Kagi Search API Key": "輸入 Kagi 搜尋 API 金鑰", "Enter Key Behavior": "Enter 鍵行為", + "Enter language": "", "Enter language codes": "輸入語言代碼", "Enter Linkup API Key": "輸入 Linkup API 金鑰", + "Enter Microsoft Web IQ API Base URL": "", + "Enter Microsoft Web IQ API Key": "", "Enter MinerU API Key": "輸入 MinerU API 金鑰", "Enter Mistral API Base URL": "輸入 Mistral API 基礎 URL", "Enter Mistral API Key": "輸入 Mistral API 金鑰", @@ -800,6 +866,7 @@ "Enter prompt here.": "在此輸入提示詞。", "Enter proxy URL (e.g. https://user:password@host:port)": "輸入代理程式 URL(例如:https://user:password@host:port)", "Enter reasoning effort": "輸入推理程度", + "Enter Redirect URI": "", "Enter Score": "輸入分數", "Enter SearchApi API Key": "輸入 SearchApi API 金鑰", "Enter SearchApi Engine": "輸入 SearchApi 引擎", @@ -809,6 +876,7 @@ "Enter SerpApi API Key": "輸入 SerpApi API 金鑰", "Enter SerpApi Engine": "輸入 SerpApi 引擎", "Enter Serper API Key": "輸入 Serper API 金鑰", + "Enter SERPHouse API Key": "", "Enter Serply API Key": "輸入 Serply API 金鑰", "Enter Serpstack API Key": "輸入 Serpstack API 金鑰", "Enter server host": "輸入伺服器主機", @@ -829,6 +897,8 @@ "Enter Tika Server URL": "輸入 Tika 伺服器 URL", "Enter timeout in seconds": "請以秒為單位輸入超時時間", "Enter to Send": "使用 Enter 傳送", + "Enter token threshold": "", + "Enter Tokenizer Model": "", "Enter Top K": "輸入 Top K 值", "Enter Top K Reranker": "輸入 Top K Reranker", "Enter URL (e.g. http://127.0.0.1:7860/)": "輸入 URL(例如:http://127.0.0.1:7860/)", @@ -869,11 +939,15 @@ "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "錯誤:ID 為「{{modelId}}」的模型已存在。請選擇不同的模型 ID。", "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "錯誤:模型 ID 不能為空。請輸入有效的模型 ID。", "Evaluations": "評估", + "Event": "", "Event created": "活動已建立", "Event deleted": "活動已刪除", + "Event names may change as Open WebUI evolves. Use broad patterns like user.* for integrations that should continue across new related events.": "", "Event title": "活動標題", "Event updated": "活動已更新", + "Events": "", "Exa API Key": "Exa API 金鑰", + "Example": "", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "範例:(&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "範例:ALL", "Example: mail": "範例:mail", @@ -901,12 +975,18 @@ "Export Config": "匯出設定檔", "Export Models": "匯出模型", "Export Prompts": "匯出提示詞", + "Export Skills": "", "Export to CSV": "匯出為 CSV", "Export Tools": "匯出工具", "Export Users": "匯出所有使用者資訊", "External": "外部", + "External connection not found.": "", "External Document Loader URL required.": "需要提供外部文件載入器 URL。", + "External Knowledge Source": "", + "External Knowledge Sources": "", "External Task Model": "外部任務模型", + "External Tool Servers": "", + "External vectors must be generated with the same embedding model configured in Open WebUI.": "", "External Web Loader API Key": "外部網頁載入器 API 金鑰", "External Web Loader URL": "外部網頁載入器 URL", "External Web Search API Key": "外部網路搜尋 API 金鑰", @@ -924,6 +1004,7 @@ "Failed to create API Key.": "建立 API 金鑰失敗。", "Failed to delete calendar": "刪除日程失敗", "Failed to delete note": "刪除筆記失敗", + "Failed to delete webhook": "", "Failed to disconnect": "中斷連線失敗", "Failed to download image": "圖片下載失敗", "Failed to extract content from the file: {{error}}": "檔案內容擷取失敗:{{error}}", @@ -931,6 +1012,7 @@ "Failed to fetch models": "取得模型失敗", "Failed to generate title": "產生標題失敗", "Failed to import models": "匯入模型失敗", + "Failed to load chat": "", "Failed to load chat preview": "對話預覽載入失敗", "Failed to load DOCX file. Please try downloading it instead.": "無法載入 DOCX 檔案,請改為下載後再開啟。", "Failed to load Excel/CSV file. Please try downloading it instead.": "無法載入 Excel/CSV 檔案。請嘗試直接下載檔案。", @@ -940,6 +1022,7 @@ "Failed to move chat": "移動對話失敗", "Failed to process URL: {{url}}": "處理連結失敗:{{url}}", "Failed to read clipboard contents": "讀取剪貼簿內容失敗", + "Failed to refresh terminals: {{error}}": "", "Failed to remove member": "移除成員失敗", "Failed to render diagram": "繪製圖表失敗", "Failed to render visualization": "繪製圖表失敗", @@ -948,9 +1031,11 @@ "Failed to save models configuration": "儲存模型設定失敗", "Failed to save policy: {{error}}": "儲存策略失敗:{{error}}", "Failed to save terminal servers": "終端伺服器儲存失敗", + "Failed to save webhook": "", "Failed to unshare chat.": "取消分享對話失敗。", "Failed to update settings": "更新設定失敗", "Failed to update status": "更新狀態失敗", + "Failed to update webhook": "", "Failed to upload file.": "上傳檔案失敗。", "Features": "功能", "Features Permissions": "功能權限", @@ -983,6 +1068,8 @@ "File uploaded successfully": "成功上傳檔案", "Filename": "檔案名稱", "Files": "檔案", + "Fill the required fields first.": "", + "Fill the source fields and test query first.": "", "Filter": "篩選", "Filter is now globally disabled": "篩選器已全域停用", "Filter is now globally enabled": "篩選器已全域啟用", @@ -1005,6 +1092,7 @@ "Folder options": "資料夾選項", "Folder updated successfully": "分組更新成功", "Folders": "分組", + "Folders Sharing": "", "Follow up": "跟進", "Follow Up Generation": "跟進內容產生", "Follow Up Generation Prompt": "跟進內容產生提示詞", @@ -1035,6 +1123,7 @@ "Function is now globally enabled": "已全域啟用函式", "Function Name": "函式名稱", "Function Name Filter List": "函式名稱篩選列表", + "Function starter": "", "Function updated successfully": "成功更新函式", "Functions": "函式", "Functions allow arbitrary code execution.": "函式允許執行任意程式碼。", @@ -1067,7 +1156,10 @@ "Gravatar": "Gravatar 大頭貼", "Grid": "網格", "Grokipedia": "Grokipedia", + "group": "", + "Group": "", "Group Channel": "群組頻道", + "Group Claim": "", "Group created successfully": "成功建立群組", "Group deleted successfully": "成功刪除群組", "Group Description": "群組描述", @@ -1079,6 +1171,7 @@ "H2": "二級標題", "H3": "三級標題", "Haptic Feedback": "觸覺回饋", + "Header variables": "", "Headers": "HTTP 標頭", "Headers must be a valid JSON object": "HTTP 標頭必須是有效的 JSON 格式", "Height": "高度", @@ -1109,6 +1202,8 @@ "ID": "ID", "ID cannot contain \":\" or \"|\" characters": "ID 不能包含 \":\" 或 \"|\" 字元", "ID copied to clipboard": "ID 已複製到剪貼簿", + "Identity audit": "", + "Idle only": "", "Idle Timeout": "閒置逾時時間", "iframe Sandbox Allow Forms": "iframe 沙盒允許表單", "iframe Sandbox Allow Same Origin": "iframe 沙盒允許同源", @@ -1134,6 +1229,7 @@ "Import From Link": "從連結匯入", "Import Models": "匯入模型", "Import Prompts": "匯入提示詞", + "Import Skills": "", "Import successful": "匯入成功", "Import Tools": "匯入工具", "Important Update": "重要更新", @@ -1191,7 +1287,6 @@ "Keep in Sidebar": "保留在側邊欄", "Key": "金鑰", "Key is required": "金鑰為必填項目", - "Keyboard shortcuts": "鍵盤快捷鍵", "Keyboard Shortcuts": "鍵盤快捷鍵", "Knowledge": "知識庫", "Knowledge Access": "知識庫存取", @@ -1204,6 +1299,8 @@ "Knowledge Name": "知識庫名稱", "Knowledge Public Sharing": "知識庫公開分享", "Knowledge Sharing": "分享知識庫", + "Knowledge source created.": "", + "Knowledge source updated.": "", "Knowledge updated successfully": "成功更新知識庫", "Kokoro.js (Browser)": "Kokoro.js (瀏覽器)", "Kokoro.js Dtype": "Kokoro.js Dtype", @@ -1220,7 +1317,6 @@ "Last ran": "上次執行", "Last reply": "上次回覆", "LDAP": "LDAP", - "LDAP server updated": "LDAP 伺服器已更新", "Leaderboard": "排行榜", "Learn more": "了解更多", "Learn More": "了解更多", @@ -1242,6 +1338,7 @@ "Legacy": "舊版", "lexical": "關鍵詞", "License": "授權", + "Lifecycle JSON": "", "Lift List": "上移清單", "Light": "淺色", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "平行搜尋數量限制。預設為 0(無限制),設定為 1 則以順序執行(建議用於具有嚴格速率限制的服務,如 Brave 免費方案)。", @@ -1265,6 +1362,7 @@ "Location access not allowed": "位置存取未獲允許", "Lost": "落敗", "Low": "低", + "Lower the context compaction token threshold for this model. The global context compaction threshold remains the maximum.": "", "LTR": "從左到右", "Made by Open WebUI Community": "由 Open WebUI 社群製作", "Make password visible in the user interface": "在使用者介面中顯示密碼", @@ -1281,6 +1379,7 @@ "Manage Pipelines": "管理管線", "Manage Tool Servers": "管理工具伺服器", "Manage your account information.": "管理您的帳號資訊。", + "Mapped Source": "", "March": "3 月", "Markdown": "Markdown", "Markdown Header Text Splitter": "Markdown 標題文字分割器", @@ -1308,6 +1407,7 @@ "Memory cleared successfully": "成功清除記憶", "Memory deleted successfully": "成功刪除記憶", "Memory updated successfully": "成功更新記憶", + "Merge Accounts by Email": "", "Merge Responses": "合併回應", "Merged Response": "整合回應結果", "Message": "訊息", @@ -1318,9 +1418,12 @@ "messages": "則訊息", "Messages": "訊息", "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "建立連結後傳送的訊息不會被分享。擁有網址的使用者可檢視分享的對話內容。", + "Metadata Field": "", "Microsoft OneDrive": "Microsoft OneDrive", "Microsoft OneDrive (personal)": "Microsoft OneDrive(個人版)", "Microsoft OneDrive (work/school)": "Microsoft OneDrive(公司版/學校版)", + "Microsoft Web IQ API Base URL": "", + "Microsoft Web IQ API Key": "", "min": "分鐘", "MinerU": "MinerU", "MinerU API Key required for Cloud API mode.": "使用 MinerU 雲端服務模式需要 API 金鑰。", @@ -1373,6 +1476,7 @@ "Models Sharing": "分享模型", "Mojeek": "Mojeek", "Mojeek Search API Key": "Mojeek 搜尋 API 金鑰", + "Monday – Friday": "", "Month": "月", "Monthly": "每月", "More": "更多", @@ -1390,6 +1494,7 @@ "Name your knowledge base": "命名您的知識庫", "Name, prompt, and model are required": "名稱、提示詞與模型為必填項目", "Native": "原生", + "Native mode (default) leverages the model's built-in tool-calling capabilities. Legacy mode works with a wider range of models by calling tools once before execution via prompt injection.": "", "Never": "尚未", "New": "最新", "New Automation": "新增自動化", @@ -1419,6 +1524,7 @@ "Next run": "下次執行", "No access grants. Private to you.": "未分享給他人,僅你可存取。", "No activity data": "沒有活動資料", + "No additional headers are sent unless configured.": "", "No authentication": "無身份驗證", "No automations found": "找不到自動化", "No chats found": "未找到對話記錄", @@ -1431,8 +1537,10 @@ "No data": "暫無資料", "No data found": "找不到資料", "No distance available": "無可用距離", + "No event webhooks configured.": "", "No execution logs available yet": "目前尚無可用的執行記錄", "No expiration can pose security risks.": "未設定 JWT 到期時間可能造成安全風險。", + "No external knowledge sources configured.": "", "No feedback found": "未找到回饋", "No file selected": "未選取檔案", "No files found": "找不到檔案", @@ -1460,6 +1568,7 @@ "No output items": "無輸出項目", "No pinned messages": "沒有置頂訊息", "No prompts found": "未找到提示詞", + "No Repeat": "", "No results": "沒有結果", "No results found": "未找到任何結果", "No search query generated": "未產生搜尋查詢", @@ -1479,6 +1588,7 @@ "No webhooks yet": "尚無 Webhook", "Node Ids": "節點 ID", "None": "無", + "Not configured": "", "Not factually correct": "與事實不符", "Not helpful": "沒有幫助", "Not Registered": "未註冊", @@ -1494,20 +1604,25 @@ "Notifications": "通知", "November": "11 月", "OAuth": "OAuth", + "OAuth / OIDC": "", "OAuth 2.1": "OAuth 2.1", "OAuth 2.1 (Static)": "OAuth 2.1(靜態)", "OAuth ID": "OAuth ID", + "OAuth Resource Parameter": "", + "OAuth Scopes": "", "OAuth Server URL": "OAuth 伺服器 URL", "OAuth session disconnected": "OAuth 工作階段已中斷", "October": "10 月", "Off": "關閉", "Okay, Let's Go!": "好的,我們開始吧!", + "Older messages are summarized when estimated context exceeds this token limit.": "", "OLED Dark": "OLED 深色", "Ollama": "Ollama", "Ollama API": "Ollama API", "Ollama API settings updated": "Ollama API 設定已更新", "Ollama Cloud API Key": "Ollama Cloud API 金鑰", "Ollama Version": "Ollama 版本", + "Omit": "", "On": "開啟", "Once": "一次", "OneDrive": "OneDrive", @@ -1578,6 +1693,7 @@ "Password": "密碼", "Passwords do not match.": "兩次輸入的密碼不一致。", "Paste Large Text as File": "將大型文字以檔案貼上", + "Path": "", "Path copied": "路徑已複製", "Paused": "已暫停", "PDF document (.pdf)": "PDF 檔案 (.pdf)", @@ -1586,18 +1702,21 @@ "pdf, docx, pptx, xlsx": "", "pending": "待處理", "Pending": "待處理", + "Pending Accounts": "", "Pending User Overlay Content": "待處理的使用者訊息覆蓋層內容", "Pending User Overlay Title": "待處理的使用者訊息覆蓋層標題", "Permission denied when accessing media devices": "存取媒體裝置時權限遭拒", "Permission denied when accessing microphone": "存取麥克風時權限遭拒", "Permission denied when accessing microphone: {{error}}": "存取麥克風時權限遭拒:{{error}}", "Permissions": "權限", + "Permissions reset to defaults": "", "Perplexity API Key": "Perplexity API 金鑰", "Perplexity Model": "Perplexity 模型", "Perplexity Search API URL": "Perplexity 搜尋 API URL", "Perplexity Search Context Usage": "Perplexity 搜尋上下文使用量", "Persistent": "持久性", "Personalization": "個人化", + "Picture Claim": "", "Pin": "釘選", "Pin to Sidebar": "固定到側邊欄", "Pinned": "已釘選", @@ -1630,13 +1749,13 @@ "Please fill in all fields.": "請填寫所有欄位。", "Please register the OAuth client": "請註冊 OAuth 用戶端", "Please save the connection to persist the OAuth client information and do not change the ID": "請儲存連線以保存 OAuth 用戶端資訊,且勿更改 ID", - "Please select a model first.": "請先選擇模型。", "Please select a model.": "請選擇一個模型。", "Please select a reason": "請選擇原因", "Please select a valid JSON file": "請選擇有效的 JSON 檔案", "Please select at least one user for Direct Message channel.": "請至少選擇一位使用者以建立直接訊息頻道。", "Please wait until all files are uploaded.": "請等待所有檔案上傳完畢。", "Policy ID": "策略 ID", + "Policy ID is required": "", "Port": "連接埠", "Ports": "連接埠", "Positive attitude": "積極的態度", @@ -1666,6 +1785,8 @@ "Prompts Public Sharing": "提示詞公開分享", "Prompts Sharing": "分享提示詞", "Provider": "供應商", + "Provider Name": "", + "Provider URL": "", "Public": "公開", "Pull \"{{searchValue}}\" from Ollama.com": "從 Ollama.com 下載「{{searchValue}}」", "Pull a model from Ollama.com": "從 Ollama.com 下載模型", @@ -1683,21 +1804,28 @@ "Read": "讀取", "Read Aloud": "大聲朗讀", "Read more →": "閱讀更多 →", + "Read only": "", "Read Only": "只讀", "Read-Only Access": "只讀權限", "Reason": "原因", "Reasoning Effort": "推理程度", "Reasoning Tags": "推理標籤", "Reasoning text...": "推理文字...", + "Receives matching events across the instance, including system/config events and events associated with any user.": "", + "Receives matching events that are not associated with a user.": "", + "Receives matching user-associated events only when the actor, user subject, or user data matches these users or current group members. System/config events are not sent.": "", "Recently Used": "最近使用", "Reconnected": "已重新連線", "Record": "錄製", "Record voice": "錄音", + "Redirect URI": "", "Redirecting you to Open WebUI Community": "正在將您重導向至 Open WebUI 社群", "Reduces the probability of generating nonsense. A higher value (e.g. 100) will give more diverse answers, while a lower value (e.g. 10) will be more conservative.": "降低產生無意義內容的機率。較高的值(例如:100)會產生更多樣化的答案,而較低的值(例如:10)會更保守。", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "以「使用者」稱呼自己(例如:「使用者正在學習西班牙文」)", "Reference Chats": "引用其他對話", "Refresh": "重新整理", + "Refresh requested: {{count}} terminal(s)_other": "", + "Refresh Terminals": "", + "Refreshing...": "", "Refused when it shouldn't have": "不應拒絕時拒絕了", "Regenerate": "重新產生回應", "Regenerate Menu": "重新產生前顯示選單", @@ -1730,19 +1858,26 @@ "Render Markdown in Previews": "在檔案與引用預覽中轉譯 Markdown", "Render Markdown in User Messages": "在使用者訊息中轉譯 Markdown", "Reorder Models": "重新排序模型", + "Repeat": "", "Repeats": "重複", "Reply": "回覆", "Reply in Thread": "在討論串中回覆", "Reply to thread...": "回覆討論串...", "Replying to {{NAME}}": "回覆 {{NAME}}", + "Require users to confirm before using Web Search.": "", "required": "必填", "Reranking Batch Size": "重排序批次大小", "Reranking Engine": "重新排序引擎", "Reranking Model": "重新排序模型", + "Research Knowledge": "", "Reset": "重設", "Reset All Models": "重設所有模型", + "Reset all permissions to their initial configuration values": "", + "Reset group permissions to match the current default user permissions": "", "Reset Image": "重設圖片", "Reset knowledge base?": "確定要重設知識庫嗎?", + "Reset persisted files": "", + "Reset to Defaults": "", "Reset Upload Directory": "重設上傳目錄", "Reset Vector Storage/Knowledge": "重設向量儲存或知識", "Reset view": "重設檢視", @@ -1761,6 +1896,7 @@ "Retrieved 1 source": "搜尋到 1 個來源", "Rich Text Input for Chat": "使用富文字輸入對話", "Role": "角色", + "Roles Claim": "", "RTL": "從右到左", "Run": "執行", "Run All": "全部執行", @@ -1779,10 +1915,12 @@ "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "不再支援直接將對話紀錄儲存到您的瀏覽器儲存空間。請點選下方按鈕來下載並刪除您的對話紀錄。別擔心,您可以透過以下方式輕鬆地將對話紀錄重新匯入後端", "Schedule": "排程", "Scheduled time must be in the future": "排程時間必須晚於目前時間", + "Scopes": "", "Scroll On Branch Change": "切換分支時自動捲動", "Scroll to Top": "回到頂部", "Search": "搜尋", "Search a model": "搜尋模型", + "Search actions": "", "Search all emojis": "搜尋 Emoji 表情符號", "Search and manage user memories": "搜尋和管理用戶記憶", "Search and view user chat history": "搜尋和查看用戶對話歷史", @@ -1792,6 +1930,7 @@ "Search Chats": "搜尋對話", "Search Collection": "搜尋集合", "Search Files": "搜尋檔案", + "Search filters": "", "Search Filters": "搜尋篩選器", "search for archived chats": "搜尋已封存的聊天", "search for folders": "搜尋分組", @@ -1806,13 +1945,16 @@ "Search Models": "搜尋模型", "Search Notes": "搜尋筆記", "Search options": "搜尋選項", + "Search or add pattern": "", "Search Prompts": "搜尋提示詞", "Search Result Count": "搜尋結果數量", + "Search skills": "", "Search Skills": "搜尋技能", - "Search skills...": "", "Search the internet": "搜尋網路", "Search the web and fetch URLs": "搜尋網路並獲取 URL", + "Search tools": "", "Search Tools": "搜尋工具", + "Search users or groups": "", "Search, view, and manage user notes": "搜尋、查看和管理用戶筆記", "SearchApi API Key": "SearchApi API 金鑰", "SearchApi Engine": "SearchApi 引擎", @@ -1828,7 +1970,6 @@ "Seed": "種子值", "Select": "選擇", "Select {{modelName}} model": "選擇模型「{{modelName}}」", - "Select a base model": "選擇基礎模型", "Select a base model (e.g. llama3, gpt-4o)": "選擇基礎模型(例如:llama3, gpt-4o)", "Select a conversation to preview": "選擇對話進行預覽", "Select a engine": "選擇引擎", @@ -1866,18 +2007,25 @@ "semantic": "語義", "Send": "傳送", "Send a Message": "傳送訊息", + "Send events for": "", "Send message": "傳送訊息", "Send now": "立即傳送", + "Send product events as JSON to external services. Chat destinations receive readable messages.": "", + "Send the PDF as a base64 data URL instead of uploading it first.": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "在請求中傳送 `stream_options: { include_usage: true }`。\n設定後,支援的提供者將在回應中回傳權杖使用資訊。", "September": "9 月", "SerpApi API Key": "SerpApi API 金鑰", "SerpApi Engine": "SerpApi 引擎", "Serper API Key": "Serper API 金鑰", + "SERPHouse API Key": "", + "SERPHouse Domain": "", "Serply API Key": "Serply API 金鑰", "Serpstack API Key": "Serpstack API 金鑰", "Server connection failed": "伺服器連線失敗", "Server connection verified": "伺服器連線已驗證", + "Service Account": "", "Session": "Session", + "Session expired. Please sign in again.": "", "Set as default": "設為預設", "Set as Production": "設為目前使用版本", "Set embedding model": "設定嵌入模型", @@ -1905,15 +2053,17 @@ "Share link copied to clipboard.": "分享連結已複製到剪貼簿。", "Share to Open WebUI Community": "分享到 Open WebUI 社群", "Share your background and interests": "分享您的背景與興趣", + "Shared": "", "Shared Chats": "已分享的對話", "Shared with you": "分享給您", "Sharing Permissions": "分享權限設定", "Show": "顯示", - "Show \"What's New\" modal on login": "登入時顯示「新功能」對話框", + "Show \"What's New\" Modal on Login": "登入時顯示「新功能」對話框", "Show Admin Details in Account Pending Overlay": "在帳號待審覆蓋層中顯示管理員詳細資訊", "Show All": "顯示全部", "Show all ({{COUNT}} characters)": "顯示全部(共 {{COUNT}} 個字元)", "Show Files": "顯示檔案", + "Show Files on Terminal Select": "", "Show Formatting Toolbar": "顯示文字格式工具列", "Show image preview": "顯示圖片預覽", "Show Model": "顯示模型", @@ -1957,6 +2107,7 @@ "Sougou Search API sID": "搜狗搜尋 API sID", "Sougou Search API SK": "搜狗搜尋 API SK", "Source": "來源", + "Specific users or groups": "", "Speech Playback Speed": "語音播放速度", "Speech recognition error: {{error}}": "語音辨識錯誤:{{error}}", "Speech-to-Text": "語音轉文字 (STT) ", @@ -1992,6 +2143,7 @@ "STT Settings": "語音轉文字 (STT) 設定", "Stylized PDF Export": "風格化 PDF 匯出", "Su_day_of_week": "週日", + "Sub Claim": "", "Submit question": "提交問題", "Submit suggestion": "提交建議", "Subtitle": "副標題", @@ -2016,8 +2168,10 @@ "Syncing...": "同步中...", "Syncs only chats with updates after your last sync timestamp. Disable to re-sync all chats.": "僅同步自上次同步時間點後有更新的對話;關閉後將重新同步全部對話。", "System": "系統", + "System events only": "", "System Instructions": "系統指令", "System Prompt": "系統提示詞", + "Table": "", "Tag": "標籤", "Tags": "標籤", "Tags Generation": "標籤生成", @@ -2038,6 +2192,12 @@ "Temporary Chat by Default": "預設使用臨時對話", "Terminal": "終端", "Terminal servers saved": "終端伺服器已儲存", + "Test": "", + "Test Query": "", + "Test returned no results.": "", + "Test succeeded.": "", + "Test the source before creating it.": "", + "Test the source before saving it.": "", "Text Splitter": "文字分割器", "Text-to-Speech": "文字轉語音", "Text-to-Speech Engine": "文字轉語音引擎", @@ -2053,7 +2213,6 @@ "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "輸入音訊的語言。以 ISO-639-1 格式(例如:en)提供輸入語言將提高準確性和減少延遲。留空則自動偵測語言。", "The LDAP attribute that maps to the mail that users use to sign in.": "對應至使用者用於登入之電子郵件的 LDAP 屬性。", "The LDAP attribute that maps to the username that users use to sign in.": "對應至使用者用於登入之使用者名稱的 LDAP 屬性。", - "The leaderboard is currently in beta, and we may adjust the rating calculations as we refine the algorithm.": "排行榜目前處於測試階段,我們可能會在改進演算法時調整評分計算方式。", "The maximum file size in MB. If the file size exceeds this limit, the file will not be uploaded.": "檔案大小上限(MB)。如果檔案大小超過此限制,檔案將不會被上傳。", "The maximum number of files that can be used at once in chat. If the number of files exceeds this limit, the files will not be uploaded.": "對話中一次可使用的最大檔案數量。如果檔案數量超過此限制,檔案將不會被上傳。", "The output format for the text. Can be 'json', 'markdown', or 'html'. Defaults to 'markdown'.": "文字輸出格式,可選擇「json」、「markdown」或「html」。預設為「markdown」。", @@ -2075,6 +2234,7 @@ "This folder is empty": "此資料夾為空", "This is a default user permission and will remain enabled.": "此權限已在預設使用者設定中啟用,並將持續生效。", "This is an experimental feature, it may not function as expected and is subject to change at any time.": "這是一個實驗性功能,它可能無法如預期運作,並且可能會隨時變更。", + "This knowledge base retrieves from a connected source. Open WebUI can query it, but cannot upload, sync, edit, delete, reset, or reindex its source data.": "", "This model is not publicly available. Please select another model.": "此模型未開放公眾使用,請選擇其他模型。", "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "此選項控制模型請求後在記憶體中保持載入狀態的時長(預設:5 分鐘)", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "此選項控制在重新整理上下文時保留多少 Token。例如,如果設定為 2,則會保留對話上下文的最後 2 個 Token。保留上下文有助於保持對話的連貫性,但也可能降低對新主題的回應能力。", @@ -2115,7 +2275,7 @@ "To learn more about available endpoints, visit our documentation.": "若要進一步了解可用的端點,請參閱我們的說明文件。", "To select skills here, add them to the \"Skills\" workspace first.": "若要在此選擇技能,請先將其加入「技能」工作區。", "To select toolkits here, add them to the \"Tools\" workspace first.": "若要在此選擇工具包,請先將它們新增到「工具」工作區。", - "Toast notifications for new updates": "快顯通知新的更新", + "Toast Notifications for New Updates": "快顯通知新的更新", "Today": "今天", "Today at": "今天", "Today at {{LOCALIZED_TIME}}": "今天 {{LOCALIZED_TIME}}", @@ -2129,6 +2289,8 @@ "Toggle whether current connection is active.": "切換目前連線的啟用狀態", "Token": "Token", "Token counts are estimates and may not reflect actual API usage": "Token 數為估算值,可能與實際 API 用量不一致", + "Token Threshold": "", + "Tokenizer Model": "", "tokens": "tokens", "Tokens": "Token 數", "Too verbose": "太過冗長", @@ -2177,14 +2339,19 @@ "Unpin": "取消釘選", "Unpin from Sidebar": "從側邊欄取消釘選", "Unravel secrets": "揭開秘密", + "Unshare All": "", + "Unshare All Shared Chats": "", "Unshare Chat": "取消分享對話", "Unsupported file type.": "不支援的檔案類型", "Untagged": "無標籤", "Untitled": "未命名", "Update": "更新", "Update and Copy Link": "更新並複製連結", + "Update Email": "", "Update for the latest features and improvements.": "更新以獲得最新功能和改進。", + "Update Name": "", "Update password": "更新密碼", + "Update Picture": "", "Update your status": "更新您的狀態", "Updated": "已更新", "Updated at": "更新於", @@ -2211,13 +2378,18 @@ "Use": "使用", "Use '#' in the prompt input to load and include your knowledge.": "在提示詞輸入中使用 '#' 來載入並包含您的知識。", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "使用 /v1/chat/completions 端點而非 /v1/audio/transcriptions 以獲得更好的準確性。", + "Use a valid event name or pattern like user.*": "", + "Use Base64": "", "Use Chat Completions API": "使用 Chat Completions API", + "Use discovered scopes": "", "Use groups to organize your users and assign permissions.": "使用權限群組來管理使用者並分配權限。", "Use LLM": "使用 LLM", "Use no proxy to fetch page contents.": "不使用代理擷取頁面內容。", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "使用 http_proxy 和 https_proxy 環境變數指定的代理擷取頁面內容。", + "Use Web Search?": "", "user": "使用者", "User": "使用者", + "User Access": "", "User Activity": "使用者動態", "User Groups": "使用者群組", "User location successfully retrieved.": "成功取得使用者位置。", @@ -2227,6 +2399,7 @@ "User Status": "使用者狀態", "User Webhooks": "使用者 Webhooks", "Username": "使用者名稱", + "Username Claim": "", "users": "使用者", "Users": "使用者", "Uses DefaultAzureCredential to authenticate": "使用 DefaultAzureCredential 進行身份驗證", @@ -2240,6 +2413,7 @@ "Valves updated": "設定項目已更新", "Valves updated successfully": "設定項目成功更新", "variable": "變數", + "Vector Field": "", "Verify Connection": "驗證連線", "Verify SSL Certificate": "驗證 SSL 憑證", "Version": "版本", @@ -2269,11 +2443,14 @@ "Web API": "網頁 API", "Web Loader Engine": "網頁載入引擎", "Web Search": "網頁搜尋", + "Web Search Confirmation": "", + "Web Search Confirmation Content": "", "Web Search Engine": "網頁搜尋引擎", "Web Search in Chat": "在對話中進行網頁搜尋", "Web Search Query Generation": "網頁搜尋查詢生成", + "Webhook deleted": "", "Webhook Name": "Webhook 名稱", - "Webhook URL": "Webhook URL", + "Webhook saved": "", "Webhooks": "Webhook", "Webpage URLs": "網頁連結", "WebUI Settings": "WebUI 設定", @@ -2316,6 +2493,7 @@ "Yandex Web Search API Key": "Yandex 網頁搜尋 API 金鑰", "Yandex Web Search config": "Yandex 網頁搜尋設定", "Yandex Web Search URL": "Yandex 網頁搜尋網址", + "Yearly": "", "Yesterday": "昨天", "Yesterday at {{LOCALIZED_TIME}}": "昨天 {{LOCALIZED_TIME}}", "You": "您", @@ -2345,6 +2523,7 @@ "Your browser does not support the video tag.": "您的瀏覽器不支援影片播放。", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的所有貢獻將會直接交給外掛開發者;Open WebUI 不會收取任何抽成。然而,所選擇的贊助平臺可能有其自身的費用。", "Your message text or inputs": "您的訊息文字或輸入", + "Your query will be sent to the configured web search provider.": "", "Your usage stats have been successfully synced.": "已成功同步您的使用統計資料。", "YouTube": "YouTube", "Youtube Language": "YouTube 語言", diff --git a/src/lib/pyodide/createPyodideWorker.ts b/src/lib/pyodide/createPyodideWorker.ts new file mode 100644 index 0000000000..de711c424c --- /dev/null +++ b/src/lib/pyodide/createPyodideWorker.ts @@ -0,0 +1,10 @@ +import { get } from 'svelte/store'; + +import { config } from '$lib/stores'; +import { PyodideSandboxHost } from '$lib/pyodide/pyodideSandboxHost'; +import PyodideWorker from '$lib/workers/pyodide.worker?worker'; + +export const createPyodideWorker = (): Worker => + get(config)?.features?.enable_pyodide_file_persistence + ? new PyodideWorker() + : (new PyodideSandboxHost() as unknown as Worker); diff --git a/src/lib/pyodide/pyodideKernel.ts b/src/lib/pyodide/pyodideKernel.ts deleted file mode 100644 index bd3eaeb77f..0000000000 --- a/src/lib/pyodide/pyodideKernel.ts +++ /dev/null @@ -1,81 +0,0 @@ -import PyodideWorker from '$lib/pyodide/pyodideKernel.worker?worker'; - -export type CellState = { - id: string; - status: 'idle' | 'running' | 'completed' | 'error'; - result: any; - stdout: string; - stderr: string; -}; - -export class PyodideKernel { - private worker: Worker; - private listeners: Map void>; - - constructor() { - this.worker = new PyodideWorker(); - this.listeners = new Map(); - - // Listen to messages from the worker - this.worker.onmessage = (event) => { - const { type, id, ...data } = event.data; - - if ((type === 'stdout' || type === 'stderr') && this.listeners.has(id)) { - this.listeners.get(id)?.({ type, id, ...data }); - } else if (type === 'result' && this.listeners.has(id)) { - this.listeners.get(id)?.({ type, id, ...data }); - // Remove the listener once the result is delivered - this.listeners.delete(id); - } else if (type === 'kernelState') { - this.listeners.forEach((listener) => listener({ type, ...data })); - } - }; - - // Initialize the worker - this.worker.postMessage({ type: 'initialize' }); - } - - async execute(id: string, code: string): Promise { - return new Promise((resolve, reject) => { - // Set up the listener for streaming and execution result - const state: CellState = { - id, - status: 'running', - result: null, - stdout: '', - stderr: '' - }; - - this.listeners.set(id, (data) => { - if (data.type === 'stdout') { - state.stdout += data.message; - } else if (data.type === 'stderr') { - state.stderr += data.message; - } else if (data.type === 'result') { - // Final result - const { state: finalState } = data; - resolve(finalState); - } - }); - - // Send execute request to the worker - this.worker.postMessage({ type: 'execute', id, code }); - }); - } - - async getState() { - return new Promise>((resolve) => { - this.worker.postMessage({ type: 'getState' }); - this.listeners.set('kernelState', (data) => { - if (data.type === 'kernelState') { - resolve(data.state); - } - }); - }); - } - - terminate() { - this.worker.postMessage({ type: 'terminate' }); - this.worker.terminate(); - } -} diff --git a/src/lib/pyodide/pyodideKernel.worker.ts b/src/lib/pyodide/pyodideKernel.worker.ts deleted file mode 100644 index 4f1eea6da0..0000000000 --- a/src/lib/pyodide/pyodideKernel.worker.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { loadPyodide, type PyodideInterface } from 'pyodide'; - -declare global { - interface Window { - stdout: string | null; - stderr: string | null; - pyodide: PyodideInterface; - cells: Record; - indexURL: string; - } -} - -type CellState = { - id: string; - status: 'idle' | 'running' | 'completed' | 'error'; - result: any; - stdout: string; - stderr: string; -}; - -const initializePyodide = async () => { - // Ensure Pyodide is loaded once and cached in the worker's global scope - if (!self.pyodide) { - self.indexURL = '/pyodide/'; - self.stdout = ''; - self.stderr = ''; - self.cells = {}; - - self.pyodide = await loadPyodide({ - indexURL: self.indexURL - }); - } -}; - -const executeCode = async (id: string, code: string) => { - if (!self.pyodide) { - await initializePyodide(); - } - - // Update the cell state to "running" - self.cells[id] = { - id, - status: 'running', - result: null, - stdout: '', - stderr: '' - }; - - // Redirect stdout/stderr to stream updates - self.pyodide.setStdout({ - batched: (msg: string) => { - self.cells[id].stdout += msg; - self.postMessage({ type: 'stdout', id, message: msg }); - } - }); - self.pyodide.setStderr({ - batched: (msg: string) => { - self.cells[id].stderr += msg; - self.postMessage({ type: 'stderr', id, message: msg }); - } - }); - - try { - // Dynamically load required packages based on imports in the Python code - await self.pyodide.loadPackagesFromImports(code, { - messageCallback: (msg: string) => { - self.postMessage({ type: 'stdout', id, package: true, message: `[package] ${msg}` }); - }, - errorCallback: (msg: string) => { - self.postMessage({ type: 'stderr', id, package: true, message: `[package] ${msg}` }); - } - }); - - // Execute the Python code - const result = await self.pyodide.runPythonAsync(code); - self.cells[id].result = result; - self.cells[id].status = 'completed'; - } catch (error) { - self.cells[id].status = 'error'; - self.cells[id].stderr += `\n${error.toString()}`; - } finally { - // Notify parent thread when execution completes - self.postMessage({ - type: 'result', - id, - state: self.cells[id] - }); - } -}; - -// Handle messages from the main thread -self.onmessage = async (event) => { - const { type, id, code, ...args } = event.data; - - switch (type) { - case 'initialize': - await initializePyodide(); - self.postMessage({ type: 'initialized' }); - break; - - case 'execute': - if (id && code) { - await executeCode(id, code); - } - break; - - case 'getState': - self.postMessage({ - type: 'kernelState', - state: self.cells - }); - break; - - case 'terminate': - // Explicitly clear the worker for cleanup - for (const key in self.cells) delete self.cells[key]; - self.close(); - break; - - default: - console.error(`Unknown message type: ${type}`); - } -}; diff --git a/src/lib/pyodide/pyodideSandboxHost.ts b/src/lib/pyodide/pyodideSandboxHost.ts new file mode 100644 index 0000000000..33c9c6451a --- /dev/null +++ b/src/lib/pyodide/pyodideSandboxHost.ts @@ -0,0 +1,280 @@ +type MessageListener = (event: MessageEvent) => void; +type ErrorListener = (event: Event) => void; +type QueuedMessage = { message: unknown; transfer: Transferable[] }; + +const sandboxScript = String.raw` +(function () { + let pyodide = null; + let pyodideReady = null; + let stdout = null; + let stderr = null; + + function post(message, transfer) { + parent.postMessage(message, '*', transfer || []); + } + + async function loadRuntime(packages) { + stdout = null; + stderr = null; + pyodide = await loadPyodide({ + indexURL: '/pyodide/', + stdout: function (text) { + stdout = stdout ? stdout + text + '\n' : text + '\n'; + }, + stderr: function (text) { + stderr = stderr ? stderr + text + '\n' : text + '\n'; + }, + packages: ['micropip'] + }); + pyodide.FS.mkdirTree('/mnt/uploads'); + await pyodide.pyimport('micropip').install(packages || []); + } + + async function ensureRuntime(packages) { + if (!pyodideReady) pyodideReady = loadRuntime(packages || []); + await pyodideReady; + if (packages && packages.length > 0) { + await pyodide.pyimport('micropip').install(packages); + } + } + + function ensureDir(dir) { + try { + pyodide.FS.stat(dir); + } catch { + pyodide.FS.mkdirTree(dir); + } + } + + function upload(files, dir) { + dir = dir || '/mnt/uploads'; + ensureDir(dir); + for (const file of files || []) { + pyodide.FS.writeFile(dir + '/' + file.name, new Uint8Array(file.data)); + } + } + + function list(path) { + const entries = []; + try { + const names = pyodide.FS.readdir(path).filter(function (name) { + return name !== '.' && name !== '..'; + }); + for (const name of names) { + try { + const stat = pyodide.FS.stat(path + '/' + name); + const isDir = pyodide.FS.isDir(stat.mode); + entries.push({ name: name, type: isDir ? 'directory' : 'file', size: isDir ? 0 : stat.size }); + } catch {} + } + } catch {} + return entries; + } + + function remove(path) { + try { + const stat = pyodide.FS.stat(path); + if (!pyodide.FS.isDir(stat.mode)) { + pyodide.FS.unlink(path); + return; + } + const names = pyodide.FS.readdir(path).filter(function (name) { + return name !== '.' && name !== '..'; + }); + for (const name of names) remove(path + '/' + name); + pyodide.FS.rmdir(path); + } catch {} + } + + function clean(value) { + try { + if (value == null) return null; + if (['string', 'number', 'boolean'].includes(typeof value)) return value; + if (typeof value === 'bigint') return value.toString(); + if (Array.isArray(value)) return value.map(clean); + if (typeof value.toJs === 'function') return clean(value.toJs()); + if (typeof value === 'object') { + const out = {}; + for (const key in value) { + if (Object.prototype.hasOwnProperty.call(value, key)) out[key] = clean(value[key]); + } + return out; + } + return JSON.stringify(value); + } catch (error) { + return '[processResult error]: ' + (error && error.message ? error.message : String(error)); + } + } + + async function patchMatplotlib() { + await pyodide.runPythonAsync([ + 'import base64', + 'import os', + 'from io import BytesIO', + 'os.environ["MPLBACKEND"] = "AGG"', + 'import matplotlib.pyplot', + '_old_show = matplotlib.pyplot.show', + 'assert _old_show, "matplotlib.pyplot.show"', + 'def show(*, block=None):', + '\\tbuf = BytesIO()', + '\\tmatplotlib.pyplot.savefig(buf, format="png")', + '\\tbuf.seek(0)', + '\\timg_str = base64.b64encode(buf.read()).decode("utf-8")', + '\\tmatplotlib.pyplot.clf()', + '\\tbuf.close()', + '\\tprint(f"data:image/png;base64,{img_str}")', + 'matplotlib.pyplot.show = show' + ].join('\n')); + } + + async function execute(id, code, files) { + stdout = null; + stderr = null; + let result = null; + if (files && files.length > 0) upload(files); + try { + if (code.includes('matplotlib')) await patchMatplotlib(); + result = clean(await pyodide.runPythonAsync(code)); + } catch (error) { + stderr = error && error.message ? error.message : String(error); + } + post({ id: id, result: result, stdout: stdout, stderr: stderr }); + } + + window.addEventListener('message', async function (event) { + if (event.source !== parent) return; + const data = event.data || {}; + const id = data.id; + if (!data.type || data.type === 'execute') { + await ensureRuntime(data.packages || []); + await execute(id, data.code, data.files); + return; + } + await ensureRuntime(); + switch (data.type) { + case 'fs:upload': + upload(data.files, data.dir); + post({ id: id, type: data.type, success: true }); + break; + case 'fs:list': + post({ id: id, type: data.type, entries: list(data.path) }); + break; + case 'fs:read': + try { + const buffer = pyodide.FS.readFile(data.path).buffer; + post({ id: id, type: data.type, data: buffer }, [buffer]); + } catch (error) { + post({ id: id, type: data.type, error: error && error.message ? error.message : String(error) }); + } + break; + case 'fs:delete': + remove(data.path); + post({ id: id, type: data.type, success: true }); + break; + case 'fs:mkdir': + pyodide.FS.mkdirTree(data.path); + post({ id: id, type: data.type, success: true }); + break; + case 'fs:sync': + post({ id: id, type: data.type, success: true }); + break; + } + }); +})(); +`; + +const sandboxHtml = ``; + +export class PyodideSandboxHost { + onmessage: MessageListener | null = null; + onerror: ErrorListener | null = null; + + private iframe: HTMLIFrameElement; + private ready = false; + private queue: QueuedMessage[] = []; + private messageListeners = new Set(); + private errorListeners = new Set(); + private onWindowMessage: (event: MessageEvent) => void; + private onIframeLoad: () => void; + private onIframeError: (event: Event) => void; + + constructor() { + this.iframe = document.createElement('iframe'); + this.iframe.setAttribute('sandbox', 'allow-scripts'); + this.iframe.setAttribute('aria-hidden', 'true'); + this.iframe.setAttribute('title', 'pyodide-sandbox'); + this.iframe.style.display = 'none'; + this.iframe.srcdoc = sandboxHtml; + + this.onWindowMessage = (event: MessageEvent) => { + if (event.source !== this.iframe.contentWindow) { + return; + } + + const messageEvent = { data: event.data } as MessageEvent; + this.onmessage?.(messageEvent); + for (const listener of this.messageListeners) { + listener(messageEvent); + } + }; + + this.onIframeLoad = () => { + this.ready = true; + for (const item of this.queue) { + this.post(item.message, item.transfer); + } + this.queue = []; + }; + + this.onIframeError = (event: Event) => { + this.onerror?.(event); + for (const listener of this.errorListeners) { + listener(event); + } + }; + + window.addEventListener('message', this.onWindowMessage); + this.iframe.addEventListener('load', this.onIframeLoad, { once: true }); + this.iframe.addEventListener('error', this.onIframeError); + document.body.appendChild(this.iframe); + } + + postMessage(message: unknown, transfer: Transferable[] = []) { + if (this.ready) { + this.post(message, transfer); + } else { + this.queue.push({ message, transfer }); + } + } + + addEventListener(type: 'message' | 'error', listener: MessageListener | ErrorListener) { + if (type === 'message') { + this.messageListeners.add(listener as MessageListener); + } else if (type === 'error') { + this.errorListeners.add(listener as ErrorListener); + } + } + + removeEventListener(type: 'message' | 'error', listener: MessageListener | ErrorListener) { + if (type === 'message') { + this.messageListeners.delete(listener as MessageListener); + } else if (type === 'error') { + this.errorListeners.delete(listener as ErrorListener); + } + } + + terminate() { + window.removeEventListener('message', this.onWindowMessage); + this.iframe.removeEventListener('load', this.onIframeLoad); + this.iframe.removeEventListener('error', this.onIframeError); + this.messageListeners.clear(); + this.errorListeners.clear(); + this.onmessage = null; + this.onerror = null; + this.iframe.remove(); + } + + private post(message: unknown, transfer: Transferable[]) { + this.iframe.contentWindow?.postMessage(message, '*', transfer); + } +} diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts index b87303c0b0..07df7a3736 100644 --- a/src/lib/stores/index.ts +++ b/src/lib/stores/index.ts @@ -213,6 +213,7 @@ type Settings = { iframeSandboxAllowForms?: boolean; iframeSandboxAllowSameOrigin?: boolean; scrollOnBranchChange?: boolean; + showFilesOnTerminalSelect?: boolean; directConnections?: null; chatBubble?: boolean; copyFormatted?: boolean; @@ -234,6 +235,7 @@ type Settings = { renderMarkdownInAssistantMessages?: boolean; recentEmojis?: string[]; pinnedMenuItems?: string[]; + pinnedNotesOrder?: string[]; system?: string; seed?: number; @@ -290,6 +292,8 @@ type Config = { enable_signup: boolean; enable_login_form: boolean; enable_web_search?: boolean; + enable_web_search_confirmation?: boolean; + web_search_confirmation_content?: string; enable_google_drive_integration: boolean; enable_onedrive_integration: boolean; enable_image_generation: boolean; @@ -301,6 +305,7 @@ type Config = { enable_autocomplete_generation: boolean; enable_direct_connections: boolean; enable_version_update_check: boolean; + enable_pyodide_file_persistence?: boolean; folder_max_file_count?: number; }; oauth: { diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 28f9682373..5a6eb64a36 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -254,6 +254,23 @@ export const sanitizeHistory = (history) => { } } + // Recover currentId before role reconstruction can make a malformed node + // look valid. + const currentMessage = history.messages?.[history.currentId]; + if (!currentMessage?.id || !currentMessage?.role) { + let latestLeafId = null; + let latestTimestamp = -1; + + for (const [id, message] of Object.entries(history.messages)) { + if (message.childrenIds.length === 0 && (message.timestamp ?? 0) > latestTimestamp) { + latestLeafId = id; + latestTimestamp = message.timestamp ?? 0; + } + } + + history.currentId = latestLeafId ?? Object.keys(history.messages)[0] ?? null; + } + // Reconstruct missing parentId and role for (const [id, message] of Object.entries(history.messages)) { // Well-formed: has role and explicit parentId (null is valid for root) @@ -280,20 +297,6 @@ export const sanitizeHistory = (history) => { for (const message of Object.values(history.messages)) { message.childrenIds = message.childrenIds.filter((childId) => history.messages[childId]); } - - // Recover currentId if it points to a missing or incomplete node - const currentMessage = history.messages?.[history.currentId]; - if (!currentMessage?.id || !currentMessage?.role) { - let latestLeafId = null; - let latestTimestamp = -1; - for (const [id, message] of Object.entries(history.messages)) { - if (message.childrenIds.length === 0 && (message.timestamp ?? 0) > latestTimestamp) { - latestLeafId = id; - latestTimestamp = message.timestamp ?? 0; - } - } - history.currentId = latestLeafId ?? Object.keys(history.messages)[0] ?? null; - } }; export const getGravatarURL = (email) => { @@ -1927,7 +1930,8 @@ export const initMermaid = async () => { mermaid.initialize({ startOnLoad: false, // Should be false when using render API theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default', - securityLevel: 'loose' + securityLevel: 'loose', + htmlLabels: false }); return mermaid; }; @@ -1999,11 +2003,23 @@ export const renderMermaidDiagram = async ( } }; -export const renderVegaVisualization = async (spec: string, i18n?: any) => { +export const renderVegaVisualization = async (spec: string, lang: string = '', i18n?: any) => { const vega = await import('vega'); const parsedSpec = JSON.parse(spec); + const hasVegaLiteKeys = + 'mark' in parsedSpec || + 'encoding' in parsedSpec || + 'layer' in parsedSpec || + 'hconcat' in parsedSpec || + 'vconcat' in parsedSpec || + 'repeat' in parsedSpec || + 'facet' in parsedSpec; + const isVegaLite = + lang === 'vega-lite' || + (parsedSpec.$schema && parsedSpec.$schema.includes('vega-lite')) || + hasVegaLiteKeys; let vegaSpec = parsedSpec; - if (parsedSpec.$schema && parsedSpec.$schema.includes('vega-lite')) { + if (isVegaLite) { const vegaLite = await import('vega-lite'); vegaSpec = vegaLite.compile(parsedSpec).spec; } diff --git a/src/lib/utils/marked/katex-extension.ts b/src/lib/utils/marked/katex-extension.ts index a890ff4135..073ee581d5 100644 --- a/src/lib/utils/marked/katex-extension.ts +++ b/src/lib/utils/marked/katex-extension.ts @@ -72,14 +72,19 @@ const isAllowedTrailing = (src: string, i: number): boolean => const isBlockBoundary = (src: string, i: number): boolean => /^(?:[ \t]*\r?\n|$)/.test(src.slice(i)); -const findClosingDelimiter = (src: string, i: number): number => - i >= src.length - 1 - ? -1 - : src[i] === '\\' - ? findClosingDelimiter(src, i + 2) - : src[i] === '$' && src[i + 1] === '$' - ? i - : findClosingDelimiter(src, i + 1); +const findClosingDelimiter = (src: string, i: number): number => { + const len = src.length - 1; + while (i < len) { + if (src[i] === '\\') { + i += 2; + } else if (src[i] === '$' && src[i + 1] === '$') { + return i; + } else { + i++; + } + } + return -1; +}; export const tokenizeDisplayMath = ( src: string, diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 772ae6fe2d..24ffc017dd 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -14,6 +14,7 @@ import { getBanners } from '$lib/apis/configs'; import { getTerminalServers } from '$lib/apis/terminal'; import { getUserSettings } from '$lib/apis/users'; + import { setTextScale } from '$lib/utils/text-scale'; import { WEBUI_VERSION, WEBUI_API_BASE_URL } from '$lib/constants'; import { compareVersion } from '$lib/utils'; @@ -86,7 +87,7 @@ } }; - const setUserSettings = async (cb: () => Promise) => { + const setUserSettings = async (cb?: () => Promise) => { let userSettings = await getUserSettings(localStorage.token).catch((error) => { console.error(error); return null; @@ -105,6 +106,8 @@ settings.set(userSettings.ui); } + setTextScale($settings?.textScale ?? 1); + if (cb) { await cb(); } @@ -206,14 +209,15 @@ checkLocalDBChats(), setBanners().catch((e) => console.error('Failed to load banners:', e)), setTools().catch((e) => console.error('Failed to load tools:', e)), - setUserSettings(async () => { - await Promise.all([ - setModels().catch((e) => console.error('Failed to load models:', e)), - setToolServers().catch((e) => console.error('Failed to load tool servers:', e)) - ]); - }).catch((e) => console.error('Failed to load user settings:', e)) + setUserSettings().catch((e) => console.error('Failed to load user settings:', e)) ]); + // Load models and tool servers in the background — don't block page render. + // These contact external services (Ollama, OpenAI, tool servers, terminal + // servers) that may be slow or unreachable. + setModels().catch((e) => console.error('Failed to load models:', e)); + setToolServers().catch((e) => console.error('Failed to load tool servers:', e)); + // Helper function to check if the pressed keys match the shortcut definition const isShortcutMatch = (event: KeyboardEvent, shortcut): boolean => { const keys = shortcut?.keys || []; diff --git a/src/routes/(app)/admin/evaluations/+page.svelte b/src/routes/(app)/admin/evaluations/+page.svelte index 176e3162f8..b0c6ca903c 100644 --- a/src/routes/(app)/admin/evaluations/+page.svelte +++ b/src/routes/(app)/admin/evaluations/+page.svelte @@ -2,11 +2,7 @@ import { goto } from '$app/navigation'; import { onMount } from 'svelte'; - import Evaluations from '$lib/components/admin/Evaluations.svelte'; - onMount(() => { goto('/admin/evaluations/leaderboard'); }); - - diff --git a/src/routes/(app)/admin/settings/+page.svelte b/src/routes/(app)/admin/settings/+page.svelte index d8a497cb24..2ebe22b6b1 100644 --- a/src/routes/(app)/admin/settings/+page.svelte +++ b/src/routes/(app)/admin/settings/+page.svelte @@ -1,11 +1,8 @@ - - diff --git a/src/routes/(app)/automations/+page.svelte b/src/routes/(app)/automations/+page.svelte index 0fef27bd3e..d810ca107c 100644 --- a/src/routes/(app)/automations/+page.svelte +++ b/src/routes/(app)/automations/+page.svelte @@ -40,6 +40,7 @@ let loading = false; let showCreateModal = false; + let cloneFrom: AutomationResponse | null = null; let showDeleteConfirm = false; let deleteTarget: AutomationResponse | null = null; @@ -50,21 +51,29 @@ let page = 1; - // Debounce only query changes (gate behind loaded to prevent double-fetch on mount) - $: if (loaded && query !== undefined) { + const handleSearchInput = () => { + if (!loaded) return; + loading = true; clearTimeout(searchDebounceTimer); searchDebounceTimer = setTimeout(() => { - page = 1; - getAutomationList(); + if (page !== 1) { + page = 1; + } else { + getAutomationList(); + } }, 300); - } + }; // Immediate response to page/filter changes (gate behind loaded) $: if (loaded && page && statusFilter !== undefined) { getAutomationList(); } + $: if (!showCreateModal) { + cloneFrom = null; + } + const getAutomationList = async () => { if (!loaded) return; @@ -139,6 +148,14 @@ getAutomationList(); }; + const cloneHandler = (automation: AutomationResponse) => { + cloneFrom = { + ...automation, + name: `${automation.name} (Clone)` + }; + showCreateModal = true; + }; + const formatRRule = (rrule: string): string => { // Detect one-time schedule (ONCE) if (rrule.includes('COUNT=1')) { @@ -195,8 +212,6 @@ } loaded = true; - // Explicit initial fetch — reactive blocks will handle subsequent changes - await getAutomationList(); return () => { clearTimeout(searchDebounceTimer); @@ -227,6 +242,7 @@ { getAutomationList(); if (e.detail?.id) { @@ -273,6 +289,7 @@