From a9d72ee4cf5406b4caf51ddeb0765525da0d9cb1 Mon Sep 17 00:00:00 2001 From: qnbs <155236708+qnbs@users.noreply.github.com> Date: Sun, 26 Jul 2026 09:46:29 +0200 Subject: [PATCH 01/14] docs: ADR-0012 + LOCAL-AI root-cause & desktop local-server guide (#266) Root-cause analysis for Ollama/LM Studio/vLLM discovery on Tauri and the PWA CORS noise: WebView fetch to localhost is cross-origin (CORS/PNA), CSP was never the blocker. Decision: route local-server HTTP through the Tauri HTTP plugin; PWA stays strictly desktop-only. Help articles updated (Tauri desktop, provider FAQ). --- docs/LOCAL-AI.md | 39 ++++++- ...12-local-server-connectivity-tauri-http.md | 102 ++++++++++++++++++ locales/en/help.json | 4 +- 3 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 docs/adr/0012-local-server-connectivity-tauri-http.md diff --git a/docs/LOCAL-AI.md b/docs/LOCAL-AI.md index 633c0709..39be09a0 100644 --- a/docs/LOCAL-AI.md +++ b/docs/LOCAL-AI.md @@ -93,7 +93,41 @@ fallback. In **Local** and **Eco** modes, only the on-device chain is used. removes them. Different browsers do not share downloads. - **Desktop (Tauri):** the same WebGPU/WASM runtimes apply; downloads live in the app's WebView storage. For server-grade local models, point the **Ollama** provider at a local - server instead (Settings → AI Models → AI → Advanced). + server instead (Settings → AI Models → AI → Advanced) — see the next section. + +--- + +## Ollama / LM Studio / vLLM servers (desktop only) + +For server-grade local models, WorldScript Studio talks to a **local inference server** over +HTTP instead of running the model in the WebView: + +| Server | Default URL | Notes | +|---|---|---| +| **Ollama** | `http://localhost:11434` | `ollama serve`; models via the Models list or `ollama pull` | +| **LM Studio** | `http://localhost:1234` | Enable the local server in LM Studio (Developer tab) | +| **vLLM** | `http://localhost:8000` | Any OpenAI-compatible `/v1` server works | + +Setup: **Settings → AI Models → AI → Advanced**, pick the **Ollama** provider, choose a preset +(or enter a custom base URL), then press **Scan common local ports**. Every endpoint gets a +live status badge (reachable / no response / timeout / HTTP error); a reachable server offers a +one-click **Use this URL** action. + +### Why this only works in the desktop app + +- **Desktop (Tauri):** all local-server traffic goes through the **Tauri HTTP plugin** (native + Rust networking), not the WebView's `fetch`. Native requests are not subject to browser CORS or + Private-Network-Access rules, so Ollama/LM Studio answer directly — **no `OLLAMA_ORIGINS` + configuration needed**. The Tauri capability scope is pinned to `localhost`/`127.0.0.1` + (`src-tauri/capabilities/default.json`); the CSP already lists the three well-known ports. +- **Web (PWA):** browsers treat `http://localhost:*` as cross-origin **and** as a private-network + target. Without server-side CORS headers (`OLLAMA_ORIGINS=…` including your PWA origin) every + request is blocked — this is a browser security boundary, not a bug. The PWA therefore shows a + banner with a link to the desktop download instead of probing your machine, and never fires + automatic localhost requests (no CORS noise in the console). + +See [ADR 0012](adr/0012-local-server-connectivity-tauri-http.md) for the full root-cause analysis +(issue #266). --- @@ -106,6 +140,9 @@ fallback. In **Local** and **Eco** modes, only the on-device chain is used. | "Another WorldScript tab holds the local inference lock" | Multi-tab GPU contention | Close other WorldScript tabs (only one tab loads the GPU model). | | Very slow generation | Low-end device / CPU fallback | Pick a smaller model or use **Eco** mode. | | Storage estimate unavailable | Browser without StorageManager | Informational only; downloads still work. | +| Ollama/LM Studio not detected (desktop) | Server not running, or custom port | Run `ollama serve` / start the LM Studio server; press **Scan common local ports**; check the base URL. | +| CORS errors mention `localhost:11434` (browser) | Ollama selected inside the PWA | Expected browser boundary — use the desktop app for local servers (see banner in Settings → AI). | +| Scan shows **timeout** | Server busy loading a model or firewall interference | Retry after the model finishes loading; check OS firewall for localhost. | The **Last local run: N tokens/sec** line under the fallback chain reflects the throughput of your most recent on-device generation — a quick way to compare models on your hardware. diff --git a/docs/adr/0012-local-server-connectivity-tauri-http.md b/docs/adr/0012-local-server-connectivity-tauri-http.md new file mode 100644 index 00000000..13accefa --- /dev/null +++ b/docs/adr/0012-local-server-connectivity-tauri-http.md @@ -0,0 +1,102 @@ +# ADR 0012 — Local AI server connectivity: route localhost HTTP through the Tauri HTTP plugin (web stays fetch) + +- **Status:** Accepted +- **Date:** 2026-07-25 +- **Deciders:** Maintainer + Kimi Code +- **Context tags:** ai, ollama, lm-studio, tauri, cors, csp, private-network-access +- **Fixes:** [#266](https://github.com/qnbs/WorldScript-Studio/issues/266) · extends [ADR 0004](0004-csp-connect-src-byok-tradeoff.md) + +## Context + +WorldScript Studio can use server-grade local models through the **Ollama** provider and can scan +for local OpenAI-compatible servers (Ollama `:11434`, LM Studio `:1234`, vLLM `:8000`). Two failure +modes were reported in #266: + +1. **Desktop build (.deb / Tauri) does not see Ollama or LM Studio even though both are running.** +2. **The installed PWA logs loud CORS errors against `localhost:11434` even when `OLLAMA_ORIGINS` + is configured.** + +### Root cause analysis + +- `services/ollamaService.ts` (`testOllamaConnection`, `listOllamaModels`, `streamOllama`, + `pullOllamaModel`) and `scanLocalOpenAiCompatibleEndpoints()` (`services/aiProviderService.ts`) + all used the **browser `fetch`** — including inside the Tauri WebView. +- The Tauri WebView origin is `http://tauri.localhost` (Linux/Windows) resp. `tauri://localhost` + (macOS). Requests to `http://localhost:11434` etc. are therefore **cross-origin**. Ollama sends + **no `Access-Control-Allow-Origin` header** unless the server is started with `OLLAMA_ORIGINS` + covering the WebView origin — the WebView then blocks the response (CORS). LM Studio and vLLM + behave similarly depending on their own CORS configuration. WebView2/WKWebView additionally apply + Private-Network-Access / mixed-content style restrictions to `localhost` targets. +- The Tauri CSP (`src-tauri/tauri.conf.json` `connect-src`) already listed all three ports for + `localhost` and `127.0.0.1`. **CSP was never the blocker — CORS was.** CSP can only *forbid* a + connection; it can never *permit* a cross-origin read that the server does not allow. +- In the PWA, `AiProviderCard`'s auto-effect fired `listOllamaModels()` **directly** (bypassing the + desktop-only guard inside `testAIConnection`) whenever the Ollama provider was selected. Each + settings visit produced CORS preflight failures in the console. `OLLAMA_ORIGINS` can silence this + only if the PWA origin is explicitly listed — but the browser path is desktop-only by policy + anyway, so auto-probing localhost from the PWA is simply wrong. +- `@tauri-apps/plugin-http` (JS) and `tauri-plugin-http` (Rust) were **already dependencies**, and + the `http:default` capability was already granted — but nothing on the Ollama path used them. The + plugin executes requests via the native Rust HTTP stack (reqwest), which is **not subject to + WebView CORS or PNA rules at all**. + +## Decision + +1. **Introduce a thin runtime-aware HTTP layer** (`services/localServerHttp.ts`): + - Under `isTauriRuntime()` (canonical `__TAURI_INTERNALS__`-aware detection, see + `services/tauriRuntime.ts`) it dynamically imports `@tauri-apps/plugin-http` and uses its + `fetch` — native, CORS-free. + - Otherwise it uses the global `fetch`. The dynamic import keeps the web bundle lean and + matches the existing `@tauri-apps/*` externalization for web builds. + - The layer owns base-URL normalization (trailing-slash strip, `localhost:11434` default), + timeout composition (`AbortSignal.timeout` merged with the caller's signal via + `AbortSignal.any`), and error classification (`unreachable` | `timeout` vs. user `AbortError`, + which is rethrown unchanged so cancel-vs-failure stays distinguishable). +2. **Route all local-server traffic through it:** all four `ollamaService` functions and + `scanLocalOpenAiCompatibleEndpoints()`. Public signatures and legacy error strings are preserved + so orchestration-layer contracts (single `onError` firing, AbortError propagation) are untouched. +3. **Classified scan results:** the scan returns a `state` (`ok` | `unreachable` | `timeout` | + `http`) plus the legacy numeric `status`, so the UI can render actionable badges instead of a + bare "no response". +4. **PWA stays strictly desktop-only** (product decision): no reachability probing from the + browser. The `AiProviderCard` auto-effect and model loading are gated on `isTauriRuntime()`, so + the PWA performs **zero** localhost requests — the CORS console noise disappears by + construction. Instead the PWA shows a quiet banner explaining the restriction plus a + "Download the desktop app" CTA. +5. **CSP stays unchanged.** The WebView CSP is bypassed for plugin-http traffic (native stack); + the web CSP keeps its explicit localhost entries for defense-in-depth documentation, and the + `https:` BYOK trade-off from ADR 0004 is unaffected. +6. **Capability scope is pinned explicitly** in `src-tauri/capabilities/default.json`. Audit finding + during this work: `http:default` alone grants **no URL scope at all** (the plugin's + `Scope::is_allowed` requires a matching allow entry), so every plugin-http call — including the + existing AI-SDK `fetchAdapter` cloud calls on desktop — was silently denied. The scope now + allows `http://localhost:*/*` + `http://127.0.0.1:*/*` (all three well-known ports plus + user-configured custom ports on loopback) and the enumerated cloud endpoints that mirror the + Tauri CSP `connect-src` (Gemini, OpenAI, x.ai, OpenRouter, Groq). Known limitation (status quo, + unchanged): LAN-IP servers (`http://192.168.…`) and arbitrary BYOK cloud base URLs remain + outside the scope; widening is a separate, deliberate decision. + +## Consequences + +- **Positive:** Desktop Ollama/LM Studio/vLLM discovery and inference work out of the box — no + `OLLAMA_ORIGINS` setup required on desktop. PWA console stays clean. Timeouts, aborts, and error + classes are consistent across all local-server calls. Scan results are actionable (per-endpoint + badge + one-click "use this URL"). +- **Negative / accepted:** A second HTTP code path exists (plugin vs. browser fetch). It is + isolated in one ~100-line module and covered by unit tests that mock both branches. + `streamOllama`/`pullOllamaModel` rely on the plugin's streaming `Response.body` reader — covered + by mocked-reader tests; a native smoke check rides on the `tauri-build.yml` workflow dispatch. +- **Security posture:** unchanged-or-better. No new cloud endpoints, no secrets, localhost-only + capability scope, privacy-first (no call happens without a user-visible provider selection or + button press). + +## Alternatives considered + +- **Document `OLLAMA_ORIGINS=tauri://localhost,http://tauri.localhost` as the fix** — rejected: + pushes setup burden onto every desktop user, still breaks on LM Studio/vLLM CORS configs, and + does nothing for PNA/mixed-content quirks in WebView2/WKWebView. +- **Rust command wrapper (`invoke`) for Ollama** — rejected: duplicates an already-shipped plugin, + adds Rust surface for zero capability gain; plugin-http is the canonical Tauri v2 answer. +- **Allow PWA status-only probing with Private Network Access permission** — rejected (product + decision): keeps CORS noise possible, adds a second-class UX path, and conflicts with the + privacy-first "desktop-only" policy for localhost servers. diff --git a/locales/en/help.json b/locales/en/help.json index 6a4e7819..b0a377b3 100644 --- a/locales/en/help.json +++ b/locales/en/help.json @@ -71,7 +71,7 @@ "help.docs.pwaDesktop.title": "PWA & desktop packaging", "help.docs.ragPipeline.content": "
WorldScript's retrieval-augmented generation (RAG) pipeline enriches every AI request with relevant passages from your own manuscript — so the model knows your story before it writes the next line.
assembleRAGPrompt() builds a token-budgeted context block from the selected chunks and prepends it to the AI prompt. The chunk badge in the Writer panel shows how many passages were injected.The WorldScript Studio desktop app wraps the same React codebase in a native Tauri v2 shell (Rust). It adds capabilities that browsers cannot provide while keeping your data fully local.
fs plugin — no browser file picker required for every operation. Logs are written to $APPDATA/logs/worldscript-YYYY-MM-DD.jsonl.localhost connections in the browser (CSP); the desktop app bypasses this restriction, letting Ollama serve models at localhost:11434 without a proxy.window-state plugin.updater plugin checks the GitHub releases JSON endpoint on startup and shows a banner under Settings → About when a new version is available. Click Install update to download and apply it in the background.tauri-plugin-stronghold can store the IDB encryption passphrase in the OS keychain so the unlock modal never appears on desktop.The Tauri CI workflow builds platform-specific installers on every tagged release (v*): .dmg for macOS (code-signed), .msi / .exe for Windows (code-signed), .AppImage and .deb for Linux. Installers are attached to GitHub Releases and referenced by the auto-updater endpoint.
On desktop, data lives in the Tauri app data directory — typically %APPDATA%\\WorldScript Studio on Windows, ~/Library/Application Support/WorldScript Studio on macOS, and ~/.local/share/worldscript-studio on Linux. You can safely copy this directory for a full manual backup.
The WorldScript Studio desktop app wraps the same React codebase in a native Tauri v2 shell (Rust). It adds capabilities that browsers cannot provide while keeping your data fully local.
fs plugin — no browser file picker required for every operation. Logs are written to $APPDATA/logs/worldscript-YYYY-MM-DD.jsonl.localhost connections (CSP + Private Network Access); the desktop app routes these calls through the native Tauri HTTP stack — no proxy and no OLLAMA_ORIGINS setup needed. Use Settings → AI → Scan common local ports to auto-detect servers at localhost:11434 (Ollama), :1234 (LM Studio) and :8000 (vLLM), then adopt a found URL with one click.window-state plugin.updater plugin checks the GitHub releases JSON endpoint on startup and shows a banner under Settings → About when a new version is available. Click Install update to download and apply it in the background.tauri-plugin-stronghold can store the IDB encryption passphrase in the OS keychain so the unlock modal never appears on desktop.The Tauri CI workflow builds platform-specific installers on every tagged release (v*): .dmg for macOS (code-signed), .msi / .exe for Windows (code-signed), .AppImage and .deb for Linux. Installers are attached to GitHub Releases and referenced by the auto-updater endpoint.
On desktop, data lives in the Tauri app data directory — typically %APPDATA%\\WorldScript Studio on Windows, ~/Library/Application Support/WorldScript Studio on macOS, and ~/.local/share/worldscript-studio on Linux. You can safely copy this directory for a full manual backup.
Only for cloud AI providers. You can use WorldScript for all writing, the Plot Board, characters, version control, and export without any API key. AI features with local providers also need no key.
gemini-2.5-flash for everyday use, gemini-2.5-pro for complex tasks.localhost:11434. Requires the Tauri desktop app. Run ollama pull llama3.2 to get started. Zero API cost, fully private, supports any Ollama-compatible model including LoRA adapters.Every API key is encrypted with AES-256-GCM (PBKDF2, 600,000 SHA-256 iterations) before being stored in IndexedDB. The plaintext key is never written to disk, never stored in localStorage, and never sent to any WorldScript server. You can store keys for multiple providers simultaneously and switch between them without re-entering them.
", "help.faq.api.title": "Do I need an API key?", @@ -79,7 +79,7 @@ "help.faq.offline.title": "Can I work offline?", "help.faq.privacy.content": "Yes, completely. WorldScript Studio is local-first by design — there is no WorldScript account, no cloud server, and no company that can access your manuscripts. All data lives in your browser's IndexedDB and OPFS, storage that only your device can read.
Switch to a local AI provider — WebLLM in the browser or Ollama on the desktop app — or disable AI features entirely. In fully offline mode, zero data is transmitted anywhere. Writing, version control, export, and all settings work without any network connection.
", "help.faq.privacy.title": "Is my story private?", - "help.faq.providers.content": "WorldScript supports multiple AI providers. Here is a quick guide to help you choose.
localhost:11434. Requires the Tauri desktop app. Best for: maximum privacy and zero API cost with any Ollama-supported model.WorldScript supports multiple AI providers. Here is a quick guide to help you choose.
localhost:11434. Requires the Tauri desktop app (browsers block localhost connections); the Scan common local ports button in Settings → AI auto-detects Ollama, LM Studio and vLLM. Best for: maximum privacy and zero API cost with any Ollama-supported model.Your entire project, including all text and AI-generated images, is saved automatically and continuously in your web browser's local storage (a database called IndexedDB). This means your work is persisted on your computer between sessions. A 'Saving...' indicator appears in the header when changes are being written, followed by 'All changes saved'.
There is no cloud account or server-side storage. This ensures complete privacy but also means you are responsible for creating backups using the 'Export Backup' feature in Settings.
", "help.faq.saving.title": "How is my project data saved?", From fa31b2ea9657b3ef2b53161f4336edef236d8c45 Mon Sep 17 00:00:00 2001 From: qnbs <155236708+qnbs@users.noreply.github.com> Date: Sun, 26 Jul 2026 09:47:02 +0200 Subject: [PATCH 02/14] fix(ai): route local-server http through tauri plugin-http (#266) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New thin services/localServerHttp.ts: runtime-aware fetch (native @tauri-apps/plugin-http on desktop — CORS-free, browser fetch on web), shared base-URL normalization, timeout composition via AbortSignal.any, and unreachable/timeout error classification. User aborts rethrow unchanged (cancel != failure). ollamaService (test/list/stream/pull) and scanLocalOpenAiCompatibleEndpoints now use it; the scan returns per-endpoint state (ok/unreachable/timeout/http) for actionable UI badges. Public signatures and legacy error strings are preserved; new unit tests cover both fetch branches and classification. --- services/aiProviderService.ts | 35 ++++++-- services/localServerHttp.ts | 107 +++++++++++++++++++++++ services/ollamaService.ts | 33 +++---- tests/unit/aiProviderService.test.ts | 58 +++++++++++++ tests/unit/localServerHttp.test.ts | 123 +++++++++++++++++++++++++++ tests/unit/ollamaService.test.ts | 8 ++ 6 files changed, 340 insertions(+), 24 deletions(-) create mode 100644 services/localServerHttp.ts create mode 100644 tests/unit/localServerHttp.test.ts diff --git a/services/aiProviderService.ts b/services/aiProviderService.ts index ee55f159..6c3183fd 100644 --- a/services/aiProviderService.ts +++ b/services/aiProviderService.ts @@ -37,6 +37,7 @@ import { streamText as streamTextGemini, } from './geminiService'; import { generateLocalText } from './localAiFacade'; +import { LocalServerError, localServerFetch } from './localServerHttp'; import { listOllamaModels as listOllamaModelsFromService, streamOllama, @@ -686,24 +687,40 @@ export async function listOllamaModels(baseUrl = 'http://localhost:11434'): Prom return listOllamaModelsFromService(baseUrl); } -/** QNBS-v3: Schneller Desktop-Check typischer lokaler /v1-Endpunkte — keine Secrets, nur Erreichbarkeit. */ -export async function scanLocalOpenAiCompatibleEndpoints(): Promise< - { labelKey: string; baseUrl: string; ok: boolean; status?: number }[] -> { +/** QNBS-v3: classified reachability of a scanned local endpoint (#266). */ +export type LocalEndpointScanState = 'ok' | 'unreachable' | 'timeout' | 'http'; + +export interface LocalEndpointScanResult { + labelKey: string; + baseUrl: string; + ok: boolean; + state: LocalEndpointScanState; + /** Numeric HTTP status when the server answered (incl. error statuses). */ + status?: number; +} + +/** + * QNBS-v3: Schneller Desktop-Check typischer lokaler /v1-Endpunkte — keine Secrets, nur + * Erreichbarkeit. #266: routed through localServerFetch (Tauri plugin-http on desktop) so the + * scan works inside the WebView, with per-endpoint state classification for actionable UI badges. + */ +export async function scanLocalOpenAiCompatibleEndpoints(): Promise+ // QNBS-v3 (#266): quiet banner instead of CORS console noise — the PWA never + // auto-probes localhost, so this is the only place the restriction surfaces. +
- {t('settings.ai.corsRestriction')} + {t('settings.ai.ollamaDesktopOnlyTitle')}
-{t('settings.ai.ollamaBrowserNote')}
+{t('settings.ai.ollamaDesktopOnlyBody')}
+ + + {t('settings.ai.downloadDesktopCta')} +WorldScript's retrieval-augmented generation (RAG) pipeline enriches every AI request with relevant passages from your own manuscript — so the model knows your story before it writes the next line.
assembleRAGPrompt() builds a token-budgeted context block from the selected chunks and prepends it to the AI prompt. The chunk badge in the Writer panel shows how many passages were injected.The WorldScript Studio desktop app wraps the same React codebase in a native Tauri v2 shell (Rust). It adds capabilities that browsers cannot provide while keeping your data fully local.
fs plugin — no browser file picker required for every operation. Logs are written to $APPDATA/logs/worldscript-YYYY-MM-DD.jsonl.localhost connections in the browser (CSP); the desktop app bypasses this restriction, letting Ollama serve models at localhost:11434 without a proxy.window-state plugin.updater plugin checks the GitHub releases JSON endpoint on startup and shows a banner under Settings → About when a new version is available. Click Install update to download and apply it in the background.tauri-plugin-stronghold can store the IDB encryption passphrase in the OS keychain so the unlock modal never appears on desktop.The Tauri CI workflow builds platform-specific installers on every tagged release (v*): .dmg for macOS (code-signed), .msi / .exe for Windows (code-signed), .AppImage and .deb for Linux. Installers are attached to GitHub Releases and referenced by the auto-updater endpoint.
On desktop, data lives in the Tauri app data directory — typically %APPDATA%\\WorldScript Studio on Windows, ~/Library/Application Support/WorldScript Studio on macOS, and ~/.local/share/worldscript-studio on Linux. You can safely copy this directory for a full manual backup.
The WorldScript Studio desktop app wraps the same React codebase in a native Tauri v2 shell (Rust). It adds capabilities that browsers cannot provide while keeping your data fully local.
fs plugin — no browser file picker required for every operation. Logs are written to $APPDATA/logs/worldscript-YYYY-MM-DD.jsonl.localhost connections (CSP + Private Network Access); the desktop app routes these calls through the native Tauri HTTP stack — no proxy and no OLLAMA_ORIGINS setup needed. Use Settings → AI → Scan common local ports to auto-detect servers at localhost:11434 (Ollama), :1234 (LM Studio) and :8000 (vLLM), then adopt a found URL with one click.window-state plugin.updater plugin checks the GitHub releases JSON endpoint on startup and shows a banner under Settings → About when a new version is available. Click Install update to download and apply it in the background.tauri-plugin-stronghold can store the IDB encryption passphrase in the OS keychain so the unlock modal never appears on desktop.The Tauri CI workflow builds platform-specific installers on every tagged release (v*): .dmg for macOS (code-signed), .msi / .exe for Windows (code-signed), .AppImage and .deb for Linux. Installers are attached to GitHub Releases and referenced by the auto-updater endpoint.
On desktop, data lives in the Tauri app data directory — typically %APPDATA%\\WorldScript Studio on Windows, ~/Library/Application Support/WorldScript Studio on macOS, and ~/.local/share/worldscript-studio on Linux. You can safely copy this directory for a full manual backup.
Only for cloud AI providers. You can use WorldScript for all writing, the Plot Board, characters, version control, and export without any API key. AI features with local providers also need no key.
gemini-2.5-flash for everyday use, gemini-2.5-pro for complex tasks.localhost:11434. Requires the Tauri desktop app. Run ollama pull llama3.2 to get started. Zero API cost, fully private, supports any Ollama-compatible model including LoRA adapters.Every API key is encrypted with AES-256-GCM (PBKDF2, 600,000 SHA-256 iterations) before being stored in IndexedDB. The plaintext key is never written to disk, never stored in localStorage, and never sent to any WorldScript server. You can store keys for multiple providers simultaneously and switch between them without re-entering them.
", "help.faq.api.title": "Do I need an API key?", @@ -1178,7 +1178,7 @@ "help.faq.offline.title": "Can I work offline?", "help.faq.privacy.content": "Yes, completely. WorldScript Studio is local-first by design — there is no WorldScript account, no cloud server, and no company that can access your manuscripts. All data lives in your browser's IndexedDB and OPFS, storage that only your device can read.
Switch to a local AI provider — WebLLM in the browser or Ollama on the desktop app — or disable AI features entirely. In fully offline mode, zero data is transmitted anywhere. Writing, version control, export, and all settings work without any network connection.
", "help.faq.privacy.title": "Is my story private?", - "help.faq.providers.content": "WorldScript supports multiple AI providers. Here is a quick guide to help you choose.
localhost:11434. Requires the Tauri desktop app. Best for: maximum privacy and zero API cost with any Ollama-supported model.WorldScript supports multiple AI providers. Here is a quick guide to help you choose.
localhost:11434. Requires the Tauri desktop app (browsers block localhost connections); the Scan common local ports button in Settings → AI auto-detects Ollama, LM Studio and vLLM. Best for: maximum privacy and zero API cost with any Ollama-supported model.Your entire project, including all text and AI-generated images, is saved automatically and continuously in your web browser's local storage (a database called IndexedDB). This means your work is persisted on your computer between sessions. A 'Saving...' indicator appears in the header when changes are being written, followed by 'All changes saved'.
There is no cloud account or server-side storage. This ensures complete privacy but also means you are responsible for creating backups using the 'Export Backup' feature in Settings.
", "help.faq.saving.title": "How is my project data saved?", @@ -1621,6 +1621,7 @@ "settings.about.githubDescription": "View source code, report issues, and contribute.", "settings.about.githubLabel": "Open-source on GitHub", "settings.about.liveDemo": "Try the live demo", + "settings.about.productName": "WorldScript Studio", "settings.about.tauriVersion": "Desktop runtime version", "settings.about.title": "About WorldScript Studio", "settings.about.versionLabel": "Version", @@ -1671,16 +1672,16 @@ "settings.advancedAi.model": "AI Model", "settings.advancedAi.modelDescription": "The AI model used for scene generation, analysis, and other AI-powered features. Model availability depends on your selected provider.", "settings.advancedAi.modelRecommendationsIntro": "Popular local checkpoints (verify names in your runtime):", - "settings.advancedAi.ollamaPull.recommendedFor": "Recommended for your device:", + "settings.advancedAi.ollamaPull.batteryNote": "Stepped down a size to save battery.", + "settings.advancedAi.ollamaPull.installed": "Installed", "settings.advancedAi.ollamaPull.pull": "Pull model", "settings.advancedAi.ollamaPull.pulling": "Downloading model…", + "settings.advancedAi.ollamaPull.recommendedFor": "Recommended for your device:", "settings.advancedAi.ollamaPull.retry": "Retry", - "settings.advancedAi.ollamaPull.installed": "Installed", - "settings.advancedAi.ollamaPull.useModel": "Use this model", - "settings.advancedAi.ollamaPull.batteryNote": "Stepped down a size to save battery.", "settings.advancedAi.ollamaPull.tier.high-end": "High-end", - "settings.advancedAi.ollamaPull.tier.mid-range": "Mid-range", "settings.advancedAi.ollamaPull.tier.low-end": "Low-end", + "settings.advancedAi.ollamaPull.tier.mid-range": "Mid-range", + "settings.advancedAi.ollamaPull.useModel": "Use this model", "settings.advancedAi.ragModeHint": "Hybrid mode blends keyword matching with semantic understanding — best for most stories. Rebuild the index after large edits.", "settings.advancedAi.ragModeHybrid": "Hybrid (semantic + lexical, recommended)", "settings.advancedAi.ragModeLabel": "Context retrieval mode", @@ -1690,85 +1691,6 @@ "settings.advancedAi.temperature": "Temperature", "settings.advancedAi.temperatureDescription": "Controls randomness. Higher values produce more creative, unpredictable text; lower values make output more focused and deterministic.", "settings.advancedAi.title": "Advanced AI Settings", - "settings.aiMode.title": "AI Execution Mode", - "settings.aiMode.description": "Choose how the app processes AI requests. Cloud mode uses your API key for best quality, Local mode runs everything on your device for maximum privacy, and Hybrid mode automatically picks the best option.", - "settings.aiMode.hybrid": "Hybrid (Smart)", - "settings.aiMode.hybridDesc": "Automatically uses local models when preloaded, otherwise falls back to the cloud. Best of both worlds.", - "settings.aiMode.cloud": "Cloud", - "settings.aiMode.cloudDesc": "All AI requests are sent to the cloud provider (Gemini, OpenAI, etc.). Best quality, requires an API key and internet connection.", - "settings.aiMode.local": "Local", - "settings.aiMode.localDesc": "All AI runs on your device using local models. No data leaves the device. Works completely offline once models are preloaded.", - "settings.aiMode.eco": "Eco", - "settings.aiMode.ecoDesc": "Battery-saving mode for low-end or mobile devices. Uses only the small 0.5B text model and rule-based heuristics. No cloud, no heavy models.", - "settings.aiMode.activeLabel": "Active: {{mode}}", - "settings.aiMode.indicator.cloud": "Cloud", - "settings.aiMode.indicator.local": "Local", - "settings.aiMode.indicator.hybrid": "Hybrid", - "settings.aiMode.indicator.eco": "Eco", - "settings.aiMode.indicator.tooltip.cloud": "Cloud mode — all AI calls go to your cloud provider", - "settings.aiMode.indicator.tooltip.local": "Local mode — all AI runs on your device", - "settings.aiMode.indicator.tooltip.hybrid": "Hybrid mode — cloud first, local as offline fallback", - "settings.aiMode.indicator.tooltip.eco": "Eco mode — smallest local model, no cloud, battery-saving", - "settings.aiMode.indicator.orCircuitOpen": "OpenRouter paused (too many rate limits). Falling back to other providers.", - "settings.aiMode.indicatorAriaLabel": "Active AI mode", - "settings.aiMode.indicator.openRouter": "OpenRouter", - "settings.aiMode.indicator.openRouterFree": "OpenRouter Free", - "settings.aiMode.indicator.orShort": "OR ⚠", - "settings.aiMode.indicator.rpm": "{{count}}/20 RPM", - "settings.aiMode.hint.webgpuMissing": "WebGPU not detected — on-device models may run slowly or fall back to a smaller engine.", - "settings.aiMode.hint.cloudOffline": "You're offline — Cloud mode can't reach the AI provider. Reconnect or switch to Local/Eco.", - "settings.aiMode.hint.hybridOffline": "You're offline — Hybrid mode will use the on-device fallback until you reconnect.", - "settings.openRouter.title": "OpenRouter", - "settings.openRouter.description": "Use OpenRouter as a unified cloud gateway. Free-tier models (marked with :free) need no paid credits.", - "settings.openRouter.enabled": "Enable OpenRouter", - "settings.openRouter.enabledHint": "When enabled, OpenRouter is preferred for cloud AI calls unless the active mode forbids cloud.", - "settings.openRouter.apiKey": "API Key", - "settings.openRouter.apiKeyPlaceholder": "sk-or-v1-…", - "settings.openRouter.apiKeyHint": "Stored encrypted on this device.", - "settings.openRouter.apiKeyAriaLabel": "OpenRouter API key", - "settings.openRouter.keyStatus.set": "Key stored — enter a new key to replace it", - "settings.openRouter.keyStatus.unset": "No API key stored", - "settings.openRouter.keyStatus.saving": "Saving…", - "settings.openRouter.keyStatus.saved": "API key saved", - "settings.openRouter.keyStatus.removed": "API key removed", - "settings.openRouter.keyError.empty": "Please enter an OpenRouter API key", - "settings.openRouter.keyError.saveFailed": "Failed to save the API key", - "settings.openRouter.keyError.invalid": "The API key appears invalid", - "settings.openRouter.keyError.network": "Network error while validating the key", - "settings.openRouter.preferredModel": "Preferred Model", - "settings.openRouter.modelPlaceholder": "Select or search a model", - "settings.openRouter.modelAriaLabel": "Preferred OpenRouter model", - "settings.openRouter.customModelLabel": "Custom model…", - "settings.openRouter.customModelPlaceholder": "deepseek/deepseek-r1:free", - "settings.openRouter.customModelAriaLabel": "Custom model identifier", - "settings.openRouter.modelFetch.loading": "Loading model catalog…", - "settings.openRouter.modelFetch.failed": "Could not load model catalog", - "settings.openRouter.modelFetch.empty": "No models found", - "settings.openRouter.freeTierNote": "Free-tier models: 20 req/min, 50 req/day without credits", - "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (free)", - "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (free)", - "settings.openRouter.freeModel.qwen2572b": "Qwen 2.5 72B Instruct (free)", - "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (free)", - "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (free)", - "settings.openRouter.paidModelNote": "Paid models require credits on your OpenRouter account.", - "settings.openRouter.policyBlocked.mode": "OpenRouter is unavailable while the AI mode is Local or Eco. Switch to Hybrid or Cloud in AI & Models to use it.", - "settings.openRouter.policyBlocked.localOnly": "OpenRouter is blocked because “Local storage only” is on. Turn it off in Privacy & Data to allow cloud AI.", - "settings.openRouter.getKeyLink": "Get a free API key at openrouter.ai/keys", - "settings.openRouter.testConnection": "Test connection", - "settings.openRouter.testConnectionOk": "Connection successful", - "settings.openRouter.testConnectionFailed": "Connection failed", - "settings.openRouter.saveKey": "Save", - "settings.openRouter.clearKey": "Remove", - "settings.openRouter.circuitBreaker": "Circuit breaker:", - "settings.openRouter.circuitOpen": "Open (paused 5 min)", - "settings.openRouter.circuitClosed": "Closed (healthy)", - "settings.openRouter.resetCircuit": "Reset", - "settings.openRouter.resetCircuitAria": "Reset OpenRouter circuit breaker", - "settings.openRouter.rpmLabel": "Requests / min (last 60 s)", - "settings.openRouter.modeWarning.local": "OpenRouter is disabled while AI mode is set to local-only.", - "settings.openRouter.modeWarning.offline": "OpenRouter is paused because the device is offline.", - "settings.openRouter.errors.generic": "An unexpected OpenRouter error occurred", - "settings.categories.openrouter": "OpenRouter", "settings.advancedAi.topP": "Top P", "settings.advancedAi.topPDescription": "Nucleus sampling threshold. Only tokens whose cumulative probability reaches this value are considered. Lower values = more focused output.", "settings.advancedEditor.autoComplete": "Auto-Complete Suggestions", @@ -1808,6 +1730,7 @@ "settings.ai.creativity": "AI Creativity Level", "settings.ai.creativityDescription": "Higher values produce more unexpected results.", "settings.ai.customModel": "Custom Model", + "settings.ai.downloadDesktopCta": "Download the desktop app", "settings.ai.fallbackNone": "None", "settings.ai.fallbackStep1": "First fallback", "settings.ai.fallbackStep2": "Second fallback", @@ -1836,15 +1759,64 @@ "settings.ai.loadModels": "Load models", "settings.ai.localAi.cancelAriaLabel": "Cancel model download", "settings.ai.localAi.cancelButton": "Cancel", + "settings.ai.localAi.clearBusy": "Local AI is busy right now — try clearing again once it finishes.", + "settings.ai.localAi.clearButton": "Clear Local Models", + "settings.ai.localAi.clearCancel": "Cancel", + "settings.ai.localAi.clearConfirm": "Delete all downloaded local models? They will re-download the next time you use local AI.", + "settings.ai.localAi.clearConfirmYes": "Delete models", + "settings.ai.localAi.clearFailed": "Could not clear local models. Please try again.", + "settings.ai.localAi.clearedAnnounce": "Cleared {{count}} local model cache(s)", + "settings.ai.localAi.clearingButton": "Clearing…", + "settings.ai.localAi.detecting": "Detecting…", + "settings.ai.localAi.deviceClassLabel": "Device class", + "settings.ai.localAi.docsLink": "Local AI setup & troubleshooting", + "settings.ai.localAi.downloadButton": "Download", "settings.ai.localAi.downloadCancelled": "Download cancelled", "settings.ai.localAi.downloadEta": "approx. {{seconds}}s remaining", + "settings.ai.localAi.downloadFailed": "Download failed. Please try again.", "settings.ai.localAi.downloadTitle": "Downloading AI model…", "settings.ai.localAi.downloadedLabel": "downloaded", + "settings.ai.localAi.downloadingButton": "Downloading…", + "settings.ai.localAi.fallbackIntro": "When a layer is unavailable, the Co-Pilot automatically tries the next one:", + "settings.ai.localAi.fallbackLayer1": "WebGPU (WebLLM) — fastest and highest quality; needs a capable GPU.", + "settings.ai.localAi.fallbackLayer2": "WASM (ONNX) — runs on the CPU when no GPU is available.", + "settings.ai.localAi.fallbackLayer3": "Transformers.js — lightweight last-resort generator.", + "settings.ai.localAi.fallbackLayer4": "Heuristic — always-available offline stub when no model can run.", + "settings.ai.localAi.fallbackTitle": "Fallback chain", + "settings.ai.localAi.modelLabel.gemma3_1b": "Gemma 3 1B (~0.8 GB)", + "settings.ai.localAi.modelLabel.gemma3_4b": "Gemma 3 4B (~4.9 GB)", + "settings.ai.localAi.modelLabel.llama32_1b": "Llama 3.2 1B (fast, ~0.7 GB)", + "settings.ai.localAi.modelLabel.llama32_3b": "Llama 3.2 3B (~1.8 GB)", + "settings.ai.localAi.modelLabel.llama33_70b": "Llama 3.3 70B (high-end, ~35 GB)", + "settings.ai.localAi.modelLabel.phi4mini": "Phi-4 Mini 3.8B (~2.3 GB)", + "settings.ai.localAi.modelLabel.qwen25_05b": "Qwen 2.5 0.5B (eco, ~0.4 GB)", + "settings.ai.localAi.modelReadyAnnounce": "{{model}} is ready for offline use", + "settings.ai.localAi.modelsDescription": "Download a model to use it offline. Larger models are higher quality but need more storage and a capable GPU.", + "settings.ai.localAi.modelsTitle": "Models", + "settings.ai.localAi.onboardingHint": "No local model downloaded yet. Download one below to enable offline AI — the first download may take a few minutes.", + "settings.ai.localAi.perfNoData": "Download and run a model to measure throughput.", + "settings.ai.localAi.perfThroughput": "Last local run: {{tps}} tokens/sec", "settings.ai.localAi.progressAriaLabel": "Model download progress", + "settings.ai.localAi.readyBadge": "Ready", + "settings.ai.localAi.recommendedModel": "Recommended for your device: {{model}}", + "settings.ai.localAi.requiresGpuNote": "Without WebGPU, models run on a slower CPU/WASM fallback or download may be unavailable.", "settings.ai.localAi.retryButton": "Retry", + "settings.ai.localAi.sectionDescription": "Run inference on your device. No data leaves the browser. Capability, downloads, and storage are managed here.", + "settings.ai.localAi.sectionTitle": "Local AI", + "settings.ai.localAi.sizeWarning": "Needs ~{{size}} MB; only {{free}} MB free", + "settings.ai.localAi.storageAriaLabel": "Local storage usage", + "settings.ai.localAi.storageModelsCached": "{{count}} local model cache(s) on disk", + "settings.ai.localAi.storageTitle": "Storage", + "settings.ai.localAi.storageUnsupported": "Storage estimates are not available in this browser.", + "settings.ai.localAi.storageUsage": "{{used}} MB of {{quota}} MB used ({{percent}}%)", + "settings.ai.localAi.webgpuAvailable": "Available", + "settings.ai.localAi.webgpuLabel": "WebGPU", + "settings.ai.localAi.webgpuUnavailable": "Not available", "settings.ai.localBackendPreset": "Local backend preset", "settings.ai.ollamaBrowserNote": "Ollama is only available in the desktop app. The browser's Content Security Policy blocks direct connections to localhost.", - "settings.ai.ollamaHint": "Make sure ollama serve is running and CORS is enabled.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama and local OpenAI-compatible servers (LM Studio, vLLM) are only available in the desktop app. Browsers block direct connections to localhost (Content Security Policy and Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Desktop app required for local servers", + "settings.ai.ollamaHint": "Make sure the server is running (e.g. ollama serve). The desktop app connects directly — no CORS setup needed.", "settings.ai.ollamaModelHint": "Quick-select models reported by your server — tap to use.", "settings.ai.ollamaServerUrl": "Ollama Server URL", "settings.ai.ollamaTauriBypass": "Desktop build: WorldScript calls Ollama directly — no browser CORS barrier.", @@ -1876,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Scan common local ports", "settings.ai.scanNo": "no response", "settings.ai.scanOk": "reachable", + "settings.ai.scanStateHttp": "HTTP error", + "settings.ai.scanStateTimeout": "timeout", + "settings.ai.scanUseUrl": "Use this URL", "settings.ai.temperature.balanced": "1 – Balanced", "settings.ai.temperature.creative": "2 – Creative", "settings.ai.temperature.precise": "0 – Precise", @@ -1899,6 +1874,34 @@ "settings.ai.webllm.tabLeaderNote": "Only one browser tab runs local inference at a time.", "settings.ai.webllm.vramLabel": "VRAM tier", "settings.ai.webllmHint": "Runs entirely in your browser via WebGPU (optional packages). Large model downloads on first use; use Ollama on desktop for heavier models.", + "settings.aiMode.activeLabel": "Active: {{mode}}", + "settings.aiMode.cloud": "Cloud", + "settings.aiMode.cloudDesc": "All AI requests are sent to the cloud provider (Gemini, OpenAI, etc.). Best quality, requires an API key and internet connection.", + "settings.aiMode.description": "Choose how the app processes AI requests. Cloud mode uses your API key for best quality, Local mode runs everything on your device for maximum privacy, and Hybrid mode automatically picks the best option.", + "settings.aiMode.eco": "Eco", + "settings.aiMode.ecoDesc": "Battery-saving mode for low-end or mobile devices. Uses only the small 0.5B text model and rule-based heuristics. No cloud, no heavy models.", + "settings.aiMode.hint.cloudOffline": "You're offline — Cloud mode can't reach the AI provider. Reconnect or switch to Local/Eco.", + "settings.aiMode.hint.hybridOffline": "You're offline — Hybrid mode will use the on-device fallback until you reconnect.", + "settings.aiMode.hint.webgpuMissing": "WebGPU not detected — on-device models may run slowly or fall back to a smaller engine.", + "settings.aiMode.hybrid": "Hybrid (Smart)", + "settings.aiMode.hybridDesc": "Automatically uses local models when preloaded, otherwise falls back to the cloud. Best of both worlds.", + "settings.aiMode.indicator.cloud": "Cloud", + "settings.aiMode.indicator.eco": "Eco", + "settings.aiMode.indicator.hybrid": "Hybrid", + "settings.aiMode.indicator.local": "Local", + "settings.aiMode.indicator.openRouter": "OpenRouter", + "settings.aiMode.indicator.openRouterFree": "OpenRouter Free", + "settings.aiMode.indicator.orCircuitOpen": "OpenRouter paused (too many rate limits). Falling back to other providers.", + "settings.aiMode.indicator.orShort": "OR ⚠", + "settings.aiMode.indicator.rpm": "{{count}}/20 RPM", + "settings.aiMode.indicator.tooltip.cloud": "Cloud mode — all AI calls go to your cloud provider", + "settings.aiMode.indicator.tooltip.eco": "Eco mode — smallest local model, no cloud, battery-saving", + "settings.aiMode.indicator.tooltip.hybrid": "Hybrid mode — cloud first, local as offline fallback", + "settings.aiMode.indicator.tooltip.local": "Local mode — all AI runs on your device", + "settings.aiMode.indicatorAriaLabel": "Active AI mode", + "settings.aiMode.local": "Local", + "settings.aiMode.localDesc": "All AI runs on your device using local models. No data leaves the device. Works completely offline once models are preloaded.", + "settings.aiMode.title": "AI Execution Mode", "settings.apiKey.configured": "API Key Configured", "settings.apiKey.encryptedNote": "Encrypted and stored in IndexedDB", "settings.apiKey.errorEmpty": "Please enter an API key", @@ -1949,7 +1952,9 @@ "settings.categories.general": "General", "settings.categories.guide": "Settings guide", "settings.categories.integrations": "Integrations", + "settings.categories.localAi": "Local AI", "settings.categories.loraAdapters": "LoRA Adapters", + "settings.categories.openrouter": "OpenRouter", "settings.categories.plugins": "Plugins", "settings.categories.privacy": "Privacy & Security", "settings.categories.privacyData": "Privacy & Data", @@ -2045,24 +2050,19 @@ "settings.editor.previewText2": "Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat.", "settings.editor.previewTitle": "Live Preview", "settings.editor.title": "Editor Preferences", - "settings.featureFlags.description": "Try features we're still refining. Your feedback shapes what ships next.", - "settings.featureFlags.category.core": "Writing", "settings.featureFlags.category.ai": "AI", - "settings.featureFlags.category.pipeline": "Editing Pipeline", - "settings.featureFlags.category.personalization": "Personalization", "settings.featureFlags.category.analytics": "Analytics", - "settings.featureFlags.category.performance": "Performance", - "settings.featureFlags.category.voice": "Voice", + "settings.featureFlags.category.core": "Writing", "settings.featureFlags.category.extensions": "Extensions", - "settings.featureFlags.category.sync": "Sync", "settings.featureFlags.category.i18n": "Language & Layout", - "settings.featureFlags.dependency.requires": "Requires {{name}}", + "settings.featureFlags.category.performance": "Performance", + "settings.featureFlags.category.personalization": "Personalization", + "settings.featureFlags.category.pipeline": "Editing Pipeline", + "settings.featureFlags.category.sync": "Sync", + "settings.featureFlags.category.voice": "Voice", "settings.featureFlags.dependency.desktopOnly": "Desktop app only", - "settings.featureFlags.risk.high": "May use significant memory, GPU, or token budget.", - "settings.featureFlags.resetToDefaults": "Reset to defaults", - "settings.featureFlags.resetTitle": "Reset experimental features?", - "settings.featureFlags.resetConfirm": "This restores every experimental feature to its default on/off state. Your projects and content are not affected.", - "settings.featureFlags.resetDone": "Experimental features reset to defaults.", + "settings.featureFlags.dependency.requires": "Requires {{name}}", + "settings.featureFlags.description": "Try features we're still refining. Your feedback shapes what ships next.", "settings.featureFlags.enableAdaptiveAiEngine": "Adaptive AI engine (hardware-aware backend selection)", "settings.featureFlags.enableAppHealthPanel": "App health snapshot (About)", "settings.featureFlags.enableBinderResearch": "Research binder (Manuscript sidebar)", @@ -2070,6 +2070,7 @@ "settings.featureFlags.enableCompileWizard": "Compile wizard (Export)", "settings.featureFlags.enableComputeShaders": "WebGPU compute shaders (GPU-accelerated RAG & attention)", "settings.featureFlags.enableDuckDbAnalytics": "Advanced analytics (fast story database)", + "settings.featureFlags.enableGlobalCopilot": "Global AI Copilot (beginner-friendly in-app live assistant)", "settings.featureFlags.enableIdbAtRestEncryption": "IDB at-rest encryption (AES-256-GCM) — enable via Settings › Privacy", "settings.featureFlags.enableLocalFirstSync": "Local-First sync (shadow — experimental)", "settings.featureFlags.enableLoraAdapters": "LoRA adapter inference (experimental)", @@ -2079,12 +2080,16 @@ "settings.featureFlags.enableProForge": "ProForge Pipeline (8-stage agentic editing)", "settings.featureFlags.enableProjectHealthScore": "Project health score (Dashboard)", "settings.featureFlags.enableRtlLayout": "RTL layout (experimental)", - "settings.featureFlags.enableGlobalCopilot": "Global AI Copilot (beginner-friendly in-app live assistant)", "settings.featureFlags.enableRustCompute": "Rust Compute (Tauri TaskSupervisor offloading — Phase 2)", "settings.featureFlags.enableStoryBibleAdvanced": "Story Bible advanced (graph + hints in Codex)", "settings.featureFlags.enableVoiceSupport": "Voice commands & dictation", "settings.featureFlags.enableVoiceWasm": "Voice WASM engine (Whisper.cpp — offline)", "settings.featureFlags.enableWorkerBusV2": "WorkerBus v2 (typed worker orchestration — Phase 2)", + "settings.featureFlags.resetConfirm": "This restores every experimental feature to its default on/off state. Your projects and content are not affected.", + "settings.featureFlags.resetDone": "Experimental features reset to defaults.", + "settings.featureFlags.resetTitle": "Reset experimental features?", + "settings.featureFlags.resetToDefaults": "Reset to defaults", + "settings.featureFlags.risk.high": "May use significant memory, GPU, or token budget.", "settings.featureFlags.title": "Early Access Features", "settings.font.custom": "Custom Font", "settings.font.mono": "Monospace", @@ -2119,6 +2124,8 @@ "settings.guide.integrations.desc": "LanguageTool and external sync.", "settings.guide.integrations.title": "Integrations", "settings.guide.intro": "Overview of every settings category. Use search at the top of Settings to jump quickly.", + "settings.guide.localAi.desc": "Run the AI on your device — check capability, download models, manage storage, and review the offline fallback chain.", + "settings.guide.localAi.title": "Local AI", "settings.guide.loraAdapters.desc": "Manage local LoRA adapters that teach a model your writing voice.", "settings.guide.loraAdapters.title": "Fine-Tuning (LoRA)", "settings.guide.notifications.desc": "Reminders and desktop alerts.", @@ -2161,8 +2168,8 @@ "settings.language.hebrew": "Hebrew (beta)", "settings.language.italian": "Italian", "settings.language.japanese": "Japanese (beta)", - "settings.language.spanish": "Spanish", "settings.language.portuguese": "Portuguese (beta)", + "settings.language.spanish": "Spanish", "settings.language.title": "Language & Region", "settings.loraAdapters.deleteBtn": "Delete", "settings.loraAdapters.description": "Load LoRA fine-tuning adapters for local WebLLM models. Adapters are stored in your browser and never sent to the cloud.", @@ -2173,6 +2180,56 @@ "settings.loraAdapters.title": "LoRA Adapters", "settings.loraAdapters.uploadBtn": "Upload adapter (.safetensors / .bin)", "settings.loraAdapters.uploadError": "Failed to load adapter. The file may be invalid or too large.", + "settings.openRouter.apiKey": "API Key", + "settings.openRouter.apiKeyAriaLabel": "OpenRouter API key", + "settings.openRouter.apiKeyHint": "Stored encrypted on this device.", + "settings.openRouter.apiKeyPlaceholder": "sk-or-v1-…", + "settings.openRouter.circuitBreaker": "Circuit breaker:", + "settings.openRouter.circuitClosed": "Closed (healthy)", + "settings.openRouter.circuitOpen": "Open (paused 5 min)", + "settings.openRouter.clearKey": "Remove", + "settings.openRouter.customModelAriaLabel": "Custom model identifier", + "settings.openRouter.customModelLabel": "Custom model…", + "settings.openRouter.customModelPlaceholder": "deepseek/deepseek-r1:free", + "settings.openRouter.description": "Use OpenRouter as a unified cloud gateway. Free-tier models (marked with :free) need no paid credits.", + "settings.openRouter.enabled": "Enable OpenRouter", + "settings.openRouter.enabledHint": "When enabled, OpenRouter is preferred for cloud AI calls unless the active mode forbids cloud.", + "settings.openRouter.errors.generic": "An unexpected OpenRouter error occurred", + "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (free)", + "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (free)", + "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (free)", + "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (free)", + "settings.openRouter.freeModel.qwen2572b": "Qwen 2.5 72B Instruct (free)", + "settings.openRouter.freeTierNote": "Free-tier models: 20 req/min, 50 req/day without credits", + "settings.openRouter.getKeyLink": "Get a free API key at openrouter.ai/keys", + "settings.openRouter.keyError.empty": "Please enter an OpenRouter API key", + "settings.openRouter.keyError.invalid": "The API key appears invalid", + "settings.openRouter.keyError.network": "Network error while validating the key", + "settings.openRouter.keyError.saveFailed": "Failed to save the API key", + "settings.openRouter.keyStatus.removed": "API key removed", + "settings.openRouter.keyStatus.saved": "API key saved", + "settings.openRouter.keyStatus.saving": "Saving…", + "settings.openRouter.keyStatus.set": "Key stored — enter a new key to replace it", + "settings.openRouter.keyStatus.unset": "No API key stored", + "settings.openRouter.modeWarning.local": "OpenRouter is disabled while AI mode is set to local-only.", + "settings.openRouter.modeWarning.offline": "OpenRouter is paused because the device is offline.", + "settings.openRouter.modelAriaLabel": "Preferred OpenRouter model", + "settings.openRouter.modelFetch.empty": "No models found", + "settings.openRouter.modelFetch.failed": "Could not load model catalog", + "settings.openRouter.modelFetch.loading": "Loading model catalog…", + "settings.openRouter.modelPlaceholder": "Select or search a model", + "settings.openRouter.paidModelNote": "Paid models require credits on your OpenRouter account.", + "settings.openRouter.policyBlocked.localOnly": "OpenRouter is blocked because “Local storage only” is on. Turn it off in Privacy & Data to allow cloud AI.", + "settings.openRouter.policyBlocked.mode": "OpenRouter is unavailable while the AI mode is Local or Eco. Switch to Hybrid or Cloud in AI & Models to use it.", + "settings.openRouter.preferredModel": "Preferred Model", + "settings.openRouter.resetCircuit": "Reset", + "settings.openRouter.resetCircuitAria": "Reset OpenRouter circuit breaker", + "settings.openRouter.rpmLabel": "Requests / min (last 60 s)", + "settings.openRouter.saveKey": "Save", + "settings.openRouter.testConnection": "Test connection", + "settings.openRouter.testConnectionFailed": "Connection failed", + "settings.openRouter.testConnectionOk": "Connection successful", + "settings.openRouter.title": "OpenRouter", "settings.overview.openGuide": "Full settings guide", "settings.overview.title": "Quick links", "settings.plugins.description": "Manage WorldScript Studio extension plugins. Plugins run in a sandboxed API layer and can only access the permissions they declare.", @@ -2214,11 +2271,11 @@ "settings.privacy.encryptionUnlockButton": "Unlock", "settings.privacy.encryptionWarning": "If you forget your passphrase, your data cannot be recovered.", "settings.privacy.encryptionWrongPassphrase": "Wrong passphrase — decryption failed", + "settings.privacy.euDataResidency": "EU Data Residency", + "settings.privacy.euDataResidencyHint": "Keep all data within European Union servers where applicable.", "settings.privacy.localStorageOnly": "Local Storage Only", "settings.privacy.migrationComplete": "All data encrypted successfully", "settings.privacy.migrationProgress": "Encrypting existing data…", - "settings.privacy.euDataResidency": "EU Data Residency", - "settings.privacy.euDataResidencyHint": "Keep all data within European Union servers where applicable.", "settings.privacy.title": "Privacy & Security", "settings.projectAi.activeIndicator": "Project AI active", "settings.projectAi.category": "Project AI", @@ -2289,8 +2346,15 @@ "settings.voice.autoPunctuationHint": "Automatically add periods and commas while dictating.", "settings.voice.cloudFallback": "Allow Cloud STT Fallback", "settings.voice.cloudFallbackHint": "When local speech recognition is unavailable, send audio to cloud providers. Requires internet.", + "settings.voice.downloadModels": "Download Models", + "settings.voice.downloadSttModel": "Download STT (Whisper)", + "settings.voice.downloadTtsModel": "Download TTS (Kokoro)", "settings.voice.enableHint": "Activate voice commands, dictation, and audio feedback.", "settings.voice.enableLabel": "Enable Voice Support", + "settings.voice.engine.auto": "Auto (recommended)", + "settings.voice.engine.privacyNote": "Privacy: ‘Web Speech API’ sends audio to your browser vendor (Google, Apple, or Microsoft). ‘Local WASM model’ runs fully on your device. ‘Auto’ prefers on-device and may fall back to cloud.", + "settings.voice.engine.wasm": "Local WASM model (offline)", + "settings.voice.engine.webSpeech": "Web Speech API (cloud)", "settings.voice.feedbackLevel": "Audio Feedback Level", "settings.voice.intro": "Control WorldScript Studio with your voice. Choose a cloud or fully on-device speech engine below.", "settings.voice.level.minimal": "Minimal — errors only", @@ -2305,91 +2369,33 @@ "settings.voice.privacy.consentDecline": "Decline", "settings.voice.privacy.consentTitle": "Web Speech Consent", "settings.voice.privacy.revokeConsent": "Revoke Consent", + "settings.voice.privacy.revokeConsentHint": "Removes your Web Speech consent. Voice will fall back to local WASM or be disabled.", "settings.voice.privacy.statusExternal": "External", "settings.voice.privacy.statusLocal": "Local", "settings.voice.privacyNotice": "By default, the Web Speech engine sends your audio to Google or Microsoft for transcription. Switch to the on-device (WASM) engine to keep all audio on your device.", + "settings.voice.pttHint": "Push-to-Talk shortcut: Ctrl+Shift+V (Windows/Linux) or ⌘+Shift+V (Mac). Hold to record.", + "settings.voice.speechRate": "Speech Rate", + "settings.voice.speechRateHint": "How fast the text-to-speech voice speaks. 1.0 = normal speed.", + "settings.voice.speechVolume": "Speech Volume", + "settings.voice.speechVolumeHint": "Volume of the text-to-speech voice. Does not affect microphone input.", + "settings.voice.sttEngine": "Speech Recognition (STT) Engine", + "settings.voice.sttEngineHint": "Choose the engine that converts your speech to text. 'Auto' picks the best available option.", "settings.voice.title": "Voice Full Support", + "settings.voice.ttsEngine": "Text-to-Speech (TTS) Engine", + "settings.voice.ttsEngineHint": "Choose the voice that reads responses aloud. 'Auto' picks the best available option.", "settings.voice.ttsMuted": "Mute All Speech Output", "settings.voice.ttsMutedHint": "Disable text-to-speech while keeping visual indicators.", + "settings.voice.wakeWordPhrase": "Wake Word Phrase", + "settings.voice.wakeWordPhraseHint": "The phrase you say to activate voice commands hands-free.", + "settings.voice.wasmModels": "WASM Voice Models", + "settings.voice.wasmModelsNotReady": "Whisper STT (~42 MB) and Kokoro TTS (~15 MB) models not downloaded", + "settings.voice.wasmModelsReady": "Downloaded and ready for local voice processing", "voice.modelDownload.cancel": "Cancel", "voice.modelDownload.description": "Downloading {{model}} model ({{size}} MB). This enables local voice processing without cloud routing.", "voice.modelDownload.error": "Download failed: {{error}}", "voice.modelDownload.progress": "{{percent}}% complete", "voice.modelDownload.retry": "Retry", "voice.modelDownload.title": "Voice Model Download", - "settings.voice.wasmModels": "WASM Voice Models", - "settings.voice.wasmModelsReady": "Downloaded and ready for local voice processing", - "settings.voice.wasmModelsNotReady": "Whisper STT (~42 MB) and Kokoro TTS (~15 MB) models not downloaded", - "settings.voice.downloadModels": "Download Models", - "settings.voice.downloadSttModel": "Download STT (Whisper)", - "settings.voice.downloadTtsModel": "Download TTS (Kokoro)", - "settings.voice.sttEngine": "Speech Recognition (STT) Engine", - "settings.voice.sttEngineHint": "Choose the engine that converts your speech to text. 'Auto' picks the best available option.", - "settings.voice.ttsEngine": "Text-to-Speech (TTS) Engine", - "settings.voice.ttsEngineHint": "Choose the voice that reads responses aloud. 'Auto' picks the best available option.", - "settings.voice.engine.auto": "Auto (recommended)", - "settings.voice.engine.webSpeech": "Web Speech API (cloud)", - "settings.voice.engine.wasm": "Local WASM model (offline)", - "settings.voice.engine.privacyNote": "Privacy: ‘Web Speech API’ sends audio to your browser vendor (Google, Apple, or Microsoft). ‘Local WASM model’ runs fully on your device. ‘Auto’ prefers on-device and may fall back to cloud.", - "settings.voice.speechRate": "Speech Rate", - "settings.voice.speechRateHint": "How fast the text-to-speech voice speaks. 1.0 = normal speed.", - "settings.voice.speechVolume": "Speech Volume", - "settings.voice.speechVolumeHint": "Volume of the text-to-speech voice. Does not affect microphone input.", - "settings.voice.wakeWordPhrase": "Wake Word Phrase", - "settings.voice.wakeWordPhraseHint": "The phrase you say to activate voice commands hands-free.", - "settings.voice.pttHint": "Push-to-Talk shortcut: Ctrl+Shift+V (Windows/Linux) or ⌘+Shift+V (Mac). Hold to record.", - "settings.voice.privacy.revokeConsentHint": "Removes your Web Speech consent. Voice will fall back to local WASM or be disabled.", - "settings.categories.localAi": "Local AI", - "settings.guide.localAi.title": "Local AI", - "settings.guide.localAi.desc": "Run the AI on your device — check capability, download models, manage storage, and review the offline fallback chain.", - "settings.ai.localAi.sectionTitle": "Local AI", - "settings.ai.localAi.sectionDescription": "Run inference on your device. No data leaves the browser. Capability, downloads, and storage are managed here.", - "settings.ai.localAi.webgpuLabel": "WebGPU", - "settings.ai.localAi.webgpuAvailable": "Available", - "settings.ai.localAi.webgpuUnavailable": "Not available", - "settings.ai.localAi.deviceClassLabel": "Device class", - "settings.ai.localAi.recommendedModel": "Recommended for your device: {{model}}", - "settings.ai.localAi.onboardingHint": "No local model downloaded yet. Download one below to enable offline AI — the first download may take a few minutes.", - "settings.ai.localAi.modelsTitle": "Models", - "settings.ai.localAi.modelsDescription": "Download a model to use it offline. Larger models are higher quality but need more storage and a capable GPU.", - "settings.ai.localAi.downloadButton": "Download", - "settings.ai.localAi.downloadingButton": "Downloading…", - "settings.ai.localAi.readyBadge": "Ready", - "settings.ai.localAi.sizeWarning": "Needs ~{{size}} MB; only {{free}} MB free", - "settings.ai.localAi.modelReadyAnnounce": "{{model}} is ready for offline use", - "settings.ai.localAi.requiresGpuNote": "Without WebGPU, models run on a slower CPU/WASM fallback or download may be unavailable.", - "settings.ai.localAi.storageTitle": "Storage", - "settings.ai.localAi.storageUsage": "{{used}} MB of {{quota}} MB used ({{percent}}%)", - "settings.ai.localAi.storageModelsCached": "{{count}} local model cache(s) on disk", - "settings.ai.localAi.storageUnsupported": "Storage estimates are not available in this browser.", - "settings.ai.localAi.storageAriaLabel": "Local storage usage", - "settings.ai.localAi.clearButton": "Clear Local Models", - "settings.ai.localAi.clearingButton": "Clearing…", - "settings.ai.localAi.clearConfirm": "Delete all downloaded local models? They will re-download the next time you use local AI.", - "settings.ai.localAi.clearConfirmYes": "Delete models", - "settings.ai.localAi.clearCancel": "Cancel", - "settings.ai.localAi.clearedAnnounce": "Cleared {{count}} local model cache(s)", - "settings.ai.localAi.fallbackTitle": "Fallback chain", - "settings.ai.localAi.fallbackIntro": "When a layer is unavailable, the Co-Pilot automatically tries the next one:", - "settings.ai.localAi.fallbackLayer1": "WebGPU (WebLLM) — fastest and highest quality; needs a capable GPU.", - "settings.ai.localAi.fallbackLayer2": "WASM (ONNX) — runs on the CPU when no GPU is available.", - "settings.ai.localAi.fallbackLayer3": "Transformers.js — lightweight last-resort generator.", - "settings.ai.localAi.fallbackLayer4": "Heuristic — always-available offline stub when no model can run.", - "settings.ai.localAi.perfThroughput": "Last local run: {{tps}} tokens/sec", - "settings.ai.localAi.perfNoData": "Download and run a model to measure throughput.", - "settings.ai.localAi.docsLink": "Local AI setup & troubleshooting", - "settings.ai.localAi.detecting": "Detecting…", - "settings.ai.localAi.clearBusy": "Local AI is busy right now — try clearing again once it finishes.", - "settings.ai.localAi.downloadFailed": "Download failed. Please try again.", - "settings.ai.localAi.clearFailed": "Could not clear local models. Please try again.", - "settings.ai.localAi.modelLabel.qwen25_05b": "Qwen 2.5 0.5B (eco, ~0.4 GB)", - "settings.ai.localAi.modelLabel.llama32_1b": "Llama 3.2 1B (fast, ~0.7 GB)", - "settings.ai.localAi.modelLabel.llama32_3b": "Llama 3.2 3B (~1.8 GB)", - "settings.ai.localAi.modelLabel.phi4mini": "Phi-4 Mini 3.8B (~2.3 GB)", - "settings.ai.localAi.modelLabel.gemma3_1b": "Gemma 3 1B (~0.8 GB)", - "settings.ai.localAi.modelLabel.gemma3_4b": "Gemma 3 4B (~4.9 GB)", - "settings.ai.localAi.modelLabel.llama33_70b": "Llama 3.3 70B (high-end, ~35 GB)", - "settings.about.productName": "WorldScript Studio", "sidebar.mainAria": "Main sidebar", "sidebar.primaryNavAria": "Primary navigation", "sidebar.secondaryNavAria": "Settings and help", diff --git a/public/locales/es/bundle.json b/public/locales/es/bundle.json index e37193d9..fba0fc79 100644 --- a/public/locales/es/bundle.json +++ b/public/locales/es/bundle.json @@ -1621,6 +1621,7 @@ "settings.about.githubDescription": "Ver el código fuente, reportar errores y contribuir.", "settings.about.githubLabel": "Código abierto en GitHub", "settings.about.liveDemo": "Probar la demo en vivo", + "settings.about.productName": "WorldScript Studio", "settings.about.tauriVersion": "Versión del runtime de escritorio", "settings.about.title": "Acerca de WorldScript Studio", "settings.about.versionLabel": "Versión", @@ -1671,16 +1672,16 @@ "settings.advancedAi.model": "Modelo de IA", "settings.advancedAi.modelDescription": "El modelo de IA usado para generación de escenas, análisis y otras funciones. La disponibilidad depende del proveedor seleccionado.", "settings.advancedAi.modelRecommendationsIntro": "Puntos de control locales populares (verifica los nombres en tu entorno de ejecución):", - "settings.advancedAi.ollamaPull.recommendedFor": "Recomendado para tu dispositivo:", + "settings.advancedAi.ollamaPull.batteryNote": "Se eligió un tamaño menor para ahorrar batería.", + "settings.advancedAi.ollamaPull.installed": "Instalado", "settings.advancedAi.ollamaPull.pull": "Descargar modelo", "settings.advancedAi.ollamaPull.pulling": "Descargando modelo…", + "settings.advancedAi.ollamaPull.recommendedFor": "Recomendado para tu dispositivo:", "settings.advancedAi.ollamaPull.retry": "Reintentar", - "settings.advancedAi.ollamaPull.installed": "Instalado", - "settings.advancedAi.ollamaPull.useModel": "Usar este modelo", - "settings.advancedAi.ollamaPull.batteryNote": "Se eligió un tamaño menor para ahorrar batería.", "settings.advancedAi.ollamaPull.tier.high-end": "Gama alta", - "settings.advancedAi.ollamaPull.tier.mid-range": "Gama media", "settings.advancedAi.ollamaPull.tier.low-end": "Gama baja", + "settings.advancedAi.ollamaPull.tier.mid-range": "Gama media", + "settings.advancedAi.ollamaPull.useModel": "Usar este modelo", "settings.advancedAi.ragModeHint": "El modo híbrido combina búsqueda por palabras clave con comprensión semántica — ideal para la mayoría de historias. Reconstruye el índice tras grandes cambios.", "settings.advancedAi.ragModeHybrid": "Híbrido (semántico + léxico, recomendado)", "settings.advancedAi.ragModeLabel": "Modo de recuperación de contexto", @@ -1729,6 +1730,7 @@ "settings.ai.creativity": "Nivel de creatividad de la IA", "settings.ai.creativityDescription": "Los valores más altos producen resultados más inesperados.", "settings.ai.customModel": "Modelo personalizado", + "settings.ai.downloadDesktopCta": "Descargar la aplicación de escritorio", "settings.ai.fallbackNone": "Ninguno", "settings.ai.fallbackStep1": "Primer respaldo", "settings.ai.fallbackStep2": "Segundo respaldo", @@ -1812,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "No disponible", "settings.ai.localBackendPreset": "Preajuste de backend local", "settings.ai.ollamaBrowserNote": "Ollama solo está disponible en la aplicación de escritorio. La política de seguridad de contenido del navegador bloquea las conexiones directas a localhost.", - "settings.ai.ollamaHint": "Asegúrate de que ollama serve está en ejecución y CORS está habilitado.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama y los servidores locales compatibles con OpenAI (LM Studio, vLLM) solo están disponibles en la aplicación de escritorio. Los navegadores bloquean las conexiones directas a localhost (Content Security Policy y Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Se requiere la aplicación de escritorio para servidores locales", + "settings.ai.ollamaHint": "Asegúrate de que el servidor esté en ejecución (p. ej. ollama serve). La aplicación de escritorio se conecta directamente, sin configuración CORS.", "settings.ai.ollamaModelHint": "Selección rápida de modelos reportados por tu servidor — toca para usar.", "settings.ai.ollamaServerUrl": "URL del servidor Ollama", "settings.ai.ollamaTauriBypass": "Versión de escritorio: WorldScript llama a Ollama directamente — sin barrera de CORS del navegador.", @@ -1844,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Escanear puertos locales comunes", "settings.ai.scanNo": "sin respuesta", "settings.ai.scanOk": "accesible", + "settings.ai.scanStateHttp": "error HTTP", + "settings.ai.scanStateTimeout": "tiempo de espera agotado", + "settings.ai.scanUseUrl": "Usar esta URL", "settings.ai.temperature.balanced": "1 – Equilibrado", "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", @@ -2043,24 +2050,19 @@ "settings.editor.previewText2": "Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat.", "settings.editor.previewTitle": "Vista previa en vivo", "settings.editor.title": "Preferencias del editor", - "settings.featureFlags.description": "Prueba funciones que aún estamos refinando. Tu opinión define lo que publicamos.", - "settings.featureFlags.category.core": "Escritura", "settings.featureFlags.category.ai": "IA", - "settings.featureFlags.category.pipeline": "Flujo de edición", - "settings.featureFlags.category.personalization": "Personalización", "settings.featureFlags.category.analytics": "Analíticas", - "settings.featureFlags.category.performance": "Rendimiento", - "settings.featureFlags.category.voice": "Voz", + "settings.featureFlags.category.core": "Escritura", "settings.featureFlags.category.extensions": "Extensiones", - "settings.featureFlags.category.sync": "Sincronización", "settings.featureFlags.category.i18n": "Idioma y diseño", - "settings.featureFlags.dependency.requires": "Requiere {{name}}", + "settings.featureFlags.category.performance": "Rendimiento", + "settings.featureFlags.category.personalization": "Personalización", + "settings.featureFlags.category.pipeline": "Flujo de edición", + "settings.featureFlags.category.sync": "Sincronización", + "settings.featureFlags.category.voice": "Voz", "settings.featureFlags.dependency.desktopOnly": "Solo en la app de escritorio", - "settings.featureFlags.risk.high": "Puede usar mucha memoria, GPU o presupuesto de tokens.", - "settings.featureFlags.resetToDefaults": "Restablecer valores predeterminados", - "settings.featureFlags.resetTitle": "¿Restablecer las funciones experimentales?", - "settings.featureFlags.resetConfirm": "Esto restaura todas las funciones experimentales a su estado predeterminado (activado/desactivado). Tus proyectos y contenido no se ven afectados.", - "settings.featureFlags.resetDone": "Funciones experimentales restablecidas a los valores predeterminados.", + "settings.featureFlags.dependency.requires": "Requiere {{name}}", + "settings.featureFlags.description": "Prueba funciones que aún estamos refinando. Tu opinión define lo que publicamos.", "settings.featureFlags.enableAdaptiveAiEngine": "Motor IA adaptativo (selección inteligente de backend)", "settings.featureFlags.enableAppHealthPanel": "Instantánea del estado de la app (acerca de)", "settings.featureFlags.enableBinderResearch": "Cuaderno de investigación (barra lateral del manuscrito)", @@ -2083,6 +2085,11 @@ "settings.featureFlags.enableVoiceSupport": "Comandos de voz y dictado", "settings.featureFlags.enableVoiceWasm": "Motor de voz WASM (Whisper.cpp — sin conexión)", "settings.featureFlags.enableWorkerBusV2": "WorkerBus v2 (orquestación tipada de trabajadores — Fase 2)", + "settings.featureFlags.resetConfirm": "Esto restaura todas las funciones experimentales a su estado predeterminado (activado/desactivado). Tus proyectos y contenido no se ven afectados.", + "settings.featureFlags.resetDone": "Funciones experimentales restablecidas a los valores predeterminados.", + "settings.featureFlags.resetTitle": "¿Restablecer las funciones experimentales?", + "settings.featureFlags.resetToDefaults": "Restablecer valores predeterminados", + "settings.featureFlags.risk.high": "Puede usar mucha memoria, GPU o presupuesto de tokens.", "settings.featureFlags.title": "Funciones de acceso anticipado", "settings.font.custom": "Fuente personalizada", "settings.font.mono": "Monoespaciado", @@ -2212,8 +2219,8 @@ "settings.openRouter.modelFetch.loading": "Cargando catálogo de modelos…", "settings.openRouter.modelPlaceholder": "Selecciona o busca un modelo", "settings.openRouter.paidModelNote": "Los modelos de pago requieren créditos en tu cuenta de OpenRouter.", - "settings.openRouter.policyBlocked.mode": "OpenRouter no está disponible en el modo de IA Local o Eco. Cambia a Híbrido o Nube en IA y Modelos para usarlo.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter está bloqueado porque “Solo almacenamiento local” está activado. Desáctivalo en Privacidad y Datos para permitir la IA en la nube.", + "settings.openRouter.policyBlocked.mode": "OpenRouter no está disponible en el modo de IA Local o Eco. Cambia a Híbrido o Nube en IA y Modelos para usarlo.", "settings.openRouter.preferredModel": "Modelo preferido", "settings.openRouter.resetCircuit": "Restablecer", "settings.openRouter.resetCircuitAria": "Restablecer el cortacircuitos de OpenRouter", @@ -2345,8 +2352,8 @@ "settings.voice.enableHint": "Activate voice commands, dictation, and audio feedback.", "settings.voice.enableLabel": "Enable Voice Support", "settings.voice.engine.auto": "Automático (recomendado)", - "settings.voice.engine.wasm": "Modelo WASM local (sin conexión)", "settings.voice.engine.privacyNote": "Privacidad: «Web Speech API» envía audio al proveedor de tu navegador (Google, Apple o Microsoft). «Modelo WASM local» se ejecuta totalmente en tu dispositivo. «Auto» prefiere local y puede recurrir a la nube.", + "settings.voice.engine.wasm": "Modelo WASM local (sin conexión)", "settings.voice.engine.webSpeech": "Web Speech API (nube)", "settings.voice.feedbackLevel": "Audio Feedback Level", "settings.voice.intro": "Controla WorldScript Studio con tu voz. Elige abajo un motor de voz en la nube o totalmente local.", @@ -2389,7 +2396,6 @@ "voice.modelDownload.progress": "{{percent}}% completado", "voice.modelDownload.retry": "Reintentar", "voice.modelDownload.title": "Descarga de modelo de voz", - "settings.about.productName": "WorldScript Studio", "sidebar.characterGraph": "Grafo de personajes", "sidebar.characterInterviews": "Entrevistas de personajes", "sidebar.characters": "Personajes", diff --git a/public/locales/eu/bundle.json b/public/locales/eu/bundle.json index 7ce35d64..44f4d84d 100644 --- a/public/locales/eu/bundle.json +++ b/public/locales/eu/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AI Sormen Maila", "settings.ai.creativityDescription": "Balio altuagoek ustekabeko emaitza gehiago sortzen dituzte.", "settings.ai.customModel": "Eredu pertsonalizatua", + "settings.ai.downloadDesktopCta": "Deskargatu mahaigaineko aplikazioa", "settings.ai.fallbackNone": "Bat ere ez", "settings.ai.fallbackStep1": "Lehenengo atzerakada", "settings.ai.fallbackStep2": "Bigarren atzerakada", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Ez dago eskuragarri", "settings.ai.localBackendPreset": "Backend lokala aurrez ezarri", "settings.ai.ollamaBrowserNote": "Ollama mahaigaineko aplikazioan bakarrik dago eskuragarri. Arakatzailearen Edukiaren Segurtasun-Politikak lokaleko ostalari konexio zuzenak blokeatzen ditu.", - "settings.ai.ollamaHint": "Ziurtatu ollama zerbitzaria martxan dagoela eta CORS gaituta dagoela.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama eta OpenAI-rekin bateragarriak diren tokiko zerbitzariak (LM Studio, vLLM) mahaigaineko aplikazioan bakarrik daude eskuragarri. Nabigatzaileek localhost-era zuzeneko konexioak blokeatzen dituzte (Edukiaren Segurtasun Politika eta Sare Pribaturako Sarbidea).", + "settings.ai.ollamaDesktopOnlyTitle": "Mahaigaineko aplikazioa behar da tokiko zerbitzarietarako", + "settings.ai.ollamaHint": "Ziurtatu zerbitzaria martxan dagoela (adib. ollama serve). Mahaigaineko aplikazioa zuzenean konektatzen da — ez da CORS konfiguraziorik behar.", "settings.ai.ollamaModelHint": "Aukeratu azkar zure zerbitzariak jakinarazitako ereduak — sakatu erabiltzeko.", "settings.ai.ollamaServerUrl": "Ollama zerbitzariaren URLa", "settings.ai.ollamaTauriBypass": "Mahaigaineko eraikuntza: WorldScript-ek zuzenean deitzen dio Ollamari — ez dago arakatzailearen CORS oztoporik.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Eskaneatu tokiko ataka arruntak", "settings.ai.scanNo": "erantzunik ez", "settings.ai.scanOk": "irisgarria", + "settings.ai.scanStateHttp": "HTTP errorea", + "settings.ai.scanStateTimeout": "denbora-muga gaindituta", + "settings.ai.scanUseUrl": "Erabili URL hau", "settings.ai.temperature.balanced": "1 – Orekatua", "settings.ai.temperature.creative": "2 – Sormena", "settings.ai.temperature.precise": "0 – Zehatza", diff --git a/public/locales/fa/bundle.json b/public/locales/fa/bundle.json index 7442ea6a..a1259f71 100644 --- a/public/locales/fa/bundle.json +++ b/public/locales/fa/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "سطح خلاقیت هوش مصنوعی", "settings.ai.creativityDescription": "مقادیر بالاتر نتایج غیرمنتظره تری ایجاد می کند.", "settings.ai.customModel": "مدل سفارشی", + "settings.ai.downloadDesktopCta": "دانلود برنامه دسکتاپ", "settings.ai.fallbackNone": "هیچ کدام", "settings.ai.fallbackStep1": "اولین بازگشت", "settings.ai.fallbackStep2": "بازگشت دوم", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "در دسترس نیست", "settings.ai.localBackendPreset": "از پیش تنظیم شده باطن محلی", "settings.ai.ollamaBrowserNote": "Ollama فقط در برنامه دسکتاپ در دسترس است. خط مشی امنیت محتوای مرورگر اتصال مستقیم به لوکال هاست را مسدود می کند.", - "settings.ai.ollamaHint": "مطمئن شوید که سرویس olama در حال اجرا است و CORS فعال است.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama و سرورهای محلی سازگار با OpenAI (LM Studio، vLLM) فقط در برنامه دسکتاپ در دسترس هستند. مرورگرها اتصالات مستقیم به localhost را مسدود میکنند (سیاست امنیت محتوا و دسترسی به شبکه خصوصی).", + "settings.ai.ollamaDesktopOnlyTitle": "برنامه دسکتاپ برای سرورهای محلی لازم است", + "settings.ai.ollamaHint": "مطمئن شوید سرور در حال اجراست (مثلاً ollama serve). برنامه دسکتاپ مستقیم متصل میشود — نیازی به تنظیم CORS نیست.", "settings.ai.ollamaModelHint": "مدلهای گزارششده توسط سرورتان را سریع انتخاب کنید — برای استفاده ضربه بزنید.", "settings.ai.ollamaServerUrl": "آدرس سرور اوللاما", "settings.ai.ollamaTauriBypass": "ساخت دسکتاپ: WorldScript مستقیماً اوللاما را فرا میخواند - بدون مانع CORS مرورگر.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "پورت های محلی رایج را اسکن کنید", "settings.ai.scanNo": "بدون پاسخ", "settings.ai.scanOk": "قابل دسترس", + "settings.ai.scanStateHttp": "خطای HTTP", + "settings.ai.scanStateTimeout": "پایان مهلت", + "settings.ai.scanUseUrl": "استفاده از این نشانی", "settings.ai.temperature.balanced": "1- متعادل", "settings.ai.temperature.creative": "2- خلاق", "settings.ai.temperature.precise": "0 - دقیق", diff --git a/public/locales/fi/bundle.json b/public/locales/fi/bundle.json index 0cce6112..7446ae77 100644 --- a/public/locales/fi/bundle.json +++ b/public/locales/fi/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "Tekoälyn luovuustaso", "settings.ai.creativityDescription": "Suuremmat arvot tuottavat enemmän odottamattomia tuloksia.", "settings.ai.customModel": "Mukautettu malli", + "settings.ai.downloadDesktopCta": "Lataa työpöytäsovellus", "settings.ai.fallbackNone": "Ei mitään", "settings.ai.fallbackStep1": "Ensimmäinen takaisku", "settings.ai.fallbackStep2": "Toinen takaisku", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Ei saatavilla", "settings.ai.localBackendPreset": "Paikallinen taustajärjestelmän esiasetus", "settings.ai.ollamaBrowserNote": "Ollama on saatavilla vain työpöytäsovelluksessa. Selaimen sisällön suojauskäytäntö estää suorat yhteydet localhostiin.", - "settings.ai.ollamaHint": "Varmista, että ollama-palvelu on käynnissä ja CORS on käytössä.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama ja paikalliset OpenAI-yhteensopivat palvelimet (LM Studio, vLLM) ovat käytettävissä vain työpöytäsovelluksessa. Selaimet estävät suorat yhteydet localhostiin (Content Security Policy ja Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Paikalliset palvelimet vaativat työpöytäsovelluksen", + "settings.ai.ollamaHint": "Varmista, että palvelin on käynnissä (esim. ollama serve). Työpöytäsovellus yhdistää suoraan — CORS-asetuksia ei tarvita.", "settings.ai.ollamaModelHint": "Palvelimesi ilmoittamat pikavalintamallit – käytä napauttamalla.", "settings.ai.ollamaServerUrl": "Ollama-palvelimen URL-osoite", "settings.ai.ollamaTauriBypass": "Työpöytärakenne: WorldScript kutsuu Ollamaa suoraan – ei selaimen CORS-estettä.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Tarkista yleiset paikalliset portit", "settings.ai.scanNo": "ei vastausta", "settings.ai.scanOk": "tavoitettavissa", + "settings.ai.scanStateHttp": "HTTP-virhe", + "settings.ai.scanStateTimeout": "aikakatkaisu", + "settings.ai.scanUseUrl": "Käytä tätä URL-osoitetta", "settings.ai.temperature.balanced": "1 – Tasapainoinen", "settings.ai.temperature.creative": "2 – Luova", "settings.ai.temperature.precise": "0 – Tarkka", diff --git a/public/locales/fr/bundle.json b/public/locales/fr/bundle.json index 30e7dc36..41506bd1 100644 --- a/public/locales/fr/bundle.json +++ b/public/locales/fr/bundle.json @@ -1621,6 +1621,7 @@ "settings.about.githubDescription": "Voir le code source, signaler des bugs et contribuer.", "settings.about.githubLabel": "Open-source sur GitHub", "settings.about.liveDemo": "Essayer la démo en ligne", + "settings.about.productName": "WorldScript Studio", "settings.about.tauriVersion": "Version du runtime bureau", "settings.about.title": "À propos de WorldScript Studio", "settings.about.versionLabel": "Version", @@ -1671,16 +1672,16 @@ "settings.advancedAi.model": "Modèle d'IA", "settings.advancedAi.modelDescription": "Le modèle IA utilisé pour la génération de scènes, l'analyse et d'autres fonctionnalités IA. La disponibilité dépend du fournisseur sélectionné.", "settings.advancedAi.modelRecommendationsIntro": "Points de contrôle locaux populaires (vérifiez les noms dans votre environnement d'exécution) :", - "settings.advancedAi.ollamaPull.recommendedFor": "Recommandé pour votre appareil :", + "settings.advancedAi.ollamaPull.batteryNote": "Taille réduite pour économiser la batterie.", + "settings.advancedAi.ollamaPull.installed": "Installé", "settings.advancedAi.ollamaPull.pull": "Télécharger le modèle", "settings.advancedAi.ollamaPull.pulling": "Téléchargement du modèle…", + "settings.advancedAi.ollamaPull.recommendedFor": "Recommandé pour votre appareil :", "settings.advancedAi.ollamaPull.retry": "Réessayer", - "settings.advancedAi.ollamaPull.installed": "Installé", - "settings.advancedAi.ollamaPull.useModel": "Utiliser ce modèle", - "settings.advancedAi.ollamaPull.batteryNote": "Taille réduite pour économiser la batterie.", "settings.advancedAi.ollamaPull.tier.high-end": "Haut de gamme", - "settings.advancedAi.ollamaPull.tier.mid-range": "Milieu de gamme", "settings.advancedAi.ollamaPull.tier.low-end": "Entrée de gamme", + "settings.advancedAi.ollamaPull.tier.mid-range": "Milieu de gamme", + "settings.advancedAi.ollamaPull.useModel": "Utiliser ce modèle", "settings.advancedAi.ragModeHint": "Le mode hybride associe recherche par mots-clés et compréhension sémantique — idéal pour la plupart des histoires. Reconstruisez l'index après de grandes modifications.", "settings.advancedAi.ragModeHybrid": "Hybride (sémantique + lexical, recommandé)", "settings.advancedAi.ragModeLabel": "Mode de récupération du contexte", @@ -1729,6 +1730,7 @@ "settings.ai.creativity": "Niveau de créativité de l'IA", "settings.ai.creativityDescription": "Des valeurs plus élevées produisent des résultats plus inattendus.", "settings.ai.customModel": "Modèle personnalisé", + "settings.ai.downloadDesktopCta": "Télécharger l'application de bureau", "settings.ai.fallbackNone": "Aucun", "settings.ai.fallbackStep1": "Premier repli", "settings.ai.fallbackStep2": "Deuxième repli", @@ -1812,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Indisponible", "settings.ai.localBackendPreset": "Préréglage backend local", "settings.ai.ollamaBrowserNote": "Ollama n'est disponible que dans l'application de bureau. La politique de sécurité du contenu du navigateur bloque les connexions directes à localhost.", - "settings.ai.ollamaHint": "Assurez-vous qu'ollama serve est en cours d'exécution et que CORS est activé.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama et les serveurs locaux compatibles OpenAI (LM Studio, vLLM) ne sont disponibles que dans l'application de bureau. Les navigateurs bloquent les connexions directes vers localhost (Content Security Policy et Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Application de bureau requise pour les serveurs locaux", + "settings.ai.ollamaHint": "Assurez-vous que le serveur est en cours d'exécution (p. ex. ollama serve). L'application de bureau se connecte directement — aucune configuration CORS nécessaire.", "settings.ai.ollamaModelHint": "Sélection rapide des modèles rapportés par votre serveur — appuyez pour utiliser.", "settings.ai.ollamaServerUrl": "URL du serveur Ollama", "settings.ai.ollamaTauriBypass": "Version bureau : WorldScript appelle Ollama directement — aucune barrière CORS du navigateur.", @@ -1844,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Scanner les ports locaux courants", "settings.ai.scanNo": "pas de réponse", "settings.ai.scanOk": "accessible", + "settings.ai.scanStateHttp": "erreur HTTP", + "settings.ai.scanStateTimeout": "délai dépassé", + "settings.ai.scanUseUrl": "Utiliser cette URL", "settings.ai.temperature.balanced": "1 – Équilibré", "settings.ai.temperature.creative": "2 – Créatif", "settings.ai.temperature.precise": "0 – Précis", @@ -2043,24 +2050,19 @@ "settings.editor.previewText2": "Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat.", "settings.editor.previewTitle": "Aperçu en direct", "settings.editor.title": "Préférences de l'éditeur", - "settings.featureFlags.description": "Essayez des fonctionnalités que nous affinons encore. Vos retours façonnent ce qui sera publié.", - "settings.featureFlags.category.core": "Écriture", "settings.featureFlags.category.ai": "IA", - "settings.featureFlags.category.pipeline": "Chaîne d'édition", - "settings.featureFlags.category.personalization": "Personnalisation", "settings.featureFlags.category.analytics": "Analyses", - "settings.featureFlags.category.performance": "Performances", - "settings.featureFlags.category.voice": "Voix", + "settings.featureFlags.category.core": "Écriture", "settings.featureFlags.category.extensions": "Extensions", - "settings.featureFlags.category.sync": "Synchronisation", "settings.featureFlags.category.i18n": "Langue et mise en page", - "settings.featureFlags.dependency.requires": "Nécessite {{name}}", + "settings.featureFlags.category.performance": "Performances", + "settings.featureFlags.category.personalization": "Personnalisation", + "settings.featureFlags.category.pipeline": "Chaîne d'édition", + "settings.featureFlags.category.sync": "Synchronisation", + "settings.featureFlags.category.voice": "Voix", "settings.featureFlags.dependency.desktopOnly": "Application de bureau uniquement", - "settings.featureFlags.risk.high": "Peut utiliser beaucoup de mémoire, de GPU ou de budget de jetons.", - "settings.featureFlags.resetToDefaults": "Réinitialiser par défaut", - "settings.featureFlags.resetTitle": "Réinitialiser les fonctionnalités expérimentales ?", - "settings.featureFlags.resetConfirm": "Cela rétablit toutes les fonctionnalités expérimentales à leur état par défaut (activé/désactivé). Vos projets et votre contenu ne sont pas affectés.", - "settings.featureFlags.resetDone": "Fonctionnalités expérimentales réinitialisées par défaut.", + "settings.featureFlags.dependency.requires": "Nécessite {{name}}", + "settings.featureFlags.description": "Essayez des fonctionnalités que nous affinons encore. Vos retours façonnent ce qui sera publié.", "settings.featureFlags.enableAdaptiveAiEngine": "Moteur IA adaptatif (sélection intelligente du backend)", "settings.featureFlags.enableAppHealthPanel": "Instantané de l'état de l'application (à propos)", "settings.featureFlags.enableBinderResearch": "Classeur de recherche (barre latérale du manuscrit)", @@ -2083,6 +2085,11 @@ "settings.featureFlags.enableVoiceSupport": "Commandes vocales & dictée", "settings.featureFlags.enableVoiceWasm": "Moteur vocal WASM (Whisper.cpp — hors ligne)", "settings.featureFlags.enableWorkerBusV2": "WorkerBus v2 (orchestration typée de workers — Phase 2)", + "settings.featureFlags.resetConfirm": "Cela rétablit toutes les fonctionnalités expérimentales à leur état par défaut (activé/désactivé). Vos projets et votre contenu ne sont pas affectés.", + "settings.featureFlags.resetDone": "Fonctionnalités expérimentales réinitialisées par défaut.", + "settings.featureFlags.resetTitle": "Réinitialiser les fonctionnalités expérimentales ?", + "settings.featureFlags.resetToDefaults": "Réinitialiser par défaut", + "settings.featureFlags.risk.high": "Peut utiliser beaucoup de mémoire, de GPU ou de budget de jetons.", "settings.featureFlags.title": "Fonctionnalités en accès anticipé", "settings.font.custom": "Police personnalisée", "settings.font.mono": "Monospace", @@ -2212,8 +2219,8 @@ "settings.openRouter.modelFetch.loading": "Chargement du catalogue de modèles…", "settings.openRouter.modelPlaceholder": "Sélectionner ou rechercher un modèle", "settings.openRouter.paidModelNote": "Les modèles payants nécessitent des crédits sur votre compte OpenRouter.", - "settings.openRouter.policyBlocked.mode": "OpenRouter est indisponible en mode IA Local ou Éco. Passez en mode Hybride ou Cloud dans IA et Modèles pour l’utiliser.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter est bloqué car « Stockage local uniquement » est activé. Désactivez-le dans Confidentialité et Données pour autoriser l’IA cloud.", + "settings.openRouter.policyBlocked.mode": "OpenRouter est indisponible en mode IA Local ou Éco. Passez en mode Hybride ou Cloud dans IA et Modèles pour l’utiliser.", "settings.openRouter.preferredModel": "Modèle préféré", "settings.openRouter.resetCircuit": "Réinitialiser", "settings.openRouter.resetCircuitAria": "Réinitialiser le disjoncteur OpenRouter", @@ -2345,8 +2352,8 @@ "settings.voice.enableHint": "Activate voice commands, dictation, and audio feedback.", "settings.voice.enableLabel": "Enable Voice Support", "settings.voice.engine.auto": "Automatique (recommandé)", - "settings.voice.engine.wasm": "Modèle WASM local (hors ligne)", "settings.voice.engine.privacyNote": "Confidentialité : « Web Speech API » envoie l'audio à l'éditeur de votre navigateur (Google, Apple ou Microsoft). « Modèle WASM local » s'exécute entièrement sur votre appareil. « Auto » privilégie le local et peut basculer vers le cloud.", + "settings.voice.engine.wasm": "Modèle WASM local (hors ligne)", "settings.voice.engine.webSpeech": "Web Speech API (cloud)", "settings.voice.feedbackLevel": "Audio Feedback Level", "settings.voice.intro": "Contrôlez WorldScript Studio à la voix. Choisissez ci-dessous un moteur vocal cloud ou entièrement local.", @@ -2389,7 +2396,6 @@ "voice.modelDownload.progress": "{{percent}}% terminé", "voice.modelDownload.retry": "Réessayer", "voice.modelDownload.title": "Téléchargement du modèle vocal", - "settings.about.productName": "WorldScript Studio", "sidebar.characterGraph": "Graphe des personnages", "sidebar.characterInterviews": "Entretiens de personnages", "sidebar.characters": "Personnages", diff --git a/public/locales/he/bundle.json b/public/locales/he/bundle.json index a3208eaa..0969a441 100644 --- a/public/locales/he/bundle.json +++ b/public/locales/he/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "רמת יצירתיות AI", "settings.ai.creativityDescription": "ערכים גבוהים מפיקים תוצאות בלתי צפויות יותר.", "settings.ai.customModel": "מודל מותאם", + "settings.ai.downloadDesktopCta": "הורדת יישום שולחן העבודה", "settings.ai.fallbackNone": "ללא", "settings.ai.fallbackStep1": "חלופה ראשונה", "settings.ai.fallbackStep2": "חלופה שנייה", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Not available", "settings.ai.localBackendPreset": "הגדרה מוגדרת מראש של מנוע אחורי מקומי", "settings.ai.ollamaBrowserNote": "Ollama זמין רק באפליקציית שולחן העבודה. מדיניות אבטחת התוכן של הדפדפן חוסמת חיבורים ישירים ל‑localhost.", - "settings.ai.ollamaHint": "ודאו ש‑ollama serve פועל ו‑CORS מופעל.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama ושרתים מקומיים תואמי-OpenAI (LM Studio, vLLM) זמינים רק ביישום שולחן העבודה. דפדפנים חוסמים חיבורים ישירים אל localhost (Content Security Policy ו-Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "נדרש יישום שולחני עבור שרתים מקומיים", + "settings.ai.ollamaHint": "ודא שהשרת פועל (למשל ollama serve). יישום שולחן העבודה מתחבר ישירות — אין צורך בהגדרת CORS.", "settings.ai.ollamaModelHint": "מודלי בחירה מהירה שדווחו על ידי השרת שלכם — הקישו לשימוש.", "settings.ai.ollamaServerUrl": "כתובת שרת Ollama", "settings.ai.ollamaTauriBypass": "בניית שולחן עבודה: WorldScript קורא ל‑Ollama ישירות — ללא מחסום CORS של הדפדפן.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "סריקת פורטים מקומיים נפוצים", "settings.ai.scanNo": "אין תגובה", "settings.ai.scanOk": "נגיש", + "settings.ai.scanStateHttp": "שגיאת HTTP", + "settings.ai.scanStateTimeout": "פג תוקף", + "settings.ai.scanUseUrl": "השתמש בכתובת זו", "settings.ai.temperature.balanced": "1 – מאוזן", "settings.ai.temperature.creative": "2 – יצירתי", "settings.ai.temperature.precise": "0 – מדויק", diff --git a/public/locales/hu/bundle.json b/public/locales/hu/bundle.json index 58058abc..5b77efed 100644 --- a/public/locales/hu/bundle.json +++ b/public/locales/hu/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AI kreativitás szintje", "settings.ai.creativityDescription": "A magasabb értékek váratlanabb eredményeket eredményeznek.", "settings.ai.customModel": "Egyedi modell", + "settings.ai.downloadDesktopCta": "Asztali alkalmazás letöltése", "settings.ai.fallbackNone": "Egyik sem", "settings.ai.fallbackStep1": "Első visszaesés", "settings.ai.fallbackStep2": "Második visszaesés", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Nem elérhető", "settings.ai.localBackendPreset": "Helyi háttér előre beállított", "settings.ai.ollamaBrowserNote": "Az Ollama csak az asztali alkalmazásban érhető el. A böngésző tartalombiztonsági házirendje blokkolja a közvetlen kapcsolatot a localhosttal.", - "settings.ai.ollamaHint": "Győződjön meg arról, hogy az ollama szolgáltatás fut, és a CORS engedélyezve van.", + "settings.ai.ollamaDesktopOnlyBody": "Az Ollama és a helyi OpenAI-kompatibilis kiszolgálók (LM Studio, vLLM) csak az asztali alkalmazásban érhetők el. A böngészők blokkolják a localhost felé irányuló közvetlen kapcsolatokat (Content Security Policy és Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Helyi kiszolgálókhoz asztali alkalmazás szükséges", + "settings.ai.ollamaHint": "Győződj meg róla, hogy a kiszolgáló fut (pl. ollama serve). Az asztali alkalmazás közvetlenül kapcsolódik — CORS-beállítás nem szükséges.", "settings.ai.ollamaModelHint": "A kiszolgáló által jelentett modellek gyors kiválasztása – koppintson a használathoz.", "settings.ai.ollamaServerUrl": "Ollama szerver URL-je", "settings.ai.ollamaTauriBypass": "Asztali felépítés: A WorldScript közvetlenül hívja az Ollamát – a böngésző CORS akadálya nélkül.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "A gyakori helyi portok vizsgálata", "settings.ai.scanNo": "nincs válasz", "settings.ai.scanOk": "elérhető", + "settings.ai.scanStateHttp": "HTTP-hiba", + "settings.ai.scanStateTimeout": "időtúllépés", + "settings.ai.scanUseUrl": "URL használata", "settings.ai.temperature.balanced": "1 – Kiegyensúlyozott", "settings.ai.temperature.creative": "2 – Kreatív", "settings.ai.temperature.precise": "0 – Pontos", diff --git a/public/locales/is/bundle.json b/public/locales/is/bundle.json index eb09a5b7..5598f2f9 100644 --- a/public/locales/is/bundle.json +++ b/public/locales/is/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AI sköpunarstig", "settings.ai.creativityDescription": "Hærri gildi gefa óvæntari niðurstöður.", "settings.ai.customModel": "Sérsniðin líkan", + "settings.ai.downloadDesktopCta": "Sækja skjáborðsforritið", "settings.ai.fallbackNone": "Engin", "settings.ai.fallbackStep1": "Fyrsta afturför", "settings.ai.fallbackStep2": "Önnur afturför", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Ekki í boði", "settings.ai.localBackendPreset": "Forstilla staðbundin bakenda", "settings.ai.ollamaBrowserNote": "Ollama er aðeins fáanlegt í skjáborðsforritinu. Innihaldsöryggisstefna vafrans lokar á beinar tengingar við localhost.", - "settings.ai.ollamaHint": "Gakktu úr skugga um að ollama þjóna sé í gangi og CORS sé virkt.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama og staðværir OpenAI-samhæfðir þjónar (LM Studio, vLLM) eru aðeins í boði í skjáborðsforritinu. Vafrar loka beinum tengingum við localhost (Content Security Policy og Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Skjáborðsforrits er krafist fyrir staðværa þjóna", + "settings.ai.ollamaHint": "Gakktu úr skugga um að þjónninn sé í gangi (t.d. ollama serve). Skjáborðsforritið tengist beint — engin CORS-uppsetning nauðsynleg.", "settings.ai.ollamaModelHint": "Flýtivalsgerðir sem miðlarinn þinn hefur tilkynnt um – bankaðu til að nota.", "settings.ai.ollamaServerUrl": "Ollama Server URL", "settings.ai.ollamaTauriBypass": "Skrifborðsbygging: WorldScript hringir beint í Ollama - engin CORS hindrun vafra.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Skannaðu algengar staðbundnar hafnir", "settings.ai.scanNo": "ekkert svar", "settings.ai.scanOk": "náðist", + "settings.ai.scanStateHttp": "HTTP-villa", + "settings.ai.scanStateTimeout": "tímamörk liðin", + "settings.ai.scanUseUrl": "Nota þessa slóð", "settings.ai.temperature.balanced": "1 - Jafnvægi", "settings.ai.temperature.creative": "2 - Skapandi", "settings.ai.temperature.precise": "0 - Nákvæmt", diff --git a/public/locales/it/bundle.json b/public/locales/it/bundle.json index 927e7b8e..9c49a8fb 100644 --- a/public/locales/it/bundle.json +++ b/public/locales/it/bundle.json @@ -1621,6 +1621,7 @@ "settings.about.githubDescription": "Visualizza il codice sorgente, segnala problemi e contribuisci.", "settings.about.githubLabel": "Open-source su GitHub", "settings.about.liveDemo": "Prova la demo dal vivo", + "settings.about.productName": "WorldScript Studio", "settings.about.tauriVersion": "Versione runtime desktop", "settings.about.title": "Informazioni su WorldScript Studio", "settings.about.versionLabel": "Versione", @@ -1671,16 +1672,16 @@ "settings.advancedAi.model": "Modello IA", "settings.advancedAi.modelDescription": "Il modello IA usato per la generazione di scene, analisi e altre funzionalità IA. La disponibilità dipende dal provider selezionato.", "settings.advancedAi.modelRecommendationsIntro": "Checkpoint locali popolari (verifica i nomi nel tuo ambiente di esecuzione):", - "settings.advancedAi.ollamaPull.recommendedFor": "Consigliato per il tuo dispositivo:", + "settings.advancedAi.ollamaPull.batteryNote": "Ridotta la dimensione per risparmiare batteria.", + "settings.advancedAi.ollamaPull.installed": "Installato", "settings.advancedAi.ollamaPull.pull": "Scarica modello", "settings.advancedAi.ollamaPull.pulling": "Download del modello…", + "settings.advancedAi.ollamaPull.recommendedFor": "Consigliato per il tuo dispositivo:", "settings.advancedAi.ollamaPull.retry": "Riprova", - "settings.advancedAi.ollamaPull.installed": "Installato", - "settings.advancedAi.ollamaPull.useModel": "Usa questo modello", - "settings.advancedAi.ollamaPull.batteryNote": "Ridotta la dimensione per risparmiare batteria.", "settings.advancedAi.ollamaPull.tier.high-end": "Fascia alta", - "settings.advancedAi.ollamaPull.tier.mid-range": "Fascia media", "settings.advancedAi.ollamaPull.tier.low-end": "Fascia bassa", + "settings.advancedAi.ollamaPull.tier.mid-range": "Fascia media", + "settings.advancedAi.ollamaPull.useModel": "Usa questo modello", "settings.advancedAi.ragModeHint": "La modalità ibrida combina ricerca per parole chiave e comprensione semantica — ideale per la maggior parte delle storie. Ricostruisci l'indice dopo modifiche importanti.", "settings.advancedAi.ragModeHybrid": "Ibrido (semantico + lessicale, consigliato)", "settings.advancedAi.ragModeLabel": "Modalità di recupero del contesto", @@ -1729,6 +1730,7 @@ "settings.ai.creativity": "Livello di creatività dell'IA", "settings.ai.creativityDescription": "Valori più alti producono risultati più inaspettati.", "settings.ai.customModel": "Modello personalizzato", + "settings.ai.downloadDesktopCta": "Scarica l'app desktop", "settings.ai.fallbackNone": "Nessuno", "settings.ai.fallbackStep1": "Primo fallback", "settings.ai.fallbackStep2": "Secondo fallback", @@ -1812,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Non disponibile", "settings.ai.localBackendPreset": "Preset backend locale", "settings.ai.ollamaBrowserNote": "Ollama è disponibile solo nell'app desktop. La politica di sicurezza dei contenuti del browser blocca le connessioni dirette a localhost.", - "settings.ai.ollamaHint": "Assicurati che ollama serve sia in esecuzione e che CORS sia abilitato.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama e i server locali compatibili con OpenAI (LM Studio, vLLM) sono disponibili solo nell'app desktop. I browser bloccano le connessioni dirette a localhost (Content Security Policy e Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "App desktop richiesta per i server locali", + "settings.ai.ollamaHint": "Assicurati che il server sia in esecuzione (es. ollama serve). L'app desktop si connette direttamente — nessuna configurazione CORS necessaria.", "settings.ai.ollamaModelHint": "Selezione rapida dei modelli segnalati dal tuo server — tocca per usare.", "settings.ai.ollamaServerUrl": "URL del server Ollama", "settings.ai.ollamaTauriBypass": "Versione desktop: WorldScript chiama Ollama direttamente — nessuna barriera CORS del browser.", @@ -1844,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Scansiona porte locali comuni", "settings.ai.scanNo": "nessuna risposta", "settings.ai.scanOk": "raggiungibile", + "settings.ai.scanStateHttp": "errore HTTP", + "settings.ai.scanStateTimeout": "timeout", + "settings.ai.scanUseUrl": "Usa questo URL", "settings.ai.temperature.balanced": "1 – Equilibrato", "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", @@ -2043,24 +2050,19 @@ "settings.editor.previewText2": "Cras elementum ultrices diam. Maecenas ligula massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit amet erat.", "settings.editor.previewTitle": "Anteprima in tempo reale", "settings.editor.title": "Preferenze dell'editor", - "settings.featureFlags.description": "Prova funzionalità che stiamo ancora perfezionando. Il tuo feedback determina ciò che verrà pubblicato.", - "settings.featureFlags.category.core": "Scrittura", "settings.featureFlags.category.ai": "IA", - "settings.featureFlags.category.pipeline": "Flusso di modifica", - "settings.featureFlags.category.personalization": "Personalizzazione", "settings.featureFlags.category.analytics": "Analisi", - "settings.featureFlags.category.performance": "Prestazioni", - "settings.featureFlags.category.voice": "Voce", + "settings.featureFlags.category.core": "Scrittura", "settings.featureFlags.category.extensions": "Estensioni", - "settings.featureFlags.category.sync": "Sincronizzazione", "settings.featureFlags.category.i18n": "Lingua e layout", - "settings.featureFlags.dependency.requires": "Richiede {{name}}", + "settings.featureFlags.category.performance": "Prestazioni", + "settings.featureFlags.category.personalization": "Personalizzazione", + "settings.featureFlags.category.pipeline": "Flusso di modifica", + "settings.featureFlags.category.sync": "Sincronizzazione", + "settings.featureFlags.category.voice": "Voce", "settings.featureFlags.dependency.desktopOnly": "Solo app desktop", - "settings.featureFlags.risk.high": "Può usare molta memoria, GPU o budget di token.", - "settings.featureFlags.resetToDefaults": "Ripristina valori predefiniti", - "settings.featureFlags.resetTitle": "Ripristinare le funzionalità sperimentali?", - "settings.featureFlags.resetConfirm": "Questo ripristina tutte le funzionalità sperimentali al loro stato predefinito (attivo/disattivo). I tuoi progetti e contenuti non sono interessati.", - "settings.featureFlags.resetDone": "Funzionalità sperimentali ripristinate ai valori predefiniti.", + "settings.featureFlags.dependency.requires": "Richiede {{name}}", + "settings.featureFlags.description": "Prova funzionalità che stiamo ancora perfezionando. Il tuo feedback determina ciò che verrà pubblicato.", "settings.featureFlags.enableAdaptiveAiEngine": "Motore IA adattivo (selezione intelligente del backend)", "settings.featureFlags.enableAppHealthPanel": "Istantanea dello stato dell'app (informazioni)", "settings.featureFlags.enableBinderResearch": "Raccoglitore di ricerca (barra laterale del manoscritto)", @@ -2083,6 +2085,11 @@ "settings.featureFlags.enableVoiceSupport": "Comandi vocali e dettatura", "settings.featureFlags.enableVoiceWasm": "Motore vocale WASM (Whisper.cpp — offline)", "settings.featureFlags.enableWorkerBusV2": "WorkerBus v2 (orchestrazione tipizzata dei worker — Fase 2)", + "settings.featureFlags.resetConfirm": "Questo ripristina tutte le funzionalità sperimentali al loro stato predefinito (attivo/disattivo). I tuoi progetti e contenuti non sono interessati.", + "settings.featureFlags.resetDone": "Funzionalità sperimentali ripristinate ai valori predefiniti.", + "settings.featureFlags.resetTitle": "Ripristinare le funzionalità sperimentali?", + "settings.featureFlags.resetToDefaults": "Ripristina valori predefiniti", + "settings.featureFlags.risk.high": "Può usare molta memoria, GPU o budget di token.", "settings.featureFlags.title": "Funzionalità in accesso anticipato", "settings.font.custom": "Carattere personalizzato", "settings.font.mono": "Monospazio", @@ -2212,8 +2219,8 @@ "settings.openRouter.modelFetch.loading": "Caricamento del catalogo modelli…", "settings.openRouter.modelPlaceholder": "Seleziona o cerca un modello", "settings.openRouter.paidModelNote": "I modelli a pagamento richiedono crediti sul tuo account OpenRouter.", - "settings.openRouter.policyBlocked.mode": "OpenRouter non è disponibile in modalità IA Locale o Eco. Passa a Ibrida o Cloud in IA e Modelli per usarlo.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter è bloccato perché “Solo archiviazione locale” è attivo. Disattivalo in Privacy e Dati per consentire l’IA nel cloud.", + "settings.openRouter.policyBlocked.mode": "OpenRouter non è disponibile in modalità IA Locale o Eco. Passa a Ibrida o Cloud in IA e Modelli per usarlo.", "settings.openRouter.preferredModel": "Modello preferito", "settings.openRouter.resetCircuit": "Reimposta", "settings.openRouter.resetCircuitAria": "Reimposta l'interruttore di OpenRouter", @@ -2345,8 +2352,8 @@ "settings.voice.enableHint": "Attiva comandi vocali, dettatura e feedback audio.", "settings.voice.enableLabel": "Abilita controllo vocale", "settings.voice.engine.auto": "Automatico (consigliato)", - "settings.voice.engine.wasm": "Modello WASM locale (offline)", "settings.voice.engine.privacyNote": "Privacy: «Web Speech API» invia l'audio al fornitore del browser (Google, Apple o Microsoft). «Modello WASM locale» funziona interamente sul dispositivo. «Auto» preferisce il locale e può ricorrere al cloud.", + "settings.voice.engine.wasm": "Modello WASM locale (offline)", "settings.voice.engine.webSpeech": "Web Speech API (cloud)", "settings.voice.feedbackLevel": "Livello di feedback audio", "settings.voice.intro": "Controlla WorldScript Studio con la voce. Scegli sotto un motore vocale cloud o completamente locale.", @@ -2389,7 +2396,6 @@ "voice.modelDownload.progress": "{{percent}}% completato", "voice.modelDownload.retry": "Riprova", "voice.modelDownload.title": "Download modello vocale", - "settings.about.productName": "WorldScript Studio", "sidebar.characterGraph": "Grafo dei personaggi", "sidebar.characterInterviews": "Interviste ai personaggi", "sidebar.characters": "Personaggi", diff --git a/public/locales/ja/bundle.json b/public/locales/ja/bundle.json index eb23181f..d4ec16c9 100644 --- a/public/locales/ja/bundle.json +++ b/public/locales/ja/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AIの創造性レベル", "settings.ai.creativityDescription": "値を大きくすると、より予期しない結果が生じます。", "settings.ai.customModel": "カスタムモデル", + "settings.ai.downloadDesktopCta": "デスクトップアプリをダウンロード", "settings.ai.fallbackNone": "なし", "settings.ai.fallbackStep1": "最初のフォールバック", "settings.ai.fallbackStep2": "2 番目のフォールバック", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "利用不可", "settings.ai.localBackendPreset": "ローカル バックエンド プリセット", "settings.ai.ollamaBrowserNote": "Ollama はデスクトップ アプリでのみ利用できます。ブラウザのコンテンツ セキュリティ ポリシーは、ローカルホストへの直接接続をブロックします。", - "settings.ai.ollamaHint": "ollamserve が実行中であり、CORS が有効になっていることを確認してください。", + "settings.ai.ollamaDesktopOnlyBody": "Ollama およびローカルの OpenAI 互換サーバー(LM Studio、vLLM)はデスクトップアプリでのみ利用できます。ブラウザーは localhost への直接接続をブロックします(Content Security Policy および Private Network Access)。", + "settings.ai.ollamaDesktopOnlyTitle": "ローカルサーバーにはデスクトップアプリが必要です", + "settings.ai.ollamaHint": "サーバーが起動していることを確認してください(例: ollama serve)。デスクトップアプリは直接接続するため、CORS の設定は不要です。", "settings.ai.ollamaModelHint": "サーバーから報告されたモデルをクイック選択します — タップして使用します。", "settings.ai.ollamaServerUrl": "オラマサーバーのURL", "settings.ai.ollamaTauriBypass": "デスクトップ ビルド: WorldScript は Ollama を直接呼び出します。ブラウザーの CORS バリアはありません。", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "共通のローカルポートをスキャンする", "settings.ai.scanNo": "応答なし", "settings.ai.scanOk": "到達可能な", + "settings.ai.scanStateHttp": "HTTP エラー", + "settings.ai.scanStateTimeout": "タイムアウト", + "settings.ai.scanUseUrl": "この URL を使用", "settings.ai.temperature.balanced": "1 – バランスのとれた", "settings.ai.temperature.creative": "2 – クリエイティブ", "settings.ai.temperature.precise": "0 – 正確", diff --git a/public/locales/ko/bundle.json b/public/locales/ko/bundle.json index 9a6cbe23..b760766f 100644 --- a/public/locales/ko/bundle.json +++ b/public/locales/ko/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AI 창의성 수준", "settings.ai.creativityDescription": "값이 높을수록 예상치 못한 결과가 더 많이 발생합니다.", "settings.ai.customModel": "맞춤형 모델", + "settings.ai.downloadDesktopCta": "데스크톱 앱 다운로드", "settings.ai.fallbackNone": "없음", "settings.ai.fallbackStep1": "첫 번째 대체", "settings.ai.fallbackStep2": "두 번째 대체", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "사용할 수 없음", "settings.ai.localBackendPreset": "로컬 백엔드 사전 설정", "settings.ai.ollamaBrowserNote": "Ollama는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저의 콘텐츠 보안 정책은 localhost에 대한 직접 연결을 차단합니다.", - "settings.ai.ollamaHint": "ollama 서비스가 실행 중이고 CORS가 활성화되어 있는지 확인하세요.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama 및 로컬 OpenAI 호환 서버(LM Studio, vLLM)는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저는 localhost에 대한 직접 연결을 차단합니다(Content Security Policy 및 Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "로컬 서버에는 데스크톱 앱이 필요합니다", + "settings.ai.ollamaHint": "서버가 실행 중인지 확인하세요(예: ollama serve). 데스크톱 앱은 직접 연결하므로 CORS 설정이 필요하지 않습니다.", "settings.ai.ollamaModelHint": "서버에서 보고한 모델을 빠르게 선택하세요. 탭하여 사용하세요.", "settings.ai.ollamaServerUrl": "올라마 서버 URL", "settings.ai.ollamaTauriBypass": "데스크탑 빌드: WorldScript는 브라우저 CORS 장벽 없이 Ollama를 직접 호출합니다.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "공통 로컬 포트 스캔", "settings.ai.scanNo": "응답 없음", "settings.ai.scanOk": "도달 가능", + "settings.ai.scanStateHttp": "HTTP 오류", + "settings.ai.scanStateTimeout": "시간 초과", + "settings.ai.scanUseUrl": "이 URL 사용", "settings.ai.temperature.balanced": "1 - 균형 잡힌", "settings.ai.temperature.creative": "2 – 창의적", "settings.ai.temperature.precise": "0 – 정확함", diff --git a/public/locales/pt/bundle.json b/public/locales/pt/bundle.json index 67ef8cdc..4e03002b 100644 --- a/public/locales/pt/bundle.json +++ b/public/locales/pt/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "IA Creativity Level", "settings.ai.creativityDescription": "Valores mais altos produzem resultados mais inesperados.", "settings.ai.customModel": "Modelo personalizado", + "settings.ai.downloadDesktopCta": "Transferir a aplicação de desktop", "settings.ai.fallbackNone": "Nenhum", "settings.ai.fallbackStep1": "Primeiro substituto", "settings.ai.fallbackStep2": "Segundo substituto", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Indisponível", "settings.ai.localBackendPreset": "Predefinição de back-end local", "settings.ai.ollamaBrowserNote": "Ollama está disponível apenas no aplicativo de desktop. A Política de Segurança de Conteúdo do navegador bloqueia conexões diretas com o host local.", - "settings.ai.ollamaHint": "Certifique-se de que ollama serve esteja em execução e que o CORS esteja ativado.", + "settings.ai.ollamaDesktopOnlyBody": "O Ollama e os servidores locais compatíveis com OpenAI (LM Studio, vLLM) só estão disponíveis na aplicação de desktop. Os navegadores bloqueiam ligações diretas a localhost (Content Security Policy e Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Aplicação de desktop necessária para servidores locais", + "settings.ai.ollamaHint": "Certifique-se de que o servidor está em execução (p. ex. ollama serve). A aplicação de desktop liga-se diretamente — sem configuração CORS.", "settings.ai.ollamaModelHint": "Selecione rapidamente os modelos relatados pelo seu servidor – toque para usar.", "settings.ai.ollamaServerUrl": "URL do servidor Ollama", "settings.ai.ollamaTauriBypass": "Construção para desktop: WorldScript chama Ollama diretamente – sem barreira CORS do navegador.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Digitalize portas locais comuns", "settings.ai.scanNo": "sem resposta", "settings.ai.scanOk": "alcançável", + "settings.ai.scanStateHttp": "erro HTTP", + "settings.ai.scanStateTimeout": "tempo limite excedido", + "settings.ai.scanUseUrl": "Usar este URL", "settings.ai.temperature.balanced": "1 – Equilibrado", "settings.ai.temperature.creative": "2 – Criativo", "settings.ai.temperature.precise": "0 – Preciso", diff --git a/public/locales/ru/bundle.json b/public/locales/ru/bundle.json index ebb2fde6..201b046c 100644 --- a/public/locales/ru/bundle.json +++ b/public/locales/ru/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "Уровень творчества ИИ", "settings.ai.creativityDescription": "Более высокие значения дают более неожиданные результаты.", "settings.ai.customModel": "Пользовательская модель", + "settings.ai.downloadDesktopCta": "Скачать настольное приложение", "settings.ai.fallbackNone": "Никто", "settings.ai.fallbackStep1": "Первый запасной вариант", "settings.ai.fallbackStep2": "Второй запасной вариант", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Нет в наличии", "settings.ai.localBackendPreset": "Локальная настройка серверной части", "settings.ai.ollamaBrowserNote": "Оллама доступен только в настольном приложении. Политика безопасности контента браузера блокирует прямые подключения к локальному хосту.", - "settings.ai.ollamaHint": "Убедитесь, что служба ollama работает и CORS включен.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama и локальные OpenAI-совместимые серверы (LM Studio, vLLM) доступны только в настольном приложении. Браузеры блокируют прямые подключения к localhost (Content Security Policy и Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Для локальных серверов требуется настольное приложение", + "settings.ai.ollamaHint": "Убедитесь, что сервер запущен (например, ollama serve). Настольное приложение подключается напрямую — настройка CORS не требуется.", "settings.ai.ollamaModelHint": "Быстрый выбор моделей, о которых сообщает ваш сервер. Нажмите, чтобы использовать.", "settings.ai.ollamaServerUrl": "URL-адрес сервера Оллама", "settings.ai.ollamaTauriBypass": "Сборка для настольных компьютеров: WorldScript напрямую вызывает Ollama — без барьера CORS браузера.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Сканировать общие локальные порты", "settings.ai.scanNo": "нет ответа", "settings.ai.scanOk": "достижимый", + "settings.ai.scanStateHttp": "ошибка HTTP", + "settings.ai.scanStateTimeout": "тайм-аут", + "settings.ai.scanUseUrl": "Использовать этот URL", "settings.ai.temperature.balanced": "1 – Сбалансированный", "settings.ai.temperature.creative": "2 – Креатив", "settings.ai.temperature.precise": "0 – Точный", diff --git a/public/locales/sv/bundle.json b/public/locales/sv/bundle.json index cbf7c40e..d1066093 100644 --- a/public/locales/sv/bundle.json +++ b/public/locales/sv/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "AI-kreativitetsnivå", "settings.ai.creativityDescription": "Högre värden ger mer oväntade resultat.", "settings.ai.customModel": "Anpassad modell", + "settings.ai.downloadDesktopCta": "Ladda ner skrivbordsappen", "settings.ai.fallbackNone": "Ingen", "settings.ai.fallbackStep1": "Första fallback", "settings.ai.fallbackStep2": "Andra fallback", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "Ej tillgängligt", "settings.ai.localBackendPreset": "Lokal förinställning av backend", "settings.ai.ollamaBrowserNote": "Ollama är endast tillgänglig i skrivbordsappen. Webbläsarens innehållssäkerhetspolicy blockerar direktanslutningar till localhost.", - "settings.ai.ollamaHint": "Se till att ollamaserven körs och att CORS är aktiverat.", + "settings.ai.ollamaDesktopOnlyBody": "Ollama och lokala OpenAI-kompatibla servrar (LM Studio, vLLM) är endast tillgängliga i skrivbordsappen. Webbläsare blockerar direkta anslutningar till localhost (Content Security Policy och Private Network Access).", + "settings.ai.ollamaDesktopOnlyTitle": "Skrivbordsappen krävs för lokala servrar", + "settings.ai.ollamaHint": "Se till att servern körs (t.ex. ollama serve). Skrivbordsappen ansluter direkt — ingen CORS-konfiguration behövs.", "settings.ai.ollamaModelHint": "Snabbvalsmodeller rapporterade av din server – tryck för att använda.", "settings.ai.ollamaServerUrl": "Ollama Server URL", "settings.ai.ollamaTauriBypass": "Skrivbordsbygge: WorldScript anropar Ollama direkt — ingen CORS-barriär för webbläsaren.", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "Skanna vanliga lokala portar", "settings.ai.scanNo": "inget svar", "settings.ai.scanOk": "nås", + "settings.ai.scanStateHttp": "HTTP-fel", + "settings.ai.scanStateTimeout": "tidsgräns överskriden", + "settings.ai.scanUseUrl": "Använd den här URL:en", "settings.ai.temperature.balanced": "1 – Balanserad", "settings.ai.temperature.creative": "2 – Kreativt", "settings.ai.temperature.precise": "0 – Exakt", diff --git a/public/locales/zh/bundle.json b/public/locales/zh/bundle.json index cc94fc6e..71eb47f2 100644 --- a/public/locales/zh/bundle.json +++ b/public/locales/zh/bundle.json @@ -1730,6 +1730,7 @@ "settings.ai.creativity": "人工智能创造力水平", "settings.ai.creativityDescription": "较高的值会产生更多意想不到的结果。", "settings.ai.customModel": "定制型号", + "settings.ai.downloadDesktopCta": "下载桌面应用", "settings.ai.fallbackNone": "没有任何", "settings.ai.fallbackStep1": "第一个后备", "settings.ai.fallbackStep2": "第二次后备", @@ -1813,7 +1814,9 @@ "settings.ai.localAi.webgpuUnavailable": "不可用", "settings.ai.localBackendPreset": "本地后端预设", "settings.ai.ollamaBrowserNote": "Ollama 仅在桌面应用程序中可用。浏览器的内容安全策略阻止与本地主机的直接连接。", - "settings.ai.ollamaHint": "确保 ollama 服务正在运行并且 CORS 已启用。", + "settings.ai.ollamaDesktopOnlyBody": "Ollama 和本地 OpenAI 兼容服务器(LM Studio、vLLM)仅在桌面应用中可用。浏览器会阻止与 localhost 的直接连接(内容安全策略和专用网络访问)。", + "settings.ai.ollamaDesktopOnlyTitle": "本地服务器需要桌面应用", + "settings.ai.ollamaHint": "请确保服务器正在运行(例如 ollama serve)。桌面应用直接连接,无需配置 CORS。", "settings.ai.ollamaModelHint": "快速选择服务器报告的模型 - 点击即可使用。", "settings.ai.ollamaServerUrl": "奥拉马服务器 URL", "settings.ai.ollamaTauriBypass": "桌面构建:WorldScript 直接调用 Ollama — 无浏览器 CORS 障碍。", @@ -1845,6 +1848,9 @@ "settings.ai.scanLocalPorts": "扫描本地常用端口", "settings.ai.scanNo": "没有回应", "settings.ai.scanOk": "可达的", + "settings.ai.scanStateHttp": "HTTP 错误", + "settings.ai.scanStateTimeout": "超时", + "settings.ai.scanUseUrl": "使用此 URL", "settings.ai.temperature.balanced": "1 – 平衡", "settings.ai.temperature.creative": "2 – 创意", "settings.ai.temperature.precise": "0 – 精确", From 14d036723d798a22b26783c94f8bf371b2e4152b Mon Sep 17 00:00:00 2001 From: qnbs <155236708+qnbs@users.noreply.github.com> Date: Sun, 26 Jul 2026 09:48:01 +0200 Subject: [PATCH 05/14] chore(collab): vendor-fork audit, bump 10.3.0-sc2, drop dead y-webrtc dep (#60) Full-file diff of packages/collab-transport against upstream y-webrtc 10.3.0: no deviations beyond the three documented SC patches (PBKDF2 600k, extractable:false, return-before-reject) + DataChannel E2E encryption. Recorded in packages/collab-transport/AUDIT.md; fork bumped to -sc2. Cleanup: removed the deprecated patches/y-webrtc@10.3.0.patch and the dead root y-webrtc dependency (zero imports). Created the previously-referenced- but-missing scripts/verify-vendor-fork.mjs invariant guard and wired it into package.json (verify:vendor) + the CI security job. --- .github/workflows/ci.yml | 5 + VENDOR-FORKS.md | 19 +- package.json | 4 +- packages/collab-transport/AUDIT.md | 56 + packages/collab-transport/package.json | 2 +- packages/collab-transport/src/crypto.js | 6 +- patches/y-webrtc@10.3.0.patch | 76 - pnpm-lock.yaml | 1798 +++++++++++++---------- scripts/verify-vendor-fork.mjs | 61 + 9 files changed, 1136 insertions(+), 891 deletions(-) create mode 100644 packages/collab-transport/AUDIT.md delete mode 100644 patches/y-webrtc@10.3.0.patch create mode 100644 scripts/verify-vendor-fork.mjs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b947d85..5e2af625 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,6 +48,11 @@ jobs: - name: pnpm audit (high + critical) run: pnpm audit --audit-level=high + # QNBS-v3 (#60): vendored y-webrtc fork invariant guard (PBKDF2 600k, non-extractable keys, + # DataChannel encryption, no dangling upstream dep) — fails the build on fork drift. + - name: Vendor fork invariant guard + run: pnpm run verify:vendor + # QNBS-v3: osv-scanner.toml (in src-tauri/) suppresses accepted RUSTSEC advisories for Cargo.lock; # scan both lockfiles so npm + Rust advisories are caught on every push - name: OSV vulnerability scan diff --git a/VENDOR-FORKS.md b/VENDOR-FORKS.md index 2fd09f22..4108408b 100644 --- a/VENDOR-FORKS.md +++ b/VENDOR-FORKS.md @@ -8,19 +8,24 @@ upstream monitoring and patch porting. | Attribute | Value | |-----------|-------| | **Upstream** | `y-webrtc@10.3.0` | -| **Fork version** | `10.3.0-sc1` | +| **Fork version** | `10.3.0-sc2` | | **Reason for fork** | E2E encryption (AES-256-GCM via Web Crypto) is not available upstream. The fork adds PBKDF2 key derivation, non-extractable CryptoKeys, and encrypted WebRTC DataChannels compatible with the y-webrtc signalling protocol. | | **Critical invariants** | 1. PBKDF2 iterations must remain **600,000** (OWASP 2024 SHA-256 minimum).
diff --git a/services/settingsSearchHints.ts b/services/settingsSearchHints.ts
index 6510a87b..b519cddd 100644
--- a/services/settingsSearchHints.ts
+++ b/services/settingsSearchHints.ts
@@ -53,13 +53,13 @@ export const SETTINGS_CATEGORY_SEARCH_HINTS: Record