Ten strings were still untranslated in de-DE, so German users saw raw English keys in the settings sidebar and in the interface settings. The settings group headings (Basics, Services, Preferences, Data, AI, Quality, Experience) all rendered in English above otherwise German tab names, plus the font family label and its description, and the multi-file upload failure toast in a knowledge base.
All ten now have German values, chosen to match the terminology the catalog already uses: AI as KI, Services as Dienste (matching Dienstkonto and the existing service endpoint strings), Interface as Benutzeroberfläche in the font description, and the third-person descriptive voice the neighbouring setting descriptions use. Experience is rendered as Benutzererlebnis rather than Darstellung because that group covers audio as well as interface and images. Both interpolation placeholders in the upload toast are preserved.
Only de-DE is touched. No key was added, removed or reordered, and no already-translated string was changed. The catalog now has no empty values left.
Fills the 917 empty strings in the es-ES locale and repairs 94 existing
entries that rendered incorrectly. No keys are added or removed, and the
terminology chosen by the Spanish community is preserved throughout: new
strings reuse the glossary already present in the file.
Filled strings:
- Reuse existing renderings so each English term keeps one Spanish form
(chunk -> Fragmento, knowledge base -> Base de Conocimiento,
workspace -> Espacio de Trabajo, skill -> Habilidad).
- Include the settings sidebar group headers added in 006f95ee5
(Basics, Services, Preferences, Data, AI, Quality, Experience), which
were otherwise falling back to English in the settings modal.
- Add real grammatical plural forms for every one/many/other variant.
Spanish requires the `many` CLDR category, which English does not have.
- Preserve every {{placeholder}}, backtick, URL, HTML tag and CLI flag.
Repaired strings:
- 4 broken interpolations, including "Deleted {{name}}", whose placeholder
had itself been translated to {{nombre}} and so rendered literally.
- 6 plural groups whose values carried the i18next key suffix as visible
text (e.g. "{{count}} seleccionados_únicos"), and one where "_one" had
been translated as the adjective "únicas".
- "Reset" now reads Restablecer rather than Reiniciar ("restart"), which
misdescribed destructive actions such as Reset Vector Storage/Knowledge.
- "Access" (Acceso) separated from "Permissions" (Permisos); the *Access
family was previously split between the two.
- "Chats Public Sharing" and "Chats Open Sharing" no longer render
identically in the group permissions panel.
- "You" corrected to "Tú"; unaccented "Tu" is the possessive "your", and
this string labels every user message bubble.
- "Channels" corrected from the singular "Canal".
- ~49 misspellings and missing accents (Conexxión, Interprete, Publicamente,
Busqueda, Incrustración, Añador, Wev, actualiada, mantentrá).
Verified: 0 empty strings, key set identical to dev, 0 placeholder
mismatches, prettier --check passes, and all strings render correctly
through i18next 23.16.8 using the application's own options.
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
The settings navigation group labels added in 006f95ee5 (Basics,
Services, Preferences, Data, Experience, AI, Quality) were left
empty in every locale, so ru-RU and uk-UA fell back to the English
key text. Fill them for both locales.
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Fill all remaining untranslated strings so both locales reach full
coverage:
- ru-RU: 967 strings translated
- uk-UA: 2110 strings translated
ru-RU also aligns terminology with the existing translations
(webhook -> вебхук, sub-agent -> субагент, reranker -> реранкер,
chunk -> чанк, parsing -> розбір/разбор) and standardizes "web search"
to «Поисковая система» across the whole file.
Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* perf: stop scanning every socket.io payload for binary data
Every socket.io event the backend sends was first walked recursively to check whether any value was a bytes object needing binary attachment framing. Open WebUI never emits binary, so the walk always came back empty and the work was thrown away. It has no early exit and allocates at every level, so it scaled with the full size of the message, and the messages are the big ones: chat streaming re-emits the whole assistant message on every update, note collaboration sends document state as a JSON array with one entry per byte. With the Redis manager it ran once per instance per emit on top of that, since every instance builds its own copy of the packet.
The server now installs a Packet subclass with binary events off, through python-socketio's own serializer hook, the same mechanism its msgpack serializer uses. Inbound binary attachments are decoded to int lists rather than refused, so the one frontend path that sends a raw Uint8Array keeps working and handlers can still echo client data straight back out. One scan remains in multi-instance setups: python-socketio's Redis manager calls it on the base Packet class directly, where the serializer hook cannot reach.
Measured per encode:
| payload | before | after |
|---|---|---|
| chat completion re-emit (7.5 KB JSON) | 30 us | 13 us |
| collaborative document state (292 KB JSON) | 9.0 ms | 1.7 ms |
With ENABLE_ORJSON=true, where the scan is nearly the whole encode cost: 20 us to 2.3 us, and 7.8 ms to 0.14 ms.
Closes#28164
* fix: match the other Yjs emits and send the full state as an array
Collaboration.ts sent the initial full-document state as a raw Uint8Array while the other two Yjs emit sites convert with Array.from first. socket.io framed that one as a binary attachment, so with the JSON-only packet class the server turns it into a list of ints and re-broadcasts it as JSON: a 10240-byte state update becomes 36561 JSON characters. Converting at the emit site keeps the wire form uniform across all three sites.
Also trims the JSONOnlyPacket docstring, which claimed attachments already arrive as int lists when the override is what converts them, and annotates the new reconstruct_binary parameters.
Loading an automation whose rule the visual controls cannot represent switched the schedule to Custom but left the bookkeeping the seeding block reads on the previous value, so that block immediately replaced the rule with a freshly built default. The rule was lost when the editor opened, before anything was saved, and cloning carried the default across as well. Recording the switch alongside it leaves the stored rule in place.
Verified in a browser against the same build without this line: a minutely rule and a yearly rule now survive reopen and save byte for byte, cloning keeps the original, and every schedule the editor itself produces, along with switching to Custom by hand, behaves exactly as before.
* fix: surface files the browser cannot read during a knowledge base directory sync
Syncing a local folder into a knowledge base could fail with nothing but "Error accessing directory": no failing file name, no network request, no server log, and no console output either, because production builds strip console.error. On Windows this happens once the absolute path of a file passes the platform limit, at which point the browser refuses to open a file it just listed.
The directory scan now handles that per file. It names the first failing path and how many files are affected, and stops before anything is uploaded. Stopping is the point: a file missing from the manifest is treated as deleted by the sync, so continuing would remove the knowledge base copy of a file that still exists on disk.
Dragging a folder in hit the same failure and reported nothing at all, and the Firefox picker path returned its promise without awaiting it, so a rejection escaped the error handler and surfaced only as an unhandled rejection. Both report through the existing handler now, and production builds keep console.error so the underlying exception stays visible.
* fix: narrow the change to the silent drag-and-drop folder failure
Dropping a folder onto a knowledge base did nothing at all when the browser refused to open one of the files inside it: the rejection escaped the async drop listener, so the user got no toast, no upload and no clue why. The listener now routes that failure through the same error handler the directory picker already uses, so one path and one message cover both ways of adding a folder.
The rest of the branch is reverted. Dropping `console.error` from the esbuild `pure` list un-stripped 597 call sites across 103 files from every production bundle, which is a repo-wide logging policy change that needs its own argument. The picker-side collect-and-count machinery only reworded a toast the existing catch already showed, and the Firefox `return await` fix is a different bug in a different path.
* fix: stop labelling a counted schedule as a one-off
The schedule label treated any rule whose text contained COUNT=1 as a single run, so counts such as 10, 12 and 14 were shown as "Once" together with the date of the first run, on the automations list and on the automation page alike. The label now matches a count of exactly one.
This covers the two places that render the label. The schedule editor reads the count the same way and changes separately. Rules that carry a start date still fall through to the raw rule text, exactly as they already did without a count; that parsing gap changes separately too.
Verified in a browser against the same build without these lines: ten ordinary schedules render identically in both places, and a genuine single-run schedule is still labelled as one.
* fix: stop counted schedules being rewritten as one-offs on save
The schedule editor decides that a rule is a one-off by looking for the text COUNT=1 anywhere in it. A rule that runs ten times carries COUNT=10, which contains that text, so opening such an automation shows it as a single run and saving writes a genuine one-off rule back. One open and save is enough to silently turn a ten run schedule into a one run schedule, with whatever date happened to sit in the rule. The check now requires that no further digit follows, the same test the two schedule labels already use.
The same screens also failed to read counted rules at all. Both label helpers and the editor parser split the stored rule on semicolons after stripping the RRULE prefix, so when the rule carries a DTSTART line the first piece is that whole line and the frequency is never found. The automations list then printed the raw rule text where a human label belongs, and the editor fell back to a plain daily schedule, quietly discarding the weekly or monthly settings on the next save. All three sites now drop the DTSTART part before splitting. They split on whitespace, so the newline form and the space separated form are both handled, matching how the backend already strips it.
New **pt-BR** translations for items introduced in the latest releases, plus a consistency/quality pass across existing strings (grammar, tone, capitalization, pluralization). Placeholders and hotkeys preserved. No logic changes.