diff --git a/README.md b/README.md index 82fa9c3c4..9395ebff7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - + @@ -351,7 +351,7 @@ One-click encrypted export of your entire project library from **Settings → Da ### 🌐 Full Multi-Language Support -Shipped UI locales with **2854 i18n keys** across all 19 languages — zero hardcoded user-facing strings: +Shipped UI locales with **2859 i18n keys** across all 19 languages — zero hardcoded user-facing strings: - 🇩🇪 **German** (Deutsch) - 🇬🇧 **English** @@ -460,7 +460,7 @@ The Settings → AI panel shows a live GPU status badge with adapter details and | **PDF Export** | jsPDF | Client-side, configurable PDF document generation | | **Document Export** | docx + jszip | Word-compatible `.docx` generation (lazy-loaded) | | **PWA** | Service Worker + Web App Manifest v3 | Offline support, installability, Workbox chunking | -| **i18n** | Custom React Context (`I18nContext.tsx`) | 2854 keys × 19 locales (de/en/es/fr/it + ar/he/fa RTL Beta + ja/zh/pt/el/fi/sv/hu/is/eu Beta); EN fallback; `localStorage` persistence | +| **i18n** | Custom React Context (`I18nContext.tsx`) | 2859 keys × 19 locales (de/en/es/fr/it + ar/he/fa RTL Beta + ja/zh/pt/el/fi/sv/hu/is/eu Beta); EN fallback; `localStorage` persistence | | **Testing** | Vitest 4.x (5807+ tests / 527 files) + Playwright E2E | Unit/integration + cross-browser E2E; Stryker mutation (manual workflow) | | **Code Quality** | Biome (lint + format) + TypeScript 7 (tsgo) strict | `--error-on-warnings` in CI; zero `any` policy | | **Visualization** | Force-directed graph | Interactive character relationship network | @@ -659,7 +659,7 @@ The main pipeline is [`.github/workflows/ci.yml`](.github/workflows/ci.yml). Opt **Current test metrics (2026-07-28):** - **5807+ unit tests** across **527 test files** — all passing - Coverage thresholds: lines ≥ 74 · branches ≥ 60 · functions ≥ 67 · statements ≥ 72 — enforced in CI (see Codecov badge for live metrics) -- i18n: **2854 keys × 19 locales** (en/de/fr/es/it + ar/he/fa RTL Beta + ja/zh/pt/el/fi/sv/hu/is/eu Beta) +- i18n: **2859 keys × 19 locales** (en/de/fr/es/it + ar/he/fa RTL Beta + ja/zh/pt/el/fi/sv/hu/is/eu Beta) **CI-cloud-first workflow (recommended):** On constrained hardware run **`pnpm run lint && pnpm run i18n:check && pnpm run typecheck`** locally, then push and let CI handle coverage, E2E, Lighthouse, and Stryker. Authoritative numbers come from CI artifacts (Codecov, JUnit). After CI goes green, update the README badges and `AUDIT.md` quality-gate line from the reported metrics. See **[`docs/CI.md`](docs/CI.md) § Cloud CI-first vs local development** for the full post-merge doc-update checklist. diff --git a/components/settings/OpenRouterSection.tsx b/components/settings/OpenRouterSection.tsx index 7137d8f1d..7677cccf8 100644 --- a/components/settings/OpenRouterSection.tsx +++ b/components/settings/OpenRouterSection.tsx @@ -20,7 +20,7 @@ import { import { getApproxRpm, isCircuitOpen, - OPENROUTER_FREE_MODELS, + OPENROUTER_FREE_MODEL_FALLBACK, resetOpenRouterCircuit, } from '../../services/ai/providers/openrouterProvider'; import { logger } from '../../services/logger'; @@ -33,6 +33,18 @@ import { Spinner } from '../ui/Spinner'; const CUSTOM_MODEL_VALUE = '__custom__'; +// QNBS-v3: i18n label suffix for each OPENROUTER_FREE_MODEL_FALLBACK entry — only rendered when +// the live catalog has no `:free` models at all (offline, fetch failure, or a genuinely empty +// catalog). Live-fetched free models use the catalog's own `name` field instead. +const FALLBACK_MODEL_LABEL_SUFFIX: Record<(typeof OPENROUTER_FREE_MODEL_FALLBACK)[number], string> = + { + 'deepseek/deepseek-r1:free': 'deepseekR1', + 'meta-llama/llama-3.3-70b-instruct:free': 'llama3370b', + 'qwen/qwen2.5-72b-instruct:free': 'qwen2572b', + 'google/gemma-3-27b-it:free': 'gemma327b', + 'mistralai/mistral-7b-instruct:free': 'mistral7b', + }; + // ─── Sub-component: circuit breaker status indicator ───────────────────────── const CircuitBreakerStatus: FC<{ t: ReturnType['t'] }> = ({ t }) => { @@ -128,7 +140,9 @@ export const OpenRouterSection: FC = () => { }, []); const enabled = openRouterSettings?.enabled ?? false; - const preferredModel = openRouterSettings?.preferredModel ?? 'deepseek/deepseek-r1:free'; + // QNBS-v3: Derived from the offline fallback, not a re-typed literal — this is the component's + // local default before Redux settings load, not a primary model source. + const preferredModel = openRouterSettings?.preferredModel ?? OPENROUTER_FREE_MODEL_FALLBACK[0]; const [apiKeyInput, setApiKeyInput] = useState(''); const [storedKey, setStoredKey] = useState(null); @@ -142,7 +156,9 @@ export const OpenRouterSection: FC = () => { const [isModelsLoading, setIsModelsLoading] = useState(false); const [modelFetchError, setModelFetchError] = useState(null); const [isCustomModel, setIsCustomModel] = useState( - !OPENROUTER_FREE_MODELS.includes(preferredModel as (typeof OPENROUTER_FREE_MODELS)[number]), + !OPENROUTER_FREE_MODEL_FALLBACK.includes( + preferredModel as (typeof OPENROUTER_FREE_MODEL_FALLBACK)[number], + ), ); const [customModelInput, setCustomModelInput] = useState(isCustomModel ? preferredModel : ''); const saveMsgTimer = useRef | null>(null); @@ -223,16 +239,90 @@ export const OpenRouterSection: FC = () => { }; }, [fetchCatalog, storedKey]); - // Keep local custom-model state in sync with external Redux changes. + // QNBS-v3: Free-tier group is derived from the LIVE catalog, not the frozen fallback constant — + // OpenRouter's free tier rotates weekly, and a hardcoded primary list silently drops new free + // models from the UI (the OR-1 bug this refactor fixes). Only fall back to the static list when + // the live catalog has no `:free` models at all. + const liveFreeModels = useMemo(() => models.filter((m) => isOpenRouterFreeModel(m.id)), [models]); + const usingFallbackFreeModels = liveFreeModels.length === 0; + // QNBS-v3: ID-only, deliberately independent of `t` — this feeds knownOptionIds (the redux-sync + // effect, selectValue, commitCustomModel all depend on it), which must stay referentially stable + // across a render that only changed an unrelated piece of state. If it depended on `t` (via the + // label-bearing modelGroups) instead, an unstable translation-function reference would make the + // redux-sync effect re-run on every render and stomp the user's in-progress custom-model entry. + const freeModelIds = useMemo( + () => + usingFallbackFreeModels + ? [...OPENROUTER_FREE_MODEL_FALLBACK] + : liveFreeModels.map((m) => m.id), + [usingFallbackFreeModels, liveFreeModels], + ); + const paidModelIds = useMemo( + () => models.filter((m) => !isOpenRouterFreeModel(m.id)).map((m) => m.id), + [models], + ); + const freeModelOptions = useMemo( + () => + usingFallbackFreeModels + ? OPENROUTER_FREE_MODEL_FALLBACK.map((m) => ({ + value: m as string, + label: t(`settings.openRouter.freeModel.${FALLBACK_MODEL_LABEL_SUFFIX[m]}`), + })) + : liveFreeModels.map((m) => ({ value: m.id, label: m.name ?? m.id })), + [usingFallbackFreeModels, liveFreeModels, t], + ); + // QNBS-v3: OR-1 fix — filter solely by isOpenRouterFreeModel; the former extra `freeIds` set + // (membership in the hardcoded list) caused any live-fetched free model NOT on that list to be + // dropped from both the free AND paid groups instead of appearing in the free group. + const paidModelOptions = useMemo( + () => + models + .filter((m) => !isOpenRouterFreeModel(m.id)) + .map((m) => ({ value: m.id, label: m.name ?? m.id })), + [models], + ); + const modelGroups = useMemo(() => { + const groups: { label: string; options: { value: string; label: string }[] }[] = [ + { label: t('settings.openRouter.freeTierNote'), options: freeModelOptions }, + ]; + if (paidModelOptions.length > 0) { + groups.push({ label: t('settings.openRouter.paidModelNote'), options: paidModelOptions }); + } + groups.push({ + label: t('settings.openRouter.customModelLabel'), + options: [{ value: CUSTOM_MODEL_VALUE, label: t('settings.openRouter.customModelLabel') }], + }); + return groups; + }, [freeModelOptions, paidModelOptions, t]); + // QNBS-v3: OR-3 fix — the actual set of selectable values (free ∪ paid ∪ custom sentinel), NOT + // `new Set(models.map(...))` (which was mislabeled "knownPaidIds" and included free models too). + // `selectValue` previously trusted this broader-than-rendered set, so a live-fetched free model + // not on the hardcoded list could report as "known" while having no matching — a silent + // Select/state divergence. Built from freeModelIds/paidModelIds (not modelGroups) so it stays + // referentially stable independent of `t` — see the freeModelIds comment above. + const knownOptionIds = useMemo( + () => new Set([...freeModelIds, ...paidModelIds, CUSTOM_MODEL_VALUE]), + [freeModelIds, paidModelIds], + ); + + // QNBS-v3: knownOptionIds gets a new Set identity on every catalog fetch (mount, refresh + // button), not just when preferredModel changes — only resync customModelInput when + // preferredModel itself changed, so a refresh mid-edit can't stomp the user's typed text. + const prevPreferredModelRef = useRef(preferredModel); + // QNBS-v3: tracks an ID the user explicitly committed via the custom-model input, so the + // stale-model warning below can't misfire for it — see modelIsStale. State, not a ref: it's + // read directly in the render body, and a ref mutation alone wouldn't trigger a re-render. + const [explicitCustomId, setExplicitCustomId] = useState(null); useEffect(() => { - const free = OPENROUTER_FREE_MODELS.includes( - preferredModel as (typeof OPENROUTER_FREE_MODELS)[number], - ); - const knownPaid = models.some((m) => m.id === preferredModel); - setIsCustomModel(!free && !knownPaid); - if (free || knownPaid) setCustomModelInput(''); - else setCustomModelInput(preferredModel); - }, [preferredModel, models]); + const known = knownOptionIds.has(preferredModel); + setIsCustomModel(!known); + if (known) { + setCustomModelInput(''); + } else if (prevPreferredModelRef.current !== preferredModel) { + setCustomModelInput(preferredModel); + } + prevPreferredModelRef.current = preferredModel; + }, [preferredModel, knownOptionIds]); const showSaveMsg = useCallback((ok: boolean, text: string) => { setSaveMsg({ ok, text }); @@ -371,6 +461,7 @@ export const OpenRouterSection: FC = () => { if (value === CUSTOM_MODEL_VALUE) { setIsCustomModel(true); } else { + setExplicitCustomId(null); setIsCustomModel(false); setCustomModelInput(''); dispatch(settingsActions.setOpenRouter({ preferredModel: value })); @@ -382,18 +473,18 @@ export const OpenRouterSection: FC = () => { const commitCustomModel = useCallback(() => { const trimmed = customModelInput.trim(); if (trimmed) { + // QNBS-v3: remembers this exact ID was deliberately entered as custom, so a later catalog + // refresh that doesn't list it can't misreport it as a removed/stale catalog model. + setExplicitCustomId(trimmed); dispatch(settingsActions.setOpenRouter({ preferredModel: trimmed })); return; } // QNBS-v3: Empty custom input — revert the selection to the actually-configured model so the UI // doesn't show "custom" selected while the stored model stays unchanged (keeps UI ↔ config in sync). - const free = OPENROUTER_FREE_MODELS.includes( - preferredModel as (typeof OPENROUTER_FREE_MODELS)[number], - ); - const storedIsCustom = !free && !models.some((m) => m.id === preferredModel); + const storedIsCustom = !knownOptionIds.has(preferredModel); setIsCustomModel(storedIsCustom); setCustomModelInput(storedIsCustom ? preferredModel : ''); - }, [customModelInput, dispatch, preferredModel, models]); + }, [customModelInput, dispatch, preferredModel, knownOptionIds]); const handleCustomModelBlur = useCallback(() => { commitCustomModel(); @@ -409,6 +500,27 @@ export const OpenRouterSection: FC = () => { [commitCustomModel], ); + // QNBS-v3: OR-5 fix — manual refresh. Clears the 1h cache and re-fetches immediately so the user + // isn't stuck waiting out the cache TTL to see a newly-released free model. + const handleRefreshCatalog = useCallback(() => { + clearOpenRouterModelCache(); + void fetchCatalog(storedKey); + }, [fetchCatalog, storedKey]); + + // QNBS-v3: OR-2 fix — a successful, non-blocked, non-loading fetch means `knownOptionIds` + // reflects the CURRENT catalog; only then can "preferredModel isn't in it" mean the model is + // actually gone (vs. still loading, or cloud access being policy-blocked). + const catalogReady = !isModelsLoading && !modelFetchError && !policyBlocked; + // QNBS-v3: exempt an ID the user explicitly entered as custom this session — otherwise a + // deliberate non-catalog model gets nagged as if it were a removed catalog selection. + const modelIsStale = + catalogReady && !knownOptionIds.has(preferredModel) && explicitCustomId !== preferredModel; + + const handleSwitchToAvailableModel = useCallback(() => { + const fallbackId = freeModelOptions[0]?.value ?? OPENROUTER_FREE_MODEL_FALLBACK[0]; + dispatch(settingsActions.setOpenRouter({ preferredModel: fallbackId })); + }, [dispatch, freeModelOptions]); + // Cleanup on unmount. useEffect(() => { return () => { @@ -419,57 +531,12 @@ export const OpenRouterSection: FC = () => { }; }, []); - const knownPaidIds = useMemo(() => new Set(models.map((m) => m.id)), [models]); - const selectValue = useMemo(() => { if (isCustomModel) return CUSTOM_MODEL_VALUE; - const free = OPENROUTER_FREE_MODELS.includes( - preferredModel as (typeof OPENROUTER_FREE_MODELS)[number], - ); - // QNBS-v3: Paid catalog models are known by id, so keep the real value instead of falling back to custom. - if (free || knownPaidIds.has(preferredModel)) return preferredModel; - return CUSTOM_MODEL_VALUE; - }, [isCustomModel, preferredModel, knownPaidIds]); - - const modelOptions = useMemo( - () => - OPENROUTER_FREE_MODELS.map((m) => ({ - value: m, - label: t( - `settings.openRouter.freeModel.${ - { - 'deepseek/deepseek-r1:free': 'deepseekR1', - 'meta-llama/llama-3.3-70b-instruct:free': 'llama3370b', - 'qwen/qwen2.5-72b-instruct:free': 'qwen2572b', - 'google/gemma-3-27b-it:free': 'gemma327b', - 'mistralai/mistral-7b-instruct:free': 'mistral7b', - }[m] - }`, - ), - })), - [t], - ); - - const fetchedPaidOptions = useMemo(() => { - const freeIds = new Set(OPENROUTER_FREE_MODELS); - return models - .filter((m) => !freeIds.has(m.id) && !isOpenRouterFreeModel(m.id)) - .map((m) => ({ value: m.id, label: m.name ?? m.id })); - }, [models]); - - const modelGroups = useMemo(() => { - const groups: { label: string; options: { value: string; label: string }[] }[] = [ - { label: t('settings.openRouter.freeTierNote'), options: modelOptions }, - ]; - if (fetchedPaidOptions.length > 0) { - groups.push({ label: t('settings.openRouter.paidModelNote'), options: fetchedPaidOptions }); - } - groups.push({ - label: t('settings.openRouter.customModelLabel'), - options: [{ value: CUSTOM_MODEL_VALUE, label: t('settings.openRouter.customModelLabel') }], - }); - return groups; - }, [modelOptions, fetchedPaidOptions, t]); + // QNBS-v3: OR-3 fix — check against the actually-rendered option set, not a broader "known + // models" set that could include an ID with no matching . + return knownOptionIds.has(preferredModel) ? preferredModel : CUSTOM_MODEL_VALUE; + }, [isCustomModel, preferredModel, knownOptionIds]); const modeWarning = useMemo(() => { if (aiMode === 'local') return t('settings.openRouter.modeWarning.local'); @@ -627,12 +694,23 @@ export const OpenRouterSection: FC = () => { {/* Preferred model */} - - {t('settings.openRouter.preferredModel')} - + + + {t('settings.openRouter.preferredModel')} + + + {t('settings.openRouter.refreshModels')} + + {isModelsLoading && ( @@ -644,6 +722,11 @@ export const OpenRouterSection: FC = () => { {modelFetchError} )} + {!isModelsLoading && usingFallbackFreeModels && ( + + {t('settings.openRouter.freeModel.fallbackNotice')} + + )} {!isModelsLoading && ( { aria-label={t('settings.openRouter.customModelAriaLabel')} /> )} + {modelIsStale && ( + + + {t('settings.openRouter.modelUnavailable')} + + + {t('settings.openRouter.switchToAvailableModel')} + + + )} {t('settings.openRouter.freeTierNote')} diff --git a/locales/ar/settings.json b/locales/ar/settings.json index a1daf5e42..6de202c70 100644 --- a/locales/ar/settings.json +++ b/locales/ar/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – إبداعي", "settings.ai.temperature.precise": "0 – دقيق", "settings.ai.testConnection": "اختبار الاتصال", - "settings.ai.testError.noApiKey": "لم يتم تعيين مفتاح API لـ {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "انتهت مهلة الاتصال ({{url}})", - "settings.ai.testError.unreachable": "غير قابل للوصول ({{url}})", - "settings.ai.testError.pluginUnavailable": "شبكة الخادم المحلي غير متوفرة: فشل تحميل مكوّن HTTP لسطح المكتب.", - "settings.ai.testError.desktopRequired": "تتوفر Ollama والخوادم المحلية المتوافقة مع OpenAI فقط في تطبيق سطح المكتب. تحظر المتصفحات الاتصالات المباشرة من صفحات الويب بـ localhost (CORS وPrivate Network Access).", "settings.ai.testError.backendProxyRequired": "يتطلب Claude وكيل خلفية (قيود CORS)", + "settings.ai.testError.desktopRequired": "تتوفر Ollama والخوادم المحلية المتوافقة مع OpenAI فقط في تطبيق سطح المكتب. تحظر المتصفحات الاتصالات المباشرة من صفحات الويب بـ localhost (CORS وPrivate Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "لم يتم تعيين مفتاح API لـ {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU غير متوفر في هذا المتصفح — يحتاج WebLLM إلى WebGPU (جرّب Chrome/Edge أو فعّل العلامات).", - "settings.ai.testError.unknownProvider": "مزوّد غير معروف", + "settings.ai.testError.pluginUnavailable": "شبكة الخادم المحلي غير متوفرة: فشل تحميل مكوّن HTTP لسطح المكتب.", + "settings.ai.testError.timeout": "انتهت مهلة الاتصال ({{url}})", "settings.ai.testError.unexpected": "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى.", + "settings.ai.testError.unknownProvider": "مزوّد غير معروف", + "settings.ai.testError.unreachable": "غير قابل للوصول ({{url}})", "settings.ai.title": "إعداد الذكاء الاصطناعي", "settings.ai.transformers.hint": "يشغّل أي نموذج HuggingFace متوافق مع Xenova محليًا عبر WebAssembly أو WebGPU.", "settings.ai.transformers.modelId": "معرّف النموذج (HuggingFace)", @@ -599,6 +599,7 @@ "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.fallbackNotice": "يتم عرض قائمة احتياطية ثابتة — كتالوج OpenRouter المباشر غير متاح حاليًا.", "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)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Could not load model catalog", "settings.openRouter.modelFetch.loading": "Loading model catalog…", "settings.openRouter.modelPlaceholder": "deepseek/deepseek-r1:free", + "settings.openRouter.modelUnavailable": "هذا النموذج غير موجود في الكتالوج الحالي.", "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.refreshModels": "تحديث النماذج", + "settings.openRouter.refreshModelsAriaLabel": "تحديث كتالوج نماذج OpenRouter", "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.switchToAvailableModel": "التبديل إلى نموذج مجاني متاح", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/locales/de/settings.json b/locales/de/settings.json index 91dda507f..8f9799ed3 100644 --- a/locales/de/settings.json +++ b/locales/de/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Kreativ", "settings.ai.temperature.precise": "0 – Präzise", "settings.ai.testConnection": "Verbindung testen", - "settings.ai.testError.noApiKey": "Kein {{provider}} API-Schlüssel gesetzt", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Zeitüberschreitung bei der Verbindung ({{url}})", - "settings.ai.testError.unreachable": "Nicht erreichbar ({{url}})", - "settings.ai.testError.pluginUnavailable": "Lokale Serververnetzung nicht verfügbar: Das Desktop-HTTP-Plugin konnte nicht geladen werden.", - "settings.ai.testError.desktopRequired": "Ollama und lokale OpenAI-kompatible Server sind nur in der Desktop-App verfügbar. Browser blockieren direkte Verbindungen von Webseiten zu localhost (CORS und Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude benötigt einen Backend-Proxy (CORS-Einschränkung)", + "settings.ai.testError.desktopRequired": "Ollama und lokale OpenAI-kompatible Server sind nur in der Desktop-App verfügbar. Browser blockieren direkte Verbindungen von Webseiten zu localhost (CORS und Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Kein {{provider}} API-Schlüssel gesetzt", "settings.ai.testError.noWebgpu": "WebGPU in diesem Browser nicht verfügbar — WebLLM benötigt WebGPU (Chrome/Edge verwenden oder Flags aktivieren).", - "settings.ai.testError.unknownProvider": "Unbekannter Anbieter", + "settings.ai.testError.pluginUnavailable": "Lokale Serververnetzung nicht verfügbar: Das Desktop-HTTP-Plugin konnte nicht geladen werden.", + "settings.ai.testError.timeout": "Zeitüberschreitung bei der Verbindung ({{url}})", "settings.ai.testError.unexpected": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.", + "settings.ai.testError.unknownProvider": "Unbekannter Anbieter", + "settings.ai.testError.unreachable": "Nicht erreichbar ({{url}})", "settings.ai.title": "KI-Konfiguration", "settings.ai.transformers.hint": "Führt jedes Xenova-kompatible HuggingFace-Modell lokal via WebAssembly oder WebGPU aus.", "settings.ai.transformers.modelId": "Modell-ID (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Wenn aktiviert, wird OpenRouter für Cloud-KI-Aufrufe bevorzugt, sofern der aktive Modus Cloud nicht verbietet.", "settings.openRouter.errors.generic": "Ein unerwarteter OpenRouter-Fehler ist aufgetreten", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Es wird die statische Fallback-Liste angezeigt — der Live-Modellkatalog von OpenRouter ist gerade nicht verfügbar.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Modellkatalog konnte nicht geladen werden", "settings.openRouter.modelFetch.loading": "Modellkatalog wird geladen …", "settings.openRouter.modelPlaceholder": "Modell auswählen oder suchen", + "settings.openRouter.modelUnavailable": "Dieses Modell ist nicht im aktuellen Katalog enthalten.", "settings.openRouter.paidModelNote": "Kostenpflichtige Modelle benötigen Guthaben auf deinem OpenRouter-Konto.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter ist blockiert, weil „Nur lokaler Speicher“ aktiviert ist. Deaktiviere es unter „Datenschutz & Daten“, um Cloud-KI zu erlauben.", "settings.openRouter.policyBlocked.mode": "OpenRouter ist im KI-Modus „Lokal“ oder „Eco“ nicht verfügbar. Wechsle unter „KI & Modelle“ zu Hybrid oder Cloud, um es zu nutzen.", "settings.openRouter.preferredModel": "Bevorzugtes Modell", + "settings.openRouter.refreshModels": "Modelle aktualisieren", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter-Modellkatalog aktualisieren", "settings.openRouter.resetCircuit": "Zurücksetzen", "settings.openRouter.resetCircuitAria": "OpenRouter-Schutzschalter zurücksetzen", "settings.openRouter.rpmLabel": "Anfragen / Min (letzte 60 s)", "settings.openRouter.saveKey": "Speichern", + "settings.openRouter.switchToAvailableModel": "Zu einem verfügbaren Free-Modell wechseln", "settings.openRouter.testConnection": "Verbindung testen", "settings.openRouter.testConnectionFailed": "Verbindung fehlgeschlagen", "settings.openRouter.testConnectionOk": "Verbindung erfolgreich", diff --git a/locales/el/common.json b/locales/el/common.json index c5655b6c6..7c9c48c04 100644 --- a/locales/el/common.json +++ b/locales/el/common.json @@ -347,7 +347,7 @@ "proforge.progress.metric.totalTime": "Συνολικός χρόνος", "proforge.progress.metric.totalTokens": "Σύνολο Μαρκών", "proforge.progress.noneRunning": "Δεν λειτουργεί αγωγός.", - "proforge.progress.stageDetails": "Λεπτομέρειες σκηνής: {{stage}}", + "proforge.progress.stageDetails": "Λεπτομέρειες σταδίου: {{stage}}", "proforge.progress.statusLabel": "Κατάσταση", "proforge.progress.totals": "Σύνολα αγωγών", "proforge.review.accept": "Αποδέχομαι", diff --git a/locales/el/settings.json b/locales/el/settings.json index d4012eab5..c7db449cb 100644 --- a/locales/el/settings.json +++ b/locales/el/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Δημιουργικό", "settings.ai.temperature.precise": "0 – Ακριβές", "settings.ai.testConnection": "Δοκιμαστική σύνδεση", - "settings.ai.testError.noApiKey": "Δεν έχει οριστεί κλειδί API {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Λήξη χρονικού ορίου σύνδεσης ({{url}})", - "settings.ai.testError.unreachable": "Μη προσβάσιμο ({{url}})", - "settings.ai.testError.pluginUnavailable": "Το δίκτυο τοπικού διακομιστή δεν είναι διαθέσιμο: η πρόσθετη λειτουργία HTTP επιφάνειας εργασίας απέτυχε να φορτωθεί.", - "settings.ai.testError.desktopRequired": "Το Ollama και οι τοπικοί διακομιστές συμβατοί με OpenAI είναι διαθέσιμοι μόνο στην εφαρμογή επιφάνειας εργασίας. Οι φυλλομετρητές αποκλείουν άμεσες συνδέσεις από ιστοσελίδες προς το localhost (CORS και Private Network Access).", "settings.ai.testError.backendProxyRequired": "Το Claude απαιτεί διακομιστή μεσολάβησης backend (περιορισμός CORS)", + "settings.ai.testError.desktopRequired": "Το Ollama και οι τοπικοί διακομιστές συμβατοί με OpenAI είναι διαθέσιμοι μόνο στην εφαρμογή επιφάνειας εργασίας. Οι φυλλομετρητές αποκλείουν άμεσες συνδέσεις από ιστοσελίδες προς το localhost (CORS και Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Δεν έχει οριστεί κλειδί API {{provider}}", "settings.ai.testError.noWebgpu": "Το WebGPU δεν είναι διαθέσιμο σε αυτό το πρόγραμμα περιήγησης — το WebLLM απαιτεί WebGPU (δοκιμάστε Chrome/Edge ή ενεργοποιήστε τις σημαίες).", - "settings.ai.testError.unknownProvider": "Άγνωστος πάροχος", + "settings.ai.testError.pluginUnavailable": "Το δίκτυο τοπικού διακομιστή δεν είναι διαθέσιμο: η πρόσθετη λειτουργία HTTP επιφάνειας εργασίας απέτυχε να φορτωθεί.", + "settings.ai.testError.timeout": "Λήξη χρονικού ορίου σύνδεσης ({{url}})", "settings.ai.testError.unexpected": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα. Δοκιμάστε ξανά.", + "settings.ai.testError.unknownProvider": "Άγνωστος πάροχος", + "settings.ai.testError.unreachable": "Μη προσβάσιμο ({{url}})", "settings.ai.title": "Διαμόρφωση AI", "settings.ai.transformers.hint": "Εκτελεί οποιοδήποτε μοντέλο HuggingFace συμβατό με Xenova τοπικά μέσω WebAssembly ή WebGPU.", "settings.ai.transformers.modelId": "Αναγνωριστικό μοντέλου (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Όταν είναι ενεργό, το OpenRouter προτιμάται για κλήσεις AI cloud, εκτός αν η ενεργή λειτουργία απαγορεύει το cloud.", "settings.openRouter.errors.generic": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (δωρεάν)", + "settings.openRouter.freeModel.fallbackNotice": "Εμφάνιση της στατικής εφεδρικής λίστας — ο ζωντανός κατάλογος του OpenRouter δεν είναι διαθέσιμος αυτήν τη στιγμή.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (δωρεάν)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (δωρεάν)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (δωρεάν)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Δεν ήταν δυνατή η φόρτωση του καταλόγου μοντέλων", "settings.openRouter.modelFetch.loading": "Φόρτωση καταλόγου μοντέλων…", "settings.openRouter.modelPlaceholder": "Επίλεξε ή αναζήτησε ένα μοντέλο", + "settings.openRouter.modelUnavailable": "Αυτό το μοντέλο δεν υπάρχει στον τρέχοντα κατάλογο.", "settings.openRouter.paidModelNote": "Τα επί πληρωμή μοντέλα απαιτούν πιστώσεις στον λογαριασμό σου OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "Το OpenRouter αποκλείεται επειδή είναι ενεργή η «Μόνο τοπική αποθήκευση». Απενεργοποιήστε την στο «Απόρρητο και Δεδομένα» για να επιτρέψετε το cloud AI.", "settings.openRouter.policyBlocked.mode": "Το OpenRouter δεν είναι διαθέσιμο όταν η λειτουργία AI είναι «Τοπική» ή «Eco». Μεταβείτε σε «Υβριδική» ή «Cloud» στο «AI και Μοντέλα» για να το χρησιμοποιήσετε.", "settings.openRouter.preferredModel": "Προτιμώμενο μοντέλο", + "settings.openRouter.refreshModels": "Ανανέωση μοντέλων", + "settings.openRouter.refreshModelsAriaLabel": "Ανανέωση του καταλόγου μοντέλων OpenRouter", "settings.openRouter.resetCircuit": "Επαναφορά", "settings.openRouter.resetCircuitAria": "Επαναφορά του διακόπτη προστασίας OpenRouter", "settings.openRouter.rpmLabel": "Αιτήματα / λεπτό (τελευταία 60 δ)", "settings.openRouter.saveKey": "Αποθήκευση", + "settings.openRouter.switchToAvailableModel": "Μετάβαση σε διαθέσιμο δωρεάν μοντέλο", "settings.openRouter.testConnection": "Δοκιμή σύνδεσης", "settings.openRouter.testConnectionFailed": "Αποτυχία σύνδεσης", "settings.openRouter.testConnectionOk": "Επιτυχής σύνδεση", diff --git a/locales/en/settings.json b/locales/en/settings.json index 6288ed233..d1f8f829e 100644 --- a/locales/en/settings.json +++ b/locales/en/settings.json @@ -599,6 +599,7 @@ "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.fallbackNotice": "Showing the static fallback list — the live OpenRouter catalog is unavailable right now.", "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)", @@ -621,14 +622,18 @@ "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.modelUnavailable": "This model isn't in the current catalog.", "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.refreshModels": "Refresh models", + "settings.openRouter.refreshModelsAriaLabel": "Refresh the OpenRouter model catalog", "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.switchToAvailableModel": "Switch to an available free model", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/locales/es/settings.json b/locales/es/settings.json index 806487afa..ebcb17b84 100644 --- a/locales/es/settings.json +++ b/locales/es/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Probar conexión", - "settings.ai.testError.noApiKey": "No se ha configurado una clave de API de {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tiempo de espera agotado ({{url}})", - "settings.ai.testError.unreachable": "No accesible ({{url}})", - "settings.ai.testError.pluginUnavailable": "La red de servidores locales no está disponible: el plugin HTTP de escritorio no se pudo cargar.", - "settings.ai.testError.desktopRequired": "Ollama y los servidores locales compatibles con OpenAI solo están disponibles en la aplicación de escritorio. Los navegadores bloquean las conexiones directas desde páginas web a localhost (CORS y Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude requiere un proxy de backend (restricción CORS)", + "settings.ai.testError.desktopRequired": "Ollama y los servidores locales compatibles con OpenAI solo están disponibles en la aplicación de escritorio. Los navegadores bloquean las conexiones directas desde páginas web a localhost (CORS y Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "No se ha configurado una clave de API de {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU no disponible en este navegador — WebLLM necesita WebGPU (prueba Chrome/Edge o activa las opciones).", - "settings.ai.testError.unknownProvider": "Proveedor desconocido", + "settings.ai.testError.pluginUnavailable": "La red de servidores locales no está disponible: el plugin HTTP de escritorio no se pudo cargar.", + "settings.ai.testError.timeout": "Tiempo de espera agotado ({{url}})", "settings.ai.testError.unexpected": "Se produjo un error inesperado. Inténtalo de nuevo.", + "settings.ai.testError.unknownProvider": "Proveedor desconocido", + "settings.ai.testError.unreachable": "No accesible ({{url}})", "settings.ai.title": "Configuración de IA", "settings.ai.transformers.hint": "Ejecuta cualquier modelo HuggingFace compatible con Xenova localmente vía WebAssembly o WebGPU.", "settings.ai.transformers.modelId": "ID del modelo (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Cuando está activado, se prefiere OpenRouter para las llamadas de IA en la nube, salvo que el modo activo prohíba la nube.", "settings.openRouter.errors.generic": "Se produjo un error inesperado de OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Mostrando la lista de reserva estática — el catálogo en vivo de OpenRouter no está disponible en este momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "No se pudo cargar el catálogo de modelos", "settings.openRouter.modelFetch.loading": "Cargando catálogo de modelos…", "settings.openRouter.modelPlaceholder": "Selecciona o busca un modelo", + "settings.openRouter.modelUnavailable": "Este modelo no está en el catálogo actual.", "settings.openRouter.paidModelNote": "Los modelos de pago requieren créditos en tu cuenta de OpenRouter.", - "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.localOnly": "OpenRouter está bloqueado porque “Solo almacenamiento local” está activado. Desactívalo 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.refreshModels": "Actualizar modelos", + "settings.openRouter.refreshModelsAriaLabel": "Actualizar el catálogo de modelos de OpenRouter", "settings.openRouter.resetCircuit": "Restablecer", "settings.openRouter.resetCircuitAria": "Restablecer el cortacircuitos de OpenRouter", "settings.openRouter.rpmLabel": "Solicitudes / min (últimos 60 s)", "settings.openRouter.saveKey": "Guardar", + "settings.openRouter.switchToAvailableModel": "Cambiar a un modelo gratuito disponible", "settings.openRouter.testConnection": "Probar conexión", "settings.openRouter.testConnectionFailed": "Error de conexión", "settings.openRouter.testConnectionOk": "Conexión correcta", diff --git a/locales/eu/common.json b/locales/eu/common.json index 27f07d5b7..bf8844604 100644 --- a/locales/eu/common.json +++ b/locales/eu/common.json @@ -663,7 +663,7 @@ "voice.cancelSpeech": "Hitzaldia bertan behera utzi", "voice.modeChip.commands": "Komandoak", "voice.modeChip.dictation": "Diktaketa", - "voice.feedback.confidence": "Konfiantza %{{percent}}", + "voice.feedback.confidence": "Konfiantza: {{percent}}%", "voice.panelLabel": "Ahots kontrola", "voice.permissionDenied": "Mikrofonorako sarbidea ukatu da. Mesedez, baimendu mikrofonorako sarbidea zure arakatzailearen ezarpenetan ahots-eginbideak erabiltzeko.", "voice.startDictation": "Hasi diktaketa", diff --git a/locales/eu/settings.json b/locales/eu/settings.json index 473e7f4cb..875d914d6 100644 --- a/locales/eu/settings.json +++ b/locales/eu/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Sormena", "settings.ai.temperature.precise": "0 – Zehatza", "settings.ai.testConnection": "Probatu konexioa", - "settings.ai.testError.noApiKey": "Ez da {{provider}} API gakorik ezarri", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Konexioak denbora-muga gainditu du ({{url}})", - "settings.ai.testError.unreachable": "Ezin da iritsi ({{url}})", - "settings.ai.testError.pluginUnavailable": "Zerbitzari lokalaren sarea ez dago erabilgarri: mahaigaineko HTTP pluginak huts egin du kargatzean.", - "settings.ai.testError.desktopRequired": "Ollama eta OpenAI-rekin bateragarriak diren zerbitzari lokalak mahaigaineko aplikazioan bakarrik daude erabilgarri. Nabigatzaileek web orrialdeetatik localhost-era zuzeneko konexioak blokeatzen dituzte (CORS eta Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude-k backend proxy bat behar du (CORS murrizketa)", + "settings.ai.testError.desktopRequired": "Ollama eta OpenAI-rekin bateragarriak diren zerbitzari lokalak mahaigaineko aplikazioan bakarrik daude erabilgarri. Nabigatzaileek web orrialdeetatik localhost-era zuzeneko konexioak blokeatzen dituzte (CORS eta Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Ez da {{provider}} API gakorik ezarri", "settings.ai.testError.noWebgpu": "WebGPU ez dago erabilgarri nabigatzaile honetan — WebLLM-ek WebGPU behar du (probatu Chrome/Edge edo gaitu banderak).", - "settings.ai.testError.unknownProvider": "Hornitzaile ezezaguna", + "settings.ai.testError.pluginUnavailable": "Zerbitzari lokalaren sarea ez dago erabilgarri: mahaigaineko HTTP pluginak huts egin du kargatzean.", + "settings.ai.testError.timeout": "Konexioak denbora-muga gainditu du ({{url}})", "settings.ai.testError.unexpected": "Ustekabeko errorea gertatu da. Saiatu berriro.", + "settings.ai.testError.unknownProvider": "Hornitzaile ezezaguna", + "settings.ai.testError.unreachable": "Ezin da iritsi ({{url}})", "settings.ai.title": "AI konfigurazioa", "settings.ai.transformers.hint": "Xenova-rekin bateragarria den HuggingFace modelo edozein exekutatzen du lokalean WebAssembly edo WebGPU bidez.", "settings.ai.transformers.modelId": "Modelo ID (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Gaituta dagoenean, OpenRouter hobesten da hodeiko AI deiak egiteko, modu aktiboak hodeia debekatzen ez badu.", "settings.openRouter.errors.generic": "Ustekabeko OpenRouter errore bat gertatu da", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (doan)", + "settings.openRouter.freeModel.fallbackNotice": "Zerrenda estatiko alternatiboa erakusten — OpenRouter-en zuzeneko katalogoa ez dago erabilgarri une honetan.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (doan)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (doan)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (doan)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Ezin izan da ereduen katalogoa kargatu", "settings.openRouter.modelFetch.loading": "Modeloen katalogoa kargatzen…", "settings.openRouter.modelPlaceholder": "Aukeratu edo bilatu eredu bat", + "settings.openRouter.modelUnavailable": "Eredu hau ez dago uneko katalogoan.", "settings.openRouter.paidModelNote": "Ordainpeko ereduek zure OpenRouter kontuan kredituak behar dituzte.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter blokeatuta dago \"Biltegiratze lokala soilik\" aktibatuta dagoelako. Desaktibatu Pribatutasuna eta Datuetan hodeiko AI ahalbidetzeko.", "settings.openRouter.policyBlocked.mode": "OpenRouter ez dago erabilgarri AI modua Tokikoa edo Ekokoa den bitartean. Erabili ahal izateko, aldatu hibrido edo hodeiko AI eta ereduetan.", "settings.openRouter.preferredModel": "Eredu hobetsia", + "settings.openRouter.refreshModels": "Ereduak eguneratu", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter eredu-katalogoa eguneratu", "settings.openRouter.resetCircuit": "Berrezarri", "settings.openRouter.resetCircuitAria": "Berrezarri OpenRouter etengailua", "settings.openRouter.rpmLabel": "Eskaerak/min (azken 60 s)", "settings.openRouter.saveKey": "Gorde", + "settings.openRouter.switchToAvailableModel": "Eskuragarri dagoen doako eredu batera aldatu", "settings.openRouter.testConnection": "Probatu konexioa", "settings.openRouter.testConnectionFailed": "Konexioak huts egin du", "settings.openRouter.testConnectionOk": "Konexioa arrakastatsua da", diff --git a/locales/fa/settings.json b/locales/fa/settings.json index 2bb70c854..1129ac17f 100644 --- a/locales/fa/settings.json +++ b/locales/fa/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2- خلاق", "settings.ai.temperature.precise": "0 - دقیق", "settings.ai.testConnection": "تست اتصال", - "settings.ai.testError.noApiKey": "کلید API {{provider}} تنظیم نشده است", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "زمان اتصال به پایان رسید ({{url}})", - "settings.ai.testError.unreachable": "در دسترس نیست ({{url}})", - "settings.ai.testError.pluginUnavailable": "شبکهسازی سرور محلی در دسترس نیست: بارگذاری افزونه HTTP دسکتاپ ناموفق بود.", - "settings.ai.testError.desktopRequired": "Ollama و سرورهای محلی سازگار با OpenAI فقط در برنامه دسکتاپ در دسترس هستند. مرورگرها اتصالات مستقیم از صفحات وب به localhost را مسدود میکنند (CORS و Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude به یک پراکسی بکاند نیاز دارد (محدودیت CORS)", + "settings.ai.testError.desktopRequired": "Ollama و سرورهای محلی سازگار با OpenAI فقط در برنامه دسکتاپ در دسترس هستند. مرورگرها اتصالات مستقیم از صفحات وب به localhost را مسدود میکنند (CORS و Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "کلید API {{provider}} تنظیم نشده است", "settings.ai.testError.noWebgpu": "WebGPU در این مرورگر در دسترس نیست — WebLLM به WebGPU نیاز دارد (Chrome/Edge را امتحان کنید یا پرچمها را فعال کنید).", - "settings.ai.testError.unknownProvider": "ارائهدهنده ناشناخته", + "settings.ai.testError.pluginUnavailable": "شبکهسازی سرور محلی در دسترس نیست: بارگذاری افزونه HTTP دسکتاپ ناموفق بود.", + "settings.ai.testError.timeout": "زمان اتصال به پایان رسید ({{url}})", "settings.ai.testError.unexpected": "خطای غیرمنتظرهای رخ داد. لطفاً دوباره امتحان کنید.", + "settings.ai.testError.unknownProvider": "ارائهدهنده ناشناخته", + "settings.ai.testError.unreachable": "در دسترس نیست ({{url}})", "settings.ai.title": "پیکربندی هوش مصنوعی", "settings.ai.transformers.hint": "هر مدل HuggingFace سازگار با Xenova را به صورت محلی از طریق WebAssembly یا WebGPU اجرا می کند.", "settings.ai.transformers.modelId": "شناسه مدل (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "وقتی فعال باشد، OpenRouter برای تماسهای ابری AI ترجیح داده میشود، مگر اینکه حالت فعال ابر را ممنوع کند.", "settings.openRouter.errors.generic": "یک خطای غیرمنتظره OpenRouter رخ داد", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (رایگان)", + "settings.openRouter.freeModel.fallbackNotice": "نمایش فهرست جایگزین ثابت — کاتالوگ زنده OpenRouter در حال حاضر در دسترس نیست.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (رایگان)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (رایگان)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (رایگان)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "کاتالوگ مدل بارگیری نشد", "settings.openRouter.modelFetch.loading": "در حال بارگیری کاتالوگ مدل…", "settings.openRouter.modelPlaceholder": "یک مدل را انتخاب یا جستجو کنید", + "settings.openRouter.modelUnavailable": "این مدل در کاتالوگ فعلی وجود ندارد.", "settings.openRouter.paidModelNote": "مدلهای پولی به اعتبار حساب OpenRouter شما نیاز دارند.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter مسدود شده است زیرا «فقط ذخیرهسازی محلی» روشن است. Turn it off in Privacy & Data to allow cloud AI.", "settings.openRouter.policyBlocked.mode": "در حالی که حالت هوش مصنوعی Local یا Eco است، OpenRouter در دسترس نیست. برای استفاده از آن، در هوش مصنوعی و مدلها به Hybrid یا Cloud بروید.", "settings.openRouter.preferredModel": "مدل ترجیحی", + "settings.openRouter.refreshModels": "بهروزرسانی مدلها", + "settings.openRouter.refreshModelsAriaLabel": "بهروزرسانی کاتالوگ مدلهای OpenRouter", "settings.openRouter.resetCircuit": "بازنشانی کنید", "settings.openRouter.resetCircuitAria": "قطع کننده مدار OpenRouter را بازنشانی کنید", "settings.openRouter.rpmLabel": "درخواست ها / دقیقه (60 ثانیه گذشته)", "settings.openRouter.saveKey": "ذخیره", + "settings.openRouter.switchToAvailableModel": "تغییر به یک مدل رایگان در دسترس", "settings.openRouter.testConnection": "تست اتصال", "settings.openRouter.testConnectionFailed": "اتصال ناموفق بود", "settings.openRouter.testConnectionOk": "اتصال با موفقیت انجام شد", diff --git a/locales/fi/settings.json b/locales/fi/settings.json index 58464432b..1f4e2c010 100644 --- a/locales/fi/settings.json +++ b/locales/fi/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Luova", "settings.ai.temperature.precise": "0 – Tarkka", "settings.ai.testConnection": "Testaa yhteys", - "settings.ai.testError.noApiKey": "{{provider}}-API-avainta ei ole asetettu", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Yhteys aikakatkaistiin ({{url}})", - "settings.ai.testError.unreachable": "Ei tavoiteta ({{url}})", - "settings.ai.testError.pluginUnavailable": "Paikallisen palvelimen verkko ei ole käytettävissä: työpöydän HTTP-lisäosan lataus epäonnistui.", - "settings.ai.testError.desktopRequired": "Ollama ja paikalliset OpenAI-yhteensopivat palvelimet ovat käytettävissä vain työpöytäsovelluksessa. Selaimet estävät suorat yhteydet verkkosivuilta osoitteeseen localhost (CORS ja Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude vaatii taustajärjestelmän välityspalvelimen (CORS-rajoitus)", + "settings.ai.testError.desktopRequired": "Ollama ja paikalliset OpenAI-yhteensopivat palvelimet ovat käytettävissä vain työpöytäsovelluksessa. Selaimet estävät suorat yhteydet verkkosivuilta osoitteeseen localhost (CORS ja Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}}-API-avainta ei ole asetettu", "settings.ai.testError.noWebgpu": "WebGPU ei ole käytettävissä tässä selaimessa — WebLLM tarvitsee WebGPU:n (kokeile Chromea/Edgeä tai ota liput käyttöön).", - "settings.ai.testError.unknownProvider": "Tuntematon palveluntarjoaja", + "settings.ai.testError.pluginUnavailable": "Paikallisen palvelimen verkko ei ole käytettävissä: työpöydän HTTP-lisäosan lataus epäonnistui.", + "settings.ai.testError.timeout": "Yhteys aikakatkaistiin ({{url}})", "settings.ai.testError.unexpected": "Tapahtui odottamaton virhe. Yritä uudelleen.", + "settings.ai.testError.unknownProvider": "Tuntematon palveluntarjoaja", + "settings.ai.testError.unreachable": "Ei tavoiteta ({{url}})", "settings.ai.title": "AI-kokoonpano", "settings.ai.transformers.hint": "Suorittaa mitä tahansa Xenova-yhteensopivaa HuggingFace-mallia paikallisesti WebAssemblyn tai WebGPU:n kautta.", "settings.ai.transformers.modelId": "Mallin tunnus (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Kun OpenRouter on käytössä, sitä suositellaan pilvi-AI-kutsuille, ellei aktiivinen tila estä pilven käyttöä.", "settings.openRouter.errors.generic": "Tapahtui odottamaton OpenRouter-virhe", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ilmainen)", + "settings.openRouter.freeModel.fallbackNotice": "Näytetään staattinen varaluettelo — OpenRouterin reaaliaikainen luettelo ei ole juuri nyt käytettävissä.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ilmainen)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ilmainen)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ilmainen)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Malliluetteloa ei voitu ladata", "settings.openRouter.modelFetch.loading": "Ladataan malliluetteloa…", "settings.openRouter.modelPlaceholder": "Valitse tai etsi malli", + "settings.openRouter.modelUnavailable": "Tämä malli ei ole nykyisessä luettelossa.", "settings.openRouter.paidModelNote": "Maksulliset mallit vaativat hyvitystä OpenRouter-tililläsi.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter on estetty, koska \"Vain paikallinen tallennus\" on päällä. Ota se käyttöön Privacy & Data -kohdassa salliaksesi pilvi-AI.", "settings.openRouter.policyBlocked.mode": "OpenRouter ei ole käytettävissä, kun AI-tila on Local tai Eco. Käytä tekoälyssä ja malleissa hybridi- tai pilvipalvelua.", "settings.openRouter.preferredModel": "Suosittu malli", + "settings.openRouter.refreshModels": "Päivitä mallit", + "settings.openRouter.refreshModelsAriaLabel": "Päivitä OpenRouter-malliluettelo", "settings.openRouter.resetCircuit": "Nollaa", "settings.openRouter.resetCircuitAria": "Nollaa OpenRouter-katkaisija", "settings.openRouter.rpmLabel": "Pyynnöt/min (viimeiset 60 s)", "settings.openRouter.saveKey": "Tallenna", + "settings.openRouter.switchToAvailableModel": "Vaihda saatavilla olevaan ilmaiseen malliin", "settings.openRouter.testConnection": "Testaa yhteys", "settings.openRouter.testConnectionFailed": "Yhteys epäonnistui", "settings.openRouter.testConnectionOk": "Yhteys onnistui", diff --git a/locales/fr/settings.json b/locales/fr/settings.json index f16a69db7..84f78cb64 100644 --- a/locales/fr/settings.json +++ b/locales/fr/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Créatif", "settings.ai.temperature.precise": "0 – Précis", "settings.ai.testConnection": "Tester la connexion", - "settings.ai.testError.noApiKey": "Aucune clé API {{provider}} définie", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Délai de connexion dépassé ({{url}})", - "settings.ai.testError.unreachable": "Injoignable ({{url}})", - "settings.ai.testError.pluginUnavailable": "Le réseau des serveurs locaux est indisponible : le plugin HTTP du bureau n'a pas pu se charger.", - "settings.ai.testError.desktopRequired": "Ollama et les serveurs locaux compatibles OpenAI ne sont disponibles que dans l'application de bureau. Les navigateurs bloquent les connexions directes des pages web vers localhost (CORS et Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude nécessite un proxy backend (restriction CORS)", + "settings.ai.testError.desktopRequired": "Ollama et les serveurs locaux compatibles OpenAI ne sont disponibles que dans l'application de bureau. Les navigateurs bloquent les connexions directes des pages web vers localhost (CORS et Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Aucune clé API {{provider}} définie", "settings.ai.testError.noWebgpu": "WebGPU indisponible dans ce navigateur — WebLLM nécessite WebGPU (essayez Chrome/Edge ou activez les indicateurs).", - "settings.ai.testError.unknownProvider": "Fournisseur inconnu", + "settings.ai.testError.pluginUnavailable": "Le réseau des serveurs locaux est indisponible : le plugin HTTP du bureau n'a pas pu se charger.", + "settings.ai.testError.timeout": "Délai de connexion dépassé ({{url}})", "settings.ai.testError.unexpected": "Une erreur inattendue s'est produite. Veuillez réessayer.", + "settings.ai.testError.unknownProvider": "Fournisseur inconnu", + "settings.ai.testError.unreachable": "Injoignable ({{url}})", "settings.ai.title": "Configuration de l'IA", "settings.ai.transformers.hint": "Exécute tout modèle HuggingFace compatible Xenova localement via WebAssembly ou WebGPU.", "settings.ai.transformers.modelId": "ID du modèle (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Lorsqu'il est activé, OpenRouter est privilégié pour les appels d'IA cloud, sauf si le mode actif interdit le cloud.", "settings.openRouter.errors.generic": "Une erreur OpenRouter inattendue s'est produite", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratuit)", + "settings.openRouter.freeModel.fallbackNotice": "Affichage de la liste de secours statique — le catalogue OpenRouter en direct n'est pas disponible pour le moment.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratuit)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratuit)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratuit)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Impossible de charger le catalogue de modèles", "settings.openRouter.modelFetch.loading": "Chargement du catalogue de modèles…", "settings.openRouter.modelPlaceholder": "Sélectionner ou rechercher un modèle", + "settings.openRouter.modelUnavailable": "Ce modèle ne figure pas dans le catalogue actuel.", "settings.openRouter.paidModelNote": "Les modèles payants nécessitent des crédits sur votre compte OpenRouter.", "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.refreshModels": "Actualiser les modèles", + "settings.openRouter.refreshModelsAriaLabel": "Actualiser le catalogue de modèles OpenRouter", "settings.openRouter.resetCircuit": "Réinitialiser", "settings.openRouter.resetCircuitAria": "Réinitialiser le disjoncteur OpenRouter", "settings.openRouter.rpmLabel": "Requêtes / min (60 dernières s)", "settings.openRouter.saveKey": "Enregistrer", + "settings.openRouter.switchToAvailableModel": "Passer à un modèle gratuit disponible", "settings.openRouter.testConnection": "Tester la connexion", "settings.openRouter.testConnectionFailed": "Échec de la connexion", "settings.openRouter.testConnectionOk": "Connexion réussie", diff --git a/locales/he/settings.json b/locales/he/settings.json index ac6311f2a..049a09383 100644 --- a/locales/he/settings.json +++ b/locales/he/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – יצירתי", "settings.ai.temperature.precise": "0 – מדויק", "settings.ai.testConnection": "בדיקת חיבור", - "settings.ai.testError.noApiKey": "לא הוגדר מפתח API עבור {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "פסק הזמן של החיבור פג ({{url}})", - "settings.ai.testError.unreachable": "לא ניתן להגיע ({{url}})", - "settings.ai.testError.pluginUnavailable": "רשת השרת המקומי אינה זמינה: תוסף ה-HTTP של שולחן העבודה נכשל בטעינה.", - "settings.ai.testError.desktopRequired": "Ollama ושרתים מקומיים תואמי OpenAI זמינים רק באפליקציית שולחן העבודה. דפדפנים חוסמים חיבורים ישירים מדפי אינטרנט אל localhost (CORS ו-Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude דורש שרת proxy (הגבלת CORS)", + "settings.ai.testError.desktopRequired": "Ollama ושרתים מקומיים תואמי OpenAI זמינים רק באפליקציית שולחן העבודה. דפדפנים חוסמים חיבורים ישירים מדפי אינטרנט אל localhost (CORS ו-Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "לא הוגדר מפתח API עבור {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU אינו זמין בדפדפן זה — WebLLM דורש WebGPU (נסה Chrome/Edge או הפעל דגלים).", - "settings.ai.testError.unknownProvider": "ספק לא ידוע", + "settings.ai.testError.pluginUnavailable": "רשת השרת המקומי אינה זמינה: תוסף ה-HTTP של שולחן העבודה נכשל בטעינה.", + "settings.ai.testError.timeout": "פסק הזמן של החיבור פג ({{url}})", "settings.ai.testError.unexpected": "אירעה שגיאה בלתי צפויה. נסה שוב.", + "settings.ai.testError.unknownProvider": "ספק לא ידוע", + "settings.ai.testError.unreachable": "לא ניתן להגיע ({{url}})", "settings.ai.title": "תצורת AI", "settings.ai.transformers.hint": "מריץ כל מודל HuggingFace תואם‑Xenova מקומית דרך WebAssembly או WebGPU.", "settings.ai.transformers.modelId": "מזהה מודל (HuggingFace)", @@ -599,6 +599,7 @@ "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.fallbackNotice": "מוצגת רשימת גיבוי סטטית — קטלוג ה-OpenRouter החי אינו זמין כרגע.", "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)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Could not load model catalog", "settings.openRouter.modelFetch.loading": "Loading model catalog…", "settings.openRouter.modelPlaceholder": "deepseek/deepseek-r1:free", + "settings.openRouter.modelUnavailable": "דגם זה אינו נמצא בקטלוג הנוכחי.", "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.refreshModels": "רענון דגמים", + "settings.openRouter.refreshModelsAriaLabel": "רענון קטלוג הדגמים של OpenRouter", "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.switchToAvailableModel": "מעבר לדגם חינמי זמין", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/locales/hu/settings.json b/locales/hu/settings.json index c51258b6b..980f6f37b 100644 --- a/locales/hu/settings.json +++ b/locales/hu/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Kreatív", "settings.ai.temperature.precise": "0 – Pontos", "settings.ai.testConnection": "Kapcsolat tesztelése", - "settings.ai.testError.noApiKey": "Nincs beállítva {{provider}} API-kulcs", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "A kapcsolat túllépte az időkorlátot ({{url}})", - "settings.ai.testError.unreachable": "Nem érhető el ({{url}})", - "settings.ai.testError.pluginUnavailable": "A helyi kiszolgálóhálózat nem érhető el: az asztali HTTP bővítmény betöltése sikertelen.", - "settings.ai.testError.desktopRequired": "Az Ollama és a helyi OpenAI-kompatibilis kiszolgálók csak az asztali alkalmazásban érhetők el. A böngészők blokkolják a weboldalak közvetlen kapcsolatait a localhosttal (CORS és Private Network Access).", "settings.ai.testError.backendProxyRequired": "A Claude háttérproxyt igényel (CORS-korlátozás)", + "settings.ai.testError.desktopRequired": "Az Ollama és a helyi OpenAI-kompatibilis kiszolgálók csak az asztali alkalmazásban érhetők el. A böngészők blokkolják a weboldalak közvetlen kapcsolatait a localhosttal (CORS és Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nincs beállítva {{provider}} API-kulcs", "settings.ai.testError.noWebgpu": "A WebGPU nem érhető el ebben a böngészőben — a WebLLM-nek WebGPU-ra van szüksége (próbáld a Chrome-ot/Edge-et, vagy engedélyezd a jelzőket).", - "settings.ai.testError.unknownProvider": "Ismeretlen szolgáltató", + "settings.ai.testError.pluginUnavailable": "A helyi kiszolgálóhálózat nem érhető el: az asztali HTTP bővítmény betöltése sikertelen.", + "settings.ai.testError.timeout": "A kapcsolat túllépte az időkorlátot ({{url}})", "settings.ai.testError.unexpected": "Váratlan hiba történt. Kérjük, próbálja újra.", + "settings.ai.testError.unknownProvider": "Ismeretlen szolgáltató", + "settings.ai.testError.unreachable": "Nem érhető el ({{url}})", "settings.ai.title": "AI konfiguráció", "settings.ai.transformers.hint": "Bármilyen Xenova-kompatibilis HuggingFace modellt futtat helyileg a WebAssembly vagy WebGPU segítségével.", "settings.ai.transformers.modelId": "Modellazonosító (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Ha engedélyezve van, az OpenRouter előnyben részesíti a felhőalapú mesterséges intelligencia hívásait, hacsak az aktív mód nem tiltja a felhőt.", "settings.openRouter.errors.generic": "Váratlan OpenRouter hiba történt", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ingyenes)", + "settings.openRouter.freeModel.fallbackNotice": "A statikus tartalék lista jelenik meg — az élő OpenRouter katalógus jelenleg nem érhető el.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ingyenes)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ingyenes)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ingyenes)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Nem sikerült betölteni a modellkatalógust", "settings.openRouter.modelFetch.loading": "Modellkatalógus betöltése…", "settings.openRouter.modelPlaceholder": "Válasszon vagy keressen egy modellt", + "settings.openRouter.modelUnavailable": "Ez a modell nincs a jelenlegi katalógusban.", "settings.openRouter.paidModelNote": "A fizetős modellekhez jóváírásra van szükség az OpenRouter-fiókjában.", "settings.openRouter.policyBlocked.localOnly": "Az OpenRouter le van tiltva, mert a „Csak helyi tárhely” be van kapcsolva. A felhő AI engedélyezéséhez kapcsolja ki az Adatvédelem és adatok részben.", "settings.openRouter.policyBlocked.mode": "Az OpenRouter nem érhető el, ha az AI mód Helyi vagy Eco. A használatához váltson hibridre vagy felhőre az AI és modellekben.", "settings.openRouter.preferredModel": "Preferált modell", - "settings.openRouter.resetCircuit": "Reset", + "settings.openRouter.refreshModels": "Modellek frissítése", + "settings.openRouter.refreshModelsAriaLabel": "Az OpenRouter modellkatalógus frissítése", + "settings.openRouter.resetCircuit": "Visszaállítás", "settings.openRouter.resetCircuitAria": "Állítsa vissza az OpenRouter megszakítót", "settings.openRouter.rpmLabel": "Kérések / perc (legutóbbi 60 mp)", "settings.openRouter.saveKey": "Mentés", + "settings.openRouter.switchToAvailableModel": "Váltás egy elérhető ingyenes modellre", "settings.openRouter.testConnection": "Kapcsolat tesztelése", "settings.openRouter.testConnectionFailed": "A csatlakozás sikertelen", "settings.openRouter.testConnectionOk": "Sikeres csatlakozás", diff --git a/locales/is/settings.json b/locales/is/settings.json index 83660cc16..f612e7a8c 100644 --- a/locales/is/settings.json +++ b/locales/is/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 - Skapandi", "settings.ai.temperature.precise": "0 - Nákvæmt", "settings.ai.testConnection": "Prófaðu tengingu", - "settings.ai.testError.noApiKey": "Enginn {{provider}} API lykill stilltur", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tengingin féll á tíma ({{url}})", - "settings.ai.testError.unreachable": "Næst ekki ({{url}})", - "settings.ai.testError.pluginUnavailable": "Staðbundið netþjónasamband ekki tiltækt: ekki tókst að hlaða HTTP-viðbót skjáborðs.", - "settings.ai.testError.desktopRequired": "Ollama og staðbundnir OpenAI-samhæfir netþjónar eru aðeins tiltækir í skjáborðsforritinu. Vafrar loka fyrir bein tengsl frá vefsíðum við localhost (CORS og Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude þarfnast bakenda-milliþjóns (CORS-takmörkun)", + "settings.ai.testError.desktopRequired": "Ollama og staðbundnir OpenAI-samhæfir netþjónar eru aðeins tiltækir í skjáborðsforritinu. Vafrar loka fyrir bein tengsl frá vefsíðum við localhost (CORS og Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Enginn {{provider}} API lykill stilltur", "settings.ai.testError.noWebgpu": "WebGPU er ekki tiltækt í þessum vafra — WebLLM þarfnast WebGPU (prófaðu Chrome/Edge eða virkjaðu flögg).", - "settings.ai.testError.unknownProvider": "Óþekktur veitandi", + "settings.ai.testError.pluginUnavailable": "Staðbundið netþjónasamband ekki tiltækt: ekki tókst að hlaða HTTP-viðbót skjáborðs.", + "settings.ai.testError.timeout": "Tengingin féll á tíma ({{url}})", "settings.ai.testError.unexpected": "Óvænt villa kom upp. Reyndu aftur.", + "settings.ai.testError.unknownProvider": "Óþekktur veitandi", + "settings.ai.testError.unreachable": "Næst ekki ({{url}})", "settings.ai.title": "AI stillingar", "settings.ai.transformers.hint": "Keyrir hvaða Xenova-samhæfða HuggingFace líkan sem er á staðnum í gegnum WebAssembly eða WebGPU.", "settings.ai.transformers.modelId": "Auðkenni fyrirmyndar (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Þegar það er virkt er OpenRouter valinn fyrir gervigreindarsímtöl í skýi nema virka stillingin banni ský.", "settings.openRouter.errors.generic": "Óvænt OpenRouter villa kom upp", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ókeypis)", + "settings.openRouter.freeModel.fallbackNotice": "Sýnir kyrrstæðan varalista — beinn OpenRouter-listi er ekki tiltækur núna.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ókeypis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ókeypis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ókeypis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Gat ekki hlaðið módelskrá", "settings.openRouter.modelFetch.loading": "Hleður líkanaskrá...", "settings.openRouter.modelPlaceholder": "Veldu eða leitaðu að gerð", + "settings.openRouter.modelUnavailable": "Þetta líkan er ekki í núverandi lista.", "settings.openRouter.paidModelNote": "Greiddar gerðir þurfa inneign á OpenRouter reikningnum þínum.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter er læst vegna þess að kveikt er á „Staðbundin geymsla“. Slökktu á því í Privacy & Data til að leyfa gervigreind í skýi.", "settings.openRouter.policyBlocked.mode": "OpenRouter er ekki tiltækur á meðan gervigreindarstillingin er Local eða Eco. Skiptu yfir í Hybrid eða Cloud í gervigreind og módel til að nota það.", "settings.openRouter.preferredModel": "Ákjósanleg gerð", + "settings.openRouter.refreshModels": "Uppfæra líkön", + "settings.openRouter.refreshModelsAriaLabel": "Uppfæra OpenRouter líkanalistann", "settings.openRouter.resetCircuit": "Endurstilla", "settings.openRouter.resetCircuitAria": "Endurstilla OpenRouter aflrofa", "settings.openRouter.rpmLabel": "Beiðnir / mín. (síðustu 60 s)", "settings.openRouter.saveKey": "Vista", + "settings.openRouter.switchToAvailableModel": "Skipta yfir í tiltækt ókeypis líkan", "settings.openRouter.testConnection": "Prófaðu tengingu", "settings.openRouter.testConnectionFailed": "Tenging mistókst", "settings.openRouter.testConnectionOk": "Tenging tókst", diff --git a/locales/it/dashboard.json b/locales/it/dashboard.json index 9eff4fbce..8f0ae271b 100644 --- a/locales/it/dashboard.json +++ b/locales/it/dashboard.json @@ -1,7 +1,7 @@ { "dashboard.authorInsights.readability": "Leggibilità (Gulpease, euristica IT)", "dashboard.authorInsights.readabilityFootnote": "Punteggi più alti sono spesso più facili da leggere; calibra sul genere.", - "dashboard.authorInsights.readabilityTooltip": "Scala di leggibilità Flesch 0–100: più alto = più facile da leggere (60–70 è linguaggio comune). È un indicatore approssimativo, non un voto normativo.", + "dashboard.authorInsights.readabilityTooltip": "Indice di leggibilità Gulpease 0–100: più alto = più facile da leggere (soglia ~60 per la scuola media, ~80 per la scuola elementare). È un indicatore approssimativo, non un voto normativo.", "dashboard.authorInsights.readabilityScaleSuffix": "/100", "dashboard.logline.updated": "Logline aggiornata", "dashboard.logline.updatedUndo": "Premi Ctrl+Z per annullare.", diff --git a/locales/it/settings.json b/locales/it/settings.json index 8e2f3a845..2d8dd4398 100644 --- a/locales/it/settings.json +++ b/locales/it/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Testa la connessione", - "settings.ai.testError.noApiKey": "Nessuna chiave API {{provider}} impostata", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Connessione scaduta ({{url}})", - "settings.ai.testError.unreachable": "Non raggiungibile ({{url}})", - "settings.ai.testError.pluginUnavailable": "Rete dei server locali non disponibile: il plugin HTTP desktop non è stato caricato.", - "settings.ai.testError.desktopRequired": "Ollama e i server locali compatibili con OpenAI sono disponibili solo nell'app desktop. I browser bloccano le connessioni dirette dalle pagine web a localhost (CORS e Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude richiede un proxy backend (restrizione CORS)", + "settings.ai.testError.desktopRequired": "Ollama e i server locali compatibili con OpenAI sono disponibili solo nell'app desktop. I browser bloccano le connessioni dirette dalle pagine web a localhost (CORS e Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nessuna chiave API {{provider}} impostata", "settings.ai.testError.noWebgpu": "WebGPU non disponibile in questo browser — WebLLM richiede WebGPU (prova Chrome/Edge o abilita i flag).", - "settings.ai.testError.unknownProvider": "Provider sconosciuto", + "settings.ai.testError.pluginUnavailable": "Rete dei server locali non disponibile: il plugin HTTP desktop non è stato caricato.", + "settings.ai.testError.timeout": "Connessione scaduta ({{url}})", "settings.ai.testError.unexpected": "Si è verificato un errore imprevisto. Riprova.", + "settings.ai.testError.unknownProvider": "Provider sconosciuto", + "settings.ai.testError.unreachable": "Non raggiungibile ({{url}})", "settings.ai.title": "Configurazione IA", "settings.ai.transformers.hint": "Esegue qualsiasi modello HuggingFace compatibile con Xenova localmente via WebAssembly o WebGPU.", "settings.ai.transformers.modelId": "ID modello (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Se abilitato, OpenRouter è preferito per le chiamate IA cloud, a meno che la modalità attiva non vieti il cloud.", "settings.openRouter.errors.generic": "Si è verificato un errore imprevisto di OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Visualizzazione dell'elenco di riserva statico — il catalogo OpenRouter in tempo reale non è disponibile al momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Impossibile caricare il catalogo modelli", "settings.openRouter.modelFetch.loading": "Caricamento del catalogo modelli…", "settings.openRouter.modelPlaceholder": "Seleziona o cerca un modello", + "settings.openRouter.modelUnavailable": "Questo modello non è presente nel catalogo attuale.", "settings.openRouter.paidModelNote": "I modelli a pagamento richiedono crediti sul tuo account OpenRouter.", "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.refreshModels": "Aggiorna modelli", + "settings.openRouter.refreshModelsAriaLabel": "Aggiorna il catalogo dei modelli OpenRouter", "settings.openRouter.resetCircuit": "Reimposta", "settings.openRouter.resetCircuitAria": "Reimposta l'interruttore di OpenRouter", "settings.openRouter.rpmLabel": "Richieste / min (ultimi 60 s)", "settings.openRouter.saveKey": "Salva", + "settings.openRouter.switchToAvailableModel": "Passa a un modello gratuito disponibile", "settings.openRouter.testConnection": "Prova connessione", "settings.openRouter.testConnectionFailed": "Connessione non riuscita", "settings.openRouter.testConnectionOk": "Connessione riuscita", diff --git a/locales/ja/settings.json b/locales/ja/settings.json index 06e49e072..f3a93c03b 100644 --- a/locales/ja/settings.json +++ b/locales/ja/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – クリエイティブ", "settings.ai.temperature.precise": "0 – 正確", "settings.ai.testConnection": "テスト接続", - "settings.ai.testError.noApiKey": "{{provider}} の API キーが設定されていません", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "接続がタイムアウトしました ({{url}})", - "settings.ai.testError.unreachable": "到達できません ({{url}})", - "settings.ai.testError.pluginUnavailable": "ローカルサーバーへの接続が利用できません: デスクトップ HTTP プラグインの読み込みに失敗しました。", - "settings.ai.testError.desktopRequired": "Ollama およびローカルの OpenAI 互換サーバーはデスクトップアプリでのみ利用できます。ブラウザは Web ページから localhost への直接接続をブロックします(CORS および Private Network Access)。", "settings.ai.testError.backendProxyRequired": "Claude にはバックエンドプロキシが必要です(CORS 制限)", + "settings.ai.testError.desktopRequired": "Ollama およびローカルの OpenAI 互換サーバーはデスクトップアプリでのみ利用できます。ブラウザは Web ページから localhost への直接接続をブロックします(CORS および Private Network Access)。", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}} の API キーが設定されていません", "settings.ai.testError.noWebgpu": "このブラウザでは WebGPU が利用できません — WebLLM には WebGPU が必要です(Chrome/Edge を試すかフラグを有効にしてください)。", - "settings.ai.testError.unknownProvider": "不明なプロバイダー", + "settings.ai.testError.pluginUnavailable": "ローカルサーバーへの接続が利用できません: デスクトップ HTTP プラグインの読み込みに失敗しました。", + "settings.ai.testError.timeout": "接続がタイムアウトしました ({{url}})", "settings.ai.testError.unexpected": "予期しないエラーが発生しました。もう一度お試しください。", + "settings.ai.testError.unknownProvider": "不明なプロバイダー", + "settings.ai.testError.unreachable": "到達できません ({{url}})", "settings.ai.title": "AIの構成", "settings.ai.transformers.hint": "WebAssembly または WebGPU を介して Xenova 互換の HuggingFace モデルをローカルで実行します。", "settings.ai.transformers.modelId": "モデルID (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "有効にすると、アクティブなモードがクラウドを禁止しない限り、クラウドAI呼び出しにOpenRouterが優先されます。", "settings.openRouter.errors.generic": "予期しないOpenRouterエラーが発生しました", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (無料)", + "settings.openRouter.freeModel.fallbackNotice": "静的なフォールバックリストを表示しています — OpenRouterのライブカタログは現在利用できません。", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (無料)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (無料)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (無料)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "モデルカタログを読み込めませんでした", "settings.openRouter.modelFetch.loading": "モデルカタログを読み込み中…", "settings.openRouter.modelPlaceholder": "モデルを選択または検索", + "settings.openRouter.modelUnavailable": "このモデルは現在のカタログにありません。", "settings.openRouter.paidModelNote": "有料モデルにはOpenRouterアカウントのクレジットが必要です。", "settings.openRouter.policyBlocked.localOnly": "「ローカルストレージのみ」がオンのため OpenRouter はブロックされています。クラウド AI を許可するには「プライバシーとデータ」でオフにしてください。", "settings.openRouter.policyBlocked.mode": "AIモードが「ローカル」または「エコ」の間は OpenRouter を利用できません。利用するには「AI とモデル」で「ハイブリッド」または「クラウド」に切り替えてください。", "settings.openRouter.preferredModel": "優先モデル", + "settings.openRouter.refreshModels": "モデルを更新", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouterモデルカタログを更新", "settings.openRouter.resetCircuit": "リセット", "settings.openRouter.resetCircuitAria": "OpenRouterサーキットブレーカーをリセット", "settings.openRouter.rpmLabel": "リクエスト/分(直近60秒)", "settings.openRouter.saveKey": "保存", + "settings.openRouter.switchToAvailableModel": "利用可能な無料モデルに切り替える", "settings.openRouter.testConnection": "接続をテスト", "settings.openRouter.testConnectionFailed": "接続に失敗しました", "settings.openRouter.testConnectionOk": "接続に成功しました", diff --git a/locales/ko/settings.json b/locales/ko/settings.json index 2636739ca..6eefe41d0 100644 --- a/locales/ko/settings.json +++ b/locales/ko/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – 창의적", "settings.ai.temperature.precise": "0 – 정확함", "settings.ai.testConnection": "연결 테스트", - "settings.ai.testError.noApiKey": "{{provider}} API 키가 설정되지 않았습니다", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "연결 시간이 초과되었습니다 ({{url}})", - "settings.ai.testError.unreachable": "연결할 수 없습니다 ({{url}})", - "settings.ai.testError.pluginUnavailable": "로컬 서버 네트워킹을 사용할 수 없습니다: 데스크톱 HTTP 플러그인을 불러오지 못했습니다.", - "settings.ai.testError.desktopRequired": "Ollama 및 로컬 OpenAI 호환 서버는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저는 웹 페이지에서 localhost로의 직접 연결을 차단합니다(CORS 및 Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude에는 백엔드 프록시가 필요합니다(CORS 제한)", + "settings.ai.testError.desktopRequired": "Ollama 및 로컬 OpenAI 호환 서버는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저는 웹 페이지에서 localhost로의 직접 연결을 차단합니다(CORS 및 Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}} API 키가 설정되지 않았습니다", "settings.ai.testError.noWebgpu": "이 브라우저에서는 WebGPU를 사용할 수 없습니다 — WebLLM에는 WebGPU가 필요합니다(Chrome/Edge를 사용하거나 플래그를 활성화하세요).", - "settings.ai.testError.unknownProvider": "알 수 없는 제공자", + "settings.ai.testError.pluginUnavailable": "로컬 서버 네트워킹을 사용할 수 없습니다: 데스크톱 HTTP 플러그인을 불러오지 못했습니다.", + "settings.ai.testError.timeout": "연결 시간이 초과되었습니다 ({{url}})", "settings.ai.testError.unexpected": "예기치 않은 오류가 발생했습니다. 다시 시도해 주세요.", + "settings.ai.testError.unknownProvider": "알 수 없는 제공자", + "settings.ai.testError.unreachable": "연결할 수 없습니다 ({{url}})", "settings.ai.title": "AI 구성", "settings.ai.transformers.hint": "WebAssembly 또는 WebGPU를 통해 Xenova 호환 HuggingFace 모델을 로컬로 실행합니다.", "settings.ai.transformers.modelId": "모델 ID(HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "활성화되면 활성 모드가 클라우드를 금지하지 않는 한 클라우드 AI 호출에 OpenRouter가 선호됩니다.", "settings.openRouter.errors.generic": "예상치 못한 OpenRouter 오류가 발생했습니다.", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (무료)", + "settings.openRouter.freeModel.fallbackNotice": "정적 대체 목록을 표시하고 있습니다 — 실시간 OpenRouter 카탈로그를 현재 사용할 수 없습니다.", "settings.openRouter.freeModel.gemma327b": "젬마 3 27B IT(무료)", "settings.openRouter.freeModel.llama3370b": "라마 3.3 70B 교육(무료)", "settings.openRouter.freeModel.mistral7b": "미스트랄 7B 교육(무료)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "모델 카탈로그를 로드할 수 없습니다.", "settings.openRouter.modelFetch.loading": "모델 카탈로그 로드 중…", "settings.openRouter.modelPlaceholder": "모델 선택 또는 검색", + "settings.openRouter.modelUnavailable": "이 모델은 현재 카탈로그에 없습니다.", "settings.openRouter.paidModelNote": "유료 모델을 사용하려면 OpenRouter 계정에 크레딧이 필요합니다.", "settings.openRouter.policyBlocked.localOnly": "\"로컬 저장소만\"이 켜져 있으므로 OpenRouter가 차단되었습니다. 클라우드 AI를 허용하려면 개인 정보 보호 및 데이터에서 이 기능을 끄세요.", "settings.openRouter.policyBlocked.mode": "AI 모드가 Local 또는 Eco인 동안에는 OpenRouter를 사용할 수 없습니다. AI 및 모델에서 하이브리드 또는 클라우드로 전환하여 사용하세요.", "settings.openRouter.preferredModel": "선호하는 모델", + "settings.openRouter.refreshModels": "모델 새로고침", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter 모델 카탈로그 새로고침", "settings.openRouter.resetCircuit": "다시 놓기", "settings.openRouter.resetCircuitAria": "OpenRouter 회로 차단기 재설정", "settings.openRouter.rpmLabel": "요청/분(지난 60초)", "settings.openRouter.saveKey": "저장", + "settings.openRouter.switchToAvailableModel": "사용 가능한 무료 모델로 전환", "settings.openRouter.testConnection": "연결 테스트", "settings.openRouter.testConnectionFailed": "연결 실패", "settings.openRouter.testConnectionOk": "연결 성공", diff --git a/locales/pt/settings.json b/locales/pt/settings.json index 4651616f9..9b1d76423 100644 --- a/locales/pt/settings.json +++ b/locales/pt/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Criativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Conexão de teste", - "settings.ai.testError.noApiKey": "Nenhuma chave de API {{provider}} definida", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tempo limite de conexão excedido ({{url}})", - "settings.ai.testError.unreachable": "Inacessível ({{url}})", - "settings.ai.testError.pluginUnavailable": "A rede do servidor local não está disponível: o plugin HTTP de ambiente de trabalho falhou ao carregar.", - "settings.ai.testError.desktopRequired": "O Ollama e os servidores locais compatíveis com OpenAI só estão disponíveis na aplicação de ambiente de trabalho. Os navegadores bloqueiam ligações diretas de páginas web ao localhost (CORS e Private Network Access).", "settings.ai.testError.backendProxyRequired": "O Claude requer um proxy de backend (restrição CORS)", + "settings.ai.testError.desktopRequired": "O Ollama e os servidores locais compatíveis com OpenAI só estão disponíveis na aplicação de ambiente de trabalho. Os navegadores bloqueiam ligações diretas de páginas web ao localhost (CORS e Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nenhuma chave de API {{provider}} definida", "settings.ai.testError.noWebgpu": "WebGPU indisponível neste navegador — o WebLLM necessita de WebGPU (experimente o Chrome/Edge ou ative as flags).", - "settings.ai.testError.unknownProvider": "Fornecedor desconhecido", + "settings.ai.testError.pluginUnavailable": "A rede do servidor local não está disponível: o plugin HTTP de ambiente de trabalho falhou ao carregar.", + "settings.ai.testError.timeout": "Tempo limite de conexão excedido ({{url}})", "settings.ai.testError.unexpected": "Ocorreu um erro inesperado. Tente novamente.", + "settings.ai.testError.unknownProvider": "Fornecedor desconhecido", + "settings.ai.testError.unreachable": "Inacessível ({{url}})", "settings.ai.title": "IA Configuration", "settings.ai.transformers.hint": "Executa qualquer modelo HuggingFace compatível com Xenova localmente via WebAssembly ou WebGPU.", "settings.ai.transformers.modelId": "ID do modelo (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Quando ativado, o OpenRouter é preferido para chamadas de IA na cloud, exceto se o modo ativo proibir a cloud.", "settings.openRouter.errors.generic": "Ocorreu um erro inesperado do OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (grátis)", + "settings.openRouter.freeModel.fallbackNotice": "A mostrar a lista de reserva estática — o catálogo em direto do OpenRouter não está disponível de momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (grátis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (grátis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (grátis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Não foi possível carregar o catálogo de modelos", "settings.openRouter.modelFetch.loading": "A carregar o catálogo de modelos…", "settings.openRouter.modelPlaceholder": "Seleciona ou procura um modelo", + "settings.openRouter.modelUnavailable": "Este modelo não está no catálogo atual.", "settings.openRouter.paidModelNote": "Os modelos pagos requerem créditos na tua conta OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "O OpenRouter está bloqueado porque “Apenas armazenamento local” está ativado. Desative-o em Privacidade e Dados para permitir a IA na nuvem.", "settings.openRouter.policyBlocked.mode": "O OpenRouter não está disponível enquanto o modo de IA for Local ou Eco. Mude para Híbrido ou Nuvem em IA e Modelos para o utilizar.", "settings.openRouter.preferredModel": "Modelo preferido", + "settings.openRouter.refreshModels": "Atualizar modelos", + "settings.openRouter.refreshModelsAriaLabel": "Atualizar o catálogo de modelos OpenRouter", "settings.openRouter.resetCircuit": "Repor", "settings.openRouter.resetCircuitAria": "Repor o disjuntor do OpenRouter", "settings.openRouter.rpmLabel": "Pedidos / min (últimos 60 s)", "settings.openRouter.saveKey": "Guardar", + "settings.openRouter.switchToAvailableModel": "Mudar para um modelo gratuito disponível", "settings.openRouter.testConnection": "Testar ligação", "settings.openRouter.testConnectionFailed": "Falha na ligação", "settings.openRouter.testConnectionOk": "Ligação bem-sucedida", diff --git a/locales/ru/settings.json b/locales/ru/settings.json index 0b4595a43..9e7c47d78 100644 --- a/locales/ru/settings.json +++ b/locales/ru/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Креатив", "settings.ai.temperature.precise": "0 – Точный", "settings.ai.testConnection": "Тестовое соединение", - "settings.ai.testError.noApiKey": "Не задан ключ API {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Тайм-аут соединения ({{url}})", - "settings.ai.testError.unreachable": "Недоступно ({{url}})", - "settings.ai.testError.pluginUnavailable": "Сеть локального сервера недоступна: не удалось загрузить настольный HTTP-плагин.", - "settings.ai.testError.desktopRequired": "Ollama и локальные серверы, совместимые с OpenAI, доступны только в настольном приложении. Браузеры блокируют прямые подключения с веб-страниц к localhost (CORS и Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude требует backend-прокси (ограничение CORS)", + "settings.ai.testError.desktopRequired": "Ollama и локальные серверы, совместимые с OpenAI, доступны только в настольном приложении. Браузеры блокируют прямые подключения с веб-страниц к localhost (CORS и Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Не задан ключ API {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU недоступен в этом браузере — WebLLM требует WebGPU (попробуйте Chrome/Edge или включите флаги).", - "settings.ai.testError.unknownProvider": "Неизвестный провайдер", + "settings.ai.testError.pluginUnavailable": "Сеть локального сервера недоступна: не удалось загрузить настольный HTTP-плагин.", + "settings.ai.testError.timeout": "Тайм-аут соединения ({{url}})", "settings.ai.testError.unexpected": "Произошла непредвиденная ошибка. Повторите попытку.", + "settings.ai.testError.unknownProvider": "Неизвестный провайдер", + "settings.ai.testError.unreachable": "Недоступно ({{url}})", "settings.ai.title": "Конфигурация ИИ", "settings.ai.transformers.hint": "Запускает любую Xenova-совместимую модель HuggingFace локально через WebAssembly или WebGPU.", "settings.ai.transformers.modelId": "Идентификатор модели (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "Если этот параметр включен, OpenRouter предпочтителен для вызовов облачного ИИ, если только активный режим не запрещает облако.", "settings.openRouter.errors.generic": "Произошла непредвиденная ошибка OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (бесплатно)", + "settings.openRouter.freeModel.fallbackNotice": "Отображается статический резервный список — прямой каталог OpenRouter сейчас недоступен.", "settings.openRouter.freeModel.gemma327b": "Джемма 3 27Б ИТ (бесплатно)", "settings.openRouter.freeModel.llama3370b": "Лама 3.3 70Б Инструкция (бесплатно)", "settings.openRouter.freeModel.mistral7b": "Мистраль 7Б Инструкт (бесплатно)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Не удалось загрузить каталог моделей.", "settings.openRouter.modelFetch.loading": "Загрузка каталога моделей…", "settings.openRouter.modelPlaceholder": "Выберите или найдите модель", + "settings.openRouter.modelUnavailable": "Эта модель отсутствует в текущем каталоге.", "settings.openRouter.paidModelNote": "Платные модели требуют кредитов на вашей учетной записи OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter заблокирован, поскольку включено «Только локальное хранилище». Отключите его в разделе «Конфиденциальность и данные», чтобы разрешить облачный искусственный интеллект.", "settings.openRouter.policyBlocked.mode": "OpenRouter недоступен, если режим AI локальный или эко. Чтобы использовать его, переключитесь на гибридный или облачный режим в разделе «ИИ и модели».", "settings.openRouter.preferredModel": "Предпочтительная модель", + "settings.openRouter.refreshModels": "Обновить модели", + "settings.openRouter.refreshModelsAriaLabel": "Обновить каталог моделей OpenRouter", "settings.openRouter.resetCircuit": "Перезагрузить", "settings.openRouter.resetCircuitAria": "Сброс автоматического выключателя OpenRouter", "settings.openRouter.rpmLabel": "Запросов/мин (последние 60 с)", "settings.openRouter.saveKey": "Сохранить", + "settings.openRouter.switchToAvailableModel": "Переключиться на доступную бесплатную модель", "settings.openRouter.testConnection": "Тестовое соединение", "settings.openRouter.testConnectionFailed": "Соединение не удалось", "settings.openRouter.testConnectionOk": "Соединение успешно", diff --git a/locales/sv/common.json b/locales/sv/common.json index 54ccedf39..ffa292103 100644 --- a/locales/sv/common.json +++ b/locales/sv/common.json @@ -347,7 +347,7 @@ "proforge.progress.metric.totalTime": "Total tid", "proforge.progress.metric.totalTokens": "Totala tokens", "proforge.progress.noneRunning": "Ingen pipeline igång.", - "proforge.progress.stageDetails": "Scendetaljer: {{stage}}", + "proforge.progress.stageDetails": "Stegdetaljer: {{stage}}", "proforge.progress.statusLabel": "Status", "proforge.progress.totals": "Rörledningssummor", "proforge.review.accept": "Acceptera", diff --git a/locales/sv/settings.json b/locales/sv/settings.json index 0e7479c56..519951cb7 100644 --- a/locales/sv/settings.json +++ b/locales/sv/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – Kreativt", "settings.ai.temperature.precise": "0 – Exakt", "settings.ai.testConnection": "Testa anslutningen", - "settings.ai.testError.noApiKey": "Ingen {{provider}}-API-nyckel angiven", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Anslutningen fick timeout ({{url}})", - "settings.ai.testError.unreachable": "Ej nåbar ({{url}})", - "settings.ai.testError.pluginUnavailable": "Lokal servernätverksanslutning ej tillgänglig: skrivbordets HTTP-plugin misslyckades med att läsas in.", - "settings.ai.testError.desktopRequired": "Ollama och lokala OpenAI-kompatibla servrar är endast tillgängliga i skrivbordsappen. Webbläsare blockerar direkta anslutningar från webbsidor till localhost (CORS och Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude kräver en backend-proxy (CORS-begränsning)", + "settings.ai.testError.desktopRequired": "Ollama och lokala OpenAI-kompatibla servrar är endast tillgängliga i skrivbordsappen. Webbläsare blockerar direkta anslutningar från webbsidor till localhost (CORS och Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Ingen {{provider}}-API-nyckel angiven", "settings.ai.testError.noWebgpu": "WebGPU är inte tillgängligt i den här webbläsaren — WebLLM behöver WebGPU (prova Chrome/Edge eller aktivera flaggor).", - "settings.ai.testError.unknownProvider": "Okänd leverantör", + "settings.ai.testError.pluginUnavailable": "Lokal servernätverksanslutning ej tillgänglig: skrivbordets HTTP-plugin misslyckades med att läsas in.", + "settings.ai.testError.timeout": "Anslutningen fick timeout ({{url}})", "settings.ai.testError.unexpected": "Ett oväntat fel inträffade. Försök igen.", + "settings.ai.testError.unknownProvider": "Okänd leverantör", + "settings.ai.testError.unreachable": "Ej nåbar ({{url}})", "settings.ai.title": "AI-konfiguration", "settings.ai.transformers.hint": "Kör valfri Xenova-kompatibel HuggingFace-modell lokalt via WebAssembly eller WebGPU.", "settings.ai.transformers.modelId": "Modell-ID (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "När den är aktiverad är OpenRouter att föredra för moln AI-samtal om inte det aktiva läget förbjuder moln.", "settings.openRouter.errors.generic": "Ett oväntat OpenRouter-fel inträffade", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Visar den statiska reservlistan — OpenRouters direktkatalog är inte tillgänglig just nu.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "Det gick inte att ladda modellkatalogen", "settings.openRouter.modelFetch.loading": "Laddar modellkatalog...", "settings.openRouter.modelPlaceholder": "Välj eller sök efter en modell", + "settings.openRouter.modelUnavailable": "Den här modellen finns inte i den aktuella katalogen.", "settings.openRouter.paidModelNote": "Betalmodeller kräver krediter på ditt OpenRouter-konto.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter är blockerad eftersom \"Endast lokal lagring\" är på. Stäng av den i Sekretess och data för att tillåta moln-AI.", "settings.openRouter.policyBlocked.mode": "OpenRouter är inte tillgängligt när AI-läget är lokalt eller eko. Byt till Hybrid eller Cloud i AI och modeller för att använda det.", "settings.openRouter.preferredModel": "Föredragen modell", + "settings.openRouter.refreshModels": "Uppdatera modeller", + "settings.openRouter.refreshModelsAriaLabel": "Uppdatera OpenRouter-modellkatalogen", "settings.openRouter.resetCircuit": "Återställa", "settings.openRouter.resetCircuitAria": "Återställ OpenRouter-strömbrytaren", "settings.openRouter.rpmLabel": "Förfrågningar/min (senaste 60 s)", "settings.openRouter.saveKey": "Spara", + "settings.openRouter.switchToAvailableModel": "Byt till en tillgänglig gratismodell", "settings.openRouter.testConnection": "Testa anslutningen", "settings.openRouter.testConnectionFailed": "Anslutning misslyckades", "settings.openRouter.testConnectionOk": "Anslutningen lyckades", diff --git a/locales/zh/settings.json b/locales/zh/settings.json index 98f9d0c28..1b62b7783 100644 --- a/locales/zh/settings.json +++ b/locales/zh/settings.json @@ -248,16 +248,16 @@ "settings.ai.temperature.creative": "2 – 创意", "settings.ai.temperature.precise": "0 – 精确", "settings.ai.testConnection": "测试连接", - "settings.ai.testError.noApiKey": "未设置 {{provider}} API 密钥", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "连接超时 ({{url}})", - "settings.ai.testError.unreachable": "无法访问 ({{url}})", - "settings.ai.testError.pluginUnavailable": "本地服务器网络不可用:桌面 HTTP 插件加载失败。", - "settings.ai.testError.desktopRequired": "Ollama 和本地 OpenAI 兼容服务器仅在桌面应用中可用。浏览器会阻止网页直接连接到 localhost(CORS 和 Private Network Access)。", "settings.ai.testError.backendProxyRequired": "Claude 需要后端代理(CORS 限制)", + "settings.ai.testError.desktopRequired": "Ollama 和本地 OpenAI 兼容服务器仅在桌面应用中可用。浏览器会阻止网页直接连接到 localhost(CORS 和 Private Network Access)。", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "未设置 {{provider}} API 密钥", "settings.ai.testError.noWebgpu": "此浏览器不支持 WebGPU — WebLLM 需要 WebGPU(请尝试 Chrome/Edge 或启用相关标志)。", - "settings.ai.testError.unknownProvider": "未知的提供商", + "settings.ai.testError.pluginUnavailable": "本地服务器网络不可用:桌面 HTTP 插件加载失败。", + "settings.ai.testError.timeout": "连接超时 ({{url}})", "settings.ai.testError.unexpected": "发生意外错误。请重试。", + "settings.ai.testError.unknownProvider": "未知的提供商", + "settings.ai.testError.unreachable": "无法访问 ({{url}})", "settings.ai.title": "人工智能配置", "settings.ai.transformers.hint": "通过 WebAssembly 或 WebGPU 在本地运行任何 Xenova 兼容的 HuggingFace 模型。", "settings.ai.transformers.modelId": "型号 ID (HuggingFace)", @@ -599,6 +599,7 @@ "settings.openRouter.enabledHint": "启用后,除非当前模式禁止云端,否则云端 AI 调用将优先使用 OpenRouter。", "settings.openRouter.errors.generic": "发生了意外的 OpenRouter 错误", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (免费)", + "settings.openRouter.freeModel.fallbackNotice": "正在显示静态后备列表 — 实时 OpenRouter 目录目前不可用。", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (免费)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (免费)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (免费)", @@ -621,14 +622,18 @@ "settings.openRouter.modelFetch.failed": "无法加载模型目录", "settings.openRouter.modelFetch.loading": "正在加载模型目录…", "settings.openRouter.modelPlaceholder": "选择或搜索模型", + "settings.openRouter.modelUnavailable": "该模型不在当前目录中。", "settings.openRouter.paidModelNote": "付费模型需要你的 OpenRouter 账户额度。", "settings.openRouter.policyBlocked.localOnly": "由于「仅本地存储」已开启,OpenRouter 被阻止。请在「隐私与数据」中将其关闭以允许云端 AI。", "settings.openRouter.policyBlocked.mode": "当 AI 模式为「本地」或「Eco」时,OpenRouter 不可用。请在「AI 与模型」中切换为「混合」或「云端」以使用它。", "settings.openRouter.preferredModel": "首选模型", + "settings.openRouter.refreshModels": "刷新模型", + "settings.openRouter.refreshModelsAriaLabel": "刷新 OpenRouter 模型目录", "settings.openRouter.resetCircuit": "重置", "settings.openRouter.resetCircuitAria": "重置 OpenRouter 断路器", "settings.openRouter.rpmLabel": "请求 / 分钟(最近 60 秒)", "settings.openRouter.saveKey": "保存", + "settings.openRouter.switchToAvailableModel": "切换到可用的免费模型", "settings.openRouter.testConnection": "测试连接", "settings.openRouter.testConnectionFailed": "连接失败", "settings.openRouter.testConnectionOk": "连接成功", diff --git a/public/locales/ar/bundle.json b/public/locales/ar/bundle.json index fef14a605..03226450c 100644 --- a/public/locales/ar/bundle.json +++ b/public/locales/ar/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – إبداعي", "settings.ai.temperature.precise": "0 – دقيق", "settings.ai.testConnection": "اختبار الاتصال", - "settings.ai.testError.noApiKey": "لم يتم تعيين مفتاح API لـ {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "انتهت مهلة الاتصال ({{url}})", - "settings.ai.testError.unreachable": "غير قابل للوصول ({{url}})", - "settings.ai.testError.pluginUnavailable": "شبكة الخادم المحلي غير متوفرة: فشل تحميل مكوّن HTTP لسطح المكتب.", - "settings.ai.testError.desktopRequired": "تتوفر Ollama والخوادم المحلية المتوافقة مع OpenAI فقط في تطبيق سطح المكتب. تحظر المتصفحات الاتصالات المباشرة من صفحات الويب بـ localhost (CORS وPrivate Network Access).", "settings.ai.testError.backendProxyRequired": "يتطلب Claude وكيل خلفية (قيود CORS)", + "settings.ai.testError.desktopRequired": "تتوفر Ollama والخوادم المحلية المتوافقة مع OpenAI فقط في تطبيق سطح المكتب. تحظر المتصفحات الاتصالات المباشرة من صفحات الويب بـ localhost (CORS وPrivate Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "لم يتم تعيين مفتاح API لـ {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU غير متوفر في هذا المتصفح — يحتاج WebLLM إلى WebGPU (جرّب Chrome/Edge أو فعّل العلامات).", - "settings.ai.testError.unknownProvider": "مزوّد غير معروف", + "settings.ai.testError.pluginUnavailable": "شبكة الخادم المحلي غير متوفرة: فشل تحميل مكوّن HTTP لسطح المكتب.", + "settings.ai.testError.timeout": "انتهت مهلة الاتصال ({{url}})", "settings.ai.testError.unexpected": "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى.", + "settings.ai.testError.unknownProvider": "مزوّد غير معروف", + "settings.ai.testError.unreachable": "غير قابل للوصول ({{url}})", "settings.ai.title": "إعداد الذكاء الاصطناعي", "settings.ai.transformers.hint": "يشغّل أي نموذج HuggingFace متوافق مع Xenova محليًا عبر WebAssembly أو WebGPU.", "settings.ai.transformers.modelId": "معرّف النموذج (HuggingFace)", @@ -2207,6 +2207,7 @@ "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.fallbackNotice": "يتم عرض قائمة احتياطية ثابتة — كتالوج OpenRouter المباشر غير متاح حاليًا.", "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)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Could not load model catalog", "settings.openRouter.modelFetch.loading": "Loading model catalog…", "settings.openRouter.modelPlaceholder": "deepseek/deepseek-r1:free", + "settings.openRouter.modelUnavailable": "هذا النموذج غير موجود في الكتالوج الحالي.", "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.refreshModels": "تحديث النماذج", + "settings.openRouter.refreshModelsAriaLabel": "تحديث كتالوج نماذج OpenRouter", "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.switchToAvailableModel": "التبديل إلى نموذج مجاني متاح", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/public/locales/de/bundle.json b/public/locales/de/bundle.json index e46fda227..c3e7c90d5 100644 --- a/public/locales/de/bundle.json +++ b/public/locales/de/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Kreativ", "settings.ai.temperature.precise": "0 – Präzise", "settings.ai.testConnection": "Verbindung testen", - "settings.ai.testError.noApiKey": "Kein {{provider}} API-Schlüssel gesetzt", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Zeitüberschreitung bei der Verbindung ({{url}})", - "settings.ai.testError.unreachable": "Nicht erreichbar ({{url}})", - "settings.ai.testError.pluginUnavailable": "Lokale Serververnetzung nicht verfügbar: Das Desktop-HTTP-Plugin konnte nicht geladen werden.", - "settings.ai.testError.desktopRequired": "Ollama und lokale OpenAI-kompatible Server sind nur in der Desktop-App verfügbar. Browser blockieren direkte Verbindungen von Webseiten zu localhost (CORS und Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude benötigt einen Backend-Proxy (CORS-Einschränkung)", + "settings.ai.testError.desktopRequired": "Ollama und lokale OpenAI-kompatible Server sind nur in der Desktop-App verfügbar. Browser blockieren direkte Verbindungen von Webseiten zu localhost (CORS und Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Kein {{provider}} API-Schlüssel gesetzt", "settings.ai.testError.noWebgpu": "WebGPU in diesem Browser nicht verfügbar — WebLLM benötigt WebGPU (Chrome/Edge verwenden oder Flags aktivieren).", - "settings.ai.testError.unknownProvider": "Unbekannter Anbieter", + "settings.ai.testError.pluginUnavailable": "Lokale Serververnetzung nicht verfügbar: Das Desktop-HTTP-Plugin konnte nicht geladen werden.", + "settings.ai.testError.timeout": "Zeitüberschreitung bei der Verbindung ({{url}})", "settings.ai.testError.unexpected": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.", + "settings.ai.testError.unknownProvider": "Unbekannter Anbieter", + "settings.ai.testError.unreachable": "Nicht erreichbar ({{url}})", "settings.ai.title": "KI-Konfiguration", "settings.ai.transformers.hint": "Führt jedes Xenova-kompatible HuggingFace-Modell lokal via WebAssembly oder WebGPU aus.", "settings.ai.transformers.modelId": "Modell-ID (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Wenn aktiviert, wird OpenRouter für Cloud-KI-Aufrufe bevorzugt, sofern der aktive Modus Cloud nicht verbietet.", "settings.openRouter.errors.generic": "Ein unerwarteter OpenRouter-Fehler ist aufgetreten", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Es wird die statische Fallback-Liste angezeigt — der Live-Modellkatalog von OpenRouter ist gerade nicht verfügbar.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Modellkatalog konnte nicht geladen werden", "settings.openRouter.modelFetch.loading": "Modellkatalog wird geladen …", "settings.openRouter.modelPlaceholder": "Modell auswählen oder suchen", + "settings.openRouter.modelUnavailable": "Dieses Modell ist nicht im aktuellen Katalog enthalten.", "settings.openRouter.paidModelNote": "Kostenpflichtige Modelle benötigen Guthaben auf deinem OpenRouter-Konto.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter ist blockiert, weil „Nur lokaler Speicher“ aktiviert ist. Deaktiviere es unter „Datenschutz & Daten“, um Cloud-KI zu erlauben.", "settings.openRouter.policyBlocked.mode": "OpenRouter ist im KI-Modus „Lokal“ oder „Eco“ nicht verfügbar. Wechsle unter „KI & Modelle“ zu Hybrid oder Cloud, um es zu nutzen.", "settings.openRouter.preferredModel": "Bevorzugtes Modell", + "settings.openRouter.refreshModels": "Modelle aktualisieren", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter-Modellkatalog aktualisieren", "settings.openRouter.resetCircuit": "Zurücksetzen", "settings.openRouter.resetCircuitAria": "OpenRouter-Schutzschalter zurücksetzen", "settings.openRouter.rpmLabel": "Anfragen / Min (letzte 60 s)", "settings.openRouter.saveKey": "Speichern", + "settings.openRouter.switchToAvailableModel": "Zu einem verfügbaren Free-Modell wechseln", "settings.openRouter.testConnection": "Verbindung testen", "settings.openRouter.testConnectionFailed": "Verbindung fehlgeschlagen", "settings.openRouter.testConnectionOk": "Verbindung erfolgreich", diff --git a/public/locales/el/bundle.json b/public/locales/el/bundle.json index e37d0607b..ea30e5760 100644 --- a/public/locales/el/bundle.json +++ b/public/locales/el/bundle.json @@ -463,7 +463,7 @@ "proforge.progress.metric.totalTime": "Συνολικός χρόνος", "proforge.progress.metric.totalTokens": "Σύνολο Μαρκών", "proforge.progress.noneRunning": "Δεν λειτουργεί αγωγός.", - "proforge.progress.stageDetails": "Λεπτομέρειες σκηνής: {{stage}}", + "proforge.progress.stageDetails": "Λεπτομέρειες σταδίου: {{stage}}", "proforge.progress.statusLabel": "Κατάσταση", "proforge.progress.totals": "Σύνολα αγωγών", "proforge.review.accept": "Αποδέχομαι", @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Δημιουργικό", "settings.ai.temperature.precise": "0 – Ακριβές", "settings.ai.testConnection": "Δοκιμαστική σύνδεση", - "settings.ai.testError.noApiKey": "Δεν έχει οριστεί κλειδί API {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Λήξη χρονικού ορίου σύνδεσης ({{url}})", - "settings.ai.testError.unreachable": "Μη προσβάσιμο ({{url}})", - "settings.ai.testError.pluginUnavailable": "Το δίκτυο τοπικού διακομιστή δεν είναι διαθέσιμο: η πρόσθετη λειτουργία HTTP επιφάνειας εργασίας απέτυχε να φορτωθεί.", - "settings.ai.testError.desktopRequired": "Το Ollama και οι τοπικοί διακομιστές συμβατοί με OpenAI είναι διαθέσιμοι μόνο στην εφαρμογή επιφάνειας εργασίας. Οι φυλλομετρητές αποκλείουν άμεσες συνδέσεις από ιστοσελίδες προς το localhost (CORS και Private Network Access).", "settings.ai.testError.backendProxyRequired": "Το Claude απαιτεί διακομιστή μεσολάβησης backend (περιορισμός CORS)", + "settings.ai.testError.desktopRequired": "Το Ollama και οι τοπικοί διακομιστές συμβατοί με OpenAI είναι διαθέσιμοι μόνο στην εφαρμογή επιφάνειας εργασίας. Οι φυλλομετρητές αποκλείουν άμεσες συνδέσεις από ιστοσελίδες προς το localhost (CORS και Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Δεν έχει οριστεί κλειδί API {{provider}}", "settings.ai.testError.noWebgpu": "Το WebGPU δεν είναι διαθέσιμο σε αυτό το πρόγραμμα περιήγησης — το WebLLM απαιτεί WebGPU (δοκιμάστε Chrome/Edge ή ενεργοποιήστε τις σημαίες).", - "settings.ai.testError.unknownProvider": "Άγνωστος πάροχος", + "settings.ai.testError.pluginUnavailable": "Το δίκτυο τοπικού διακομιστή δεν είναι διαθέσιμο: η πρόσθετη λειτουργία HTTP επιφάνειας εργασίας απέτυχε να φορτωθεί.", + "settings.ai.testError.timeout": "Λήξη χρονικού ορίου σύνδεσης ({{url}})", "settings.ai.testError.unexpected": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα. Δοκιμάστε ξανά.", + "settings.ai.testError.unknownProvider": "Άγνωστος πάροχος", + "settings.ai.testError.unreachable": "Μη προσβάσιμο ({{url}})", "settings.ai.title": "Διαμόρφωση AI", "settings.ai.transformers.hint": "Εκτελεί οποιοδήποτε μοντέλο HuggingFace συμβατό με Xenova τοπικά μέσω WebAssembly ή WebGPU.", "settings.ai.transformers.modelId": "Αναγνωριστικό μοντέλου (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Όταν είναι ενεργό, το OpenRouter προτιμάται για κλήσεις AI cloud, εκτός αν η ενεργή λειτουργία απαγορεύει το cloud.", "settings.openRouter.errors.generic": "Παρουσιάστηκε ένα μη αναμενόμενο σφάλμα OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (δωρεάν)", + "settings.openRouter.freeModel.fallbackNotice": "Εμφάνιση της στατικής εφεδρικής λίστας — ο ζωντανός κατάλογος του OpenRouter δεν είναι διαθέσιμος αυτήν τη στιγμή.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (δωρεάν)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (δωρεάν)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (δωρεάν)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Δεν ήταν δυνατή η φόρτωση του καταλόγου μοντέλων", "settings.openRouter.modelFetch.loading": "Φόρτωση καταλόγου μοντέλων…", "settings.openRouter.modelPlaceholder": "Επίλεξε ή αναζήτησε ένα μοντέλο", + "settings.openRouter.modelUnavailable": "Αυτό το μοντέλο δεν υπάρχει στον τρέχοντα κατάλογο.", "settings.openRouter.paidModelNote": "Τα επί πληρωμή μοντέλα απαιτούν πιστώσεις στον λογαριασμό σου OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "Το OpenRouter αποκλείεται επειδή είναι ενεργή η «Μόνο τοπική αποθήκευση». Απενεργοποιήστε την στο «Απόρρητο και Δεδομένα» για να επιτρέψετε το cloud AI.", "settings.openRouter.policyBlocked.mode": "Το OpenRouter δεν είναι διαθέσιμο όταν η λειτουργία AI είναι «Τοπική» ή «Eco». Μεταβείτε σε «Υβριδική» ή «Cloud» στο «AI και Μοντέλα» για να το χρησιμοποιήσετε.", "settings.openRouter.preferredModel": "Προτιμώμενο μοντέλο", + "settings.openRouter.refreshModels": "Ανανέωση μοντέλων", + "settings.openRouter.refreshModelsAriaLabel": "Ανανέωση του καταλόγου μοντέλων OpenRouter", "settings.openRouter.resetCircuit": "Επαναφορά", "settings.openRouter.resetCircuitAria": "Επαναφορά του διακόπτη προστασίας OpenRouter", "settings.openRouter.rpmLabel": "Αιτήματα / λεπτό (τελευταία 60 δ)", "settings.openRouter.saveKey": "Αποθήκευση", + "settings.openRouter.switchToAvailableModel": "Μετάβαση σε διαθέσιμο δωρεάν μοντέλο", "settings.openRouter.testConnection": "Δοκιμή σύνδεσης", "settings.openRouter.testConnectionFailed": "Αποτυχία σύνδεσης", "settings.openRouter.testConnectionOk": "Επιτυχής σύνδεση", diff --git a/public/locales/en/bundle.json b/public/locales/en/bundle.json index c7143f0f4..fc4e3d4ea 100644 --- a/public/locales/en/bundle.json +++ b/public/locales/en/bundle.json @@ -2207,6 +2207,7 @@ "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.fallbackNotice": "Showing the static fallback list — the live OpenRouter catalog is unavailable right now.", "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)", @@ -2229,14 +2230,18 @@ "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.modelUnavailable": "This model isn't in the current catalog.", "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.refreshModels": "Refresh models", + "settings.openRouter.refreshModelsAriaLabel": "Refresh the OpenRouter model catalog", "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.switchToAvailableModel": "Switch to an available free model", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/public/locales/es/bundle.json b/public/locales/es/bundle.json index 217267e97..9bc1fd030 100644 --- a/public/locales/es/bundle.json +++ b/public/locales/es/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Probar conexión", - "settings.ai.testError.noApiKey": "No se ha configurado una clave de API de {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tiempo de espera agotado ({{url}})", - "settings.ai.testError.unreachable": "No accesible ({{url}})", - "settings.ai.testError.pluginUnavailable": "La red de servidores locales no está disponible: el plugin HTTP de escritorio no se pudo cargar.", - "settings.ai.testError.desktopRequired": "Ollama y los servidores locales compatibles con OpenAI solo están disponibles en la aplicación de escritorio. Los navegadores bloquean las conexiones directas desde páginas web a localhost (CORS y Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude requiere un proxy de backend (restricción CORS)", + "settings.ai.testError.desktopRequired": "Ollama y los servidores locales compatibles con OpenAI solo están disponibles en la aplicación de escritorio. Los navegadores bloquean las conexiones directas desde páginas web a localhost (CORS y Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "No se ha configurado una clave de API de {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU no disponible en este navegador — WebLLM necesita WebGPU (prueba Chrome/Edge o activa las opciones).", - "settings.ai.testError.unknownProvider": "Proveedor desconocido", + "settings.ai.testError.pluginUnavailable": "La red de servidores locales no está disponible: el plugin HTTP de escritorio no se pudo cargar.", + "settings.ai.testError.timeout": "Tiempo de espera agotado ({{url}})", "settings.ai.testError.unexpected": "Se produjo un error inesperado. Inténtalo de nuevo.", + "settings.ai.testError.unknownProvider": "Proveedor desconocido", + "settings.ai.testError.unreachable": "No accesible ({{url}})", "settings.ai.title": "Configuración de IA", "settings.ai.transformers.hint": "Ejecuta cualquier modelo HuggingFace compatible con Xenova localmente vía WebAssembly o WebGPU.", "settings.ai.transformers.modelId": "ID del modelo (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Cuando está activado, se prefiere OpenRouter para las llamadas de IA en la nube, salvo que el modo activo prohíba la nube.", "settings.openRouter.errors.generic": "Se produjo un error inesperado de OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Mostrando la lista de reserva estática — el catálogo en vivo de OpenRouter no está disponible en este momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "No se pudo cargar el catálogo de modelos", "settings.openRouter.modelFetch.loading": "Cargando catálogo de modelos…", "settings.openRouter.modelPlaceholder": "Selecciona o busca un modelo", + "settings.openRouter.modelUnavailable": "Este modelo no está en el catálogo actual.", "settings.openRouter.paidModelNote": "Los modelos de pago requieren créditos en tu cuenta de OpenRouter.", - "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.localOnly": "OpenRouter está bloqueado porque “Solo almacenamiento local” está activado. Desactívalo 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.refreshModels": "Actualizar modelos", + "settings.openRouter.refreshModelsAriaLabel": "Actualizar el catálogo de modelos de OpenRouter", "settings.openRouter.resetCircuit": "Restablecer", "settings.openRouter.resetCircuitAria": "Restablecer el cortacircuitos de OpenRouter", "settings.openRouter.rpmLabel": "Solicitudes / min (últimos 60 s)", "settings.openRouter.saveKey": "Guardar", + "settings.openRouter.switchToAvailableModel": "Cambiar a un modelo gratuito disponible", "settings.openRouter.testConnection": "Probar conexión", "settings.openRouter.testConnectionFailed": "Error de conexión", "settings.openRouter.testConnectionOk": "Conexión correcta", diff --git a/public/locales/eu/bundle.json b/public/locales/eu/bundle.json index b0ac3da7d..4429ecdc6 100644 --- a/public/locales/eu/bundle.json +++ b/public/locales/eu/bundle.json @@ -779,7 +779,7 @@ "voice.cancelSpeech": "Hitzaldia bertan behera utzi", "voice.modeChip.commands": "Komandoak", "voice.modeChip.dictation": "Diktaketa", - "voice.feedback.confidence": "Konfiantza %{{percent}}", + "voice.feedback.confidence": "Konfiantza: {{percent}}%", "voice.panelLabel": "Ahots kontrola", "voice.permissionDenied": "Mikrofonorako sarbidea ukatu da. Mesedez, baimendu mikrofonorako sarbidea zure arakatzailearen ezarpenetan ahots-eginbideak erabiltzeko.", "voice.startDictation": "Hasi diktaketa", @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Sormena", "settings.ai.temperature.precise": "0 – Zehatza", "settings.ai.testConnection": "Probatu konexioa", - "settings.ai.testError.noApiKey": "Ez da {{provider}} API gakorik ezarri", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Konexioak denbora-muga gainditu du ({{url}})", - "settings.ai.testError.unreachable": "Ezin da iritsi ({{url}})", - "settings.ai.testError.pluginUnavailable": "Zerbitzari lokalaren sarea ez dago erabilgarri: mahaigaineko HTTP pluginak huts egin du kargatzean.", - "settings.ai.testError.desktopRequired": "Ollama eta OpenAI-rekin bateragarriak diren zerbitzari lokalak mahaigaineko aplikazioan bakarrik daude erabilgarri. Nabigatzaileek web orrialdeetatik localhost-era zuzeneko konexioak blokeatzen dituzte (CORS eta Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude-k backend proxy bat behar du (CORS murrizketa)", + "settings.ai.testError.desktopRequired": "Ollama eta OpenAI-rekin bateragarriak diren zerbitzari lokalak mahaigaineko aplikazioan bakarrik daude erabilgarri. Nabigatzaileek web orrialdeetatik localhost-era zuzeneko konexioak blokeatzen dituzte (CORS eta Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Ez da {{provider}} API gakorik ezarri", "settings.ai.testError.noWebgpu": "WebGPU ez dago erabilgarri nabigatzaile honetan — WebLLM-ek WebGPU behar du (probatu Chrome/Edge edo gaitu banderak).", - "settings.ai.testError.unknownProvider": "Hornitzaile ezezaguna", + "settings.ai.testError.pluginUnavailable": "Zerbitzari lokalaren sarea ez dago erabilgarri: mahaigaineko HTTP pluginak huts egin du kargatzean.", + "settings.ai.testError.timeout": "Konexioak denbora-muga gainditu du ({{url}})", "settings.ai.testError.unexpected": "Ustekabeko errorea gertatu da. Saiatu berriro.", + "settings.ai.testError.unknownProvider": "Hornitzaile ezezaguna", + "settings.ai.testError.unreachable": "Ezin da iritsi ({{url}})", "settings.ai.title": "AI konfigurazioa", "settings.ai.transformers.hint": "Xenova-rekin bateragarria den HuggingFace modelo edozein exekutatzen du lokalean WebAssembly edo WebGPU bidez.", "settings.ai.transformers.modelId": "Modelo ID (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Gaituta dagoenean, OpenRouter hobesten da hodeiko AI deiak egiteko, modu aktiboak hodeia debekatzen ez badu.", "settings.openRouter.errors.generic": "Ustekabeko OpenRouter errore bat gertatu da", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (doan)", + "settings.openRouter.freeModel.fallbackNotice": "Zerrenda estatiko alternatiboa erakusten — OpenRouter-en zuzeneko katalogoa ez dago erabilgarri une honetan.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (doan)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (doan)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (doan)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Ezin izan da ereduen katalogoa kargatu", "settings.openRouter.modelFetch.loading": "Modeloen katalogoa kargatzen…", "settings.openRouter.modelPlaceholder": "Aukeratu edo bilatu eredu bat", + "settings.openRouter.modelUnavailable": "Eredu hau ez dago uneko katalogoan.", "settings.openRouter.paidModelNote": "Ordainpeko ereduek zure OpenRouter kontuan kredituak behar dituzte.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter blokeatuta dago \"Biltegiratze lokala soilik\" aktibatuta dagoelako. Desaktibatu Pribatutasuna eta Datuetan hodeiko AI ahalbidetzeko.", "settings.openRouter.policyBlocked.mode": "OpenRouter ez dago erabilgarri AI modua Tokikoa edo Ekokoa den bitartean. Erabili ahal izateko, aldatu hibrido edo hodeiko AI eta ereduetan.", "settings.openRouter.preferredModel": "Eredu hobetsia", + "settings.openRouter.refreshModels": "Ereduak eguneratu", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter eredu-katalogoa eguneratu", "settings.openRouter.resetCircuit": "Berrezarri", "settings.openRouter.resetCircuitAria": "Berrezarri OpenRouter etengailua", "settings.openRouter.rpmLabel": "Eskaerak/min (azken 60 s)", "settings.openRouter.saveKey": "Gorde", + "settings.openRouter.switchToAvailableModel": "Eskuragarri dagoen doako eredu batera aldatu", "settings.openRouter.testConnection": "Probatu konexioa", "settings.openRouter.testConnectionFailed": "Konexioak huts egin du", "settings.openRouter.testConnectionOk": "Konexioa arrakastatsua da", diff --git a/public/locales/fa/bundle.json b/public/locales/fa/bundle.json index 51f95b5d5..d12b91284 100644 --- a/public/locales/fa/bundle.json +++ b/public/locales/fa/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2- خلاق", "settings.ai.temperature.precise": "0 - دقیق", "settings.ai.testConnection": "تست اتصال", - "settings.ai.testError.noApiKey": "کلید API {{provider}} تنظیم نشده است", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "زمان اتصال به پایان رسید ({{url}})", - "settings.ai.testError.unreachable": "در دسترس نیست ({{url}})", - "settings.ai.testError.pluginUnavailable": "شبکهسازی سرور محلی در دسترس نیست: بارگذاری افزونه HTTP دسکتاپ ناموفق بود.", - "settings.ai.testError.desktopRequired": "Ollama و سرورهای محلی سازگار با OpenAI فقط در برنامه دسکتاپ در دسترس هستند. مرورگرها اتصالات مستقیم از صفحات وب به localhost را مسدود میکنند (CORS و Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude به یک پراکسی بکاند نیاز دارد (محدودیت CORS)", + "settings.ai.testError.desktopRequired": "Ollama و سرورهای محلی سازگار با OpenAI فقط در برنامه دسکتاپ در دسترس هستند. مرورگرها اتصالات مستقیم از صفحات وب به localhost را مسدود میکنند (CORS و Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "کلید API {{provider}} تنظیم نشده است", "settings.ai.testError.noWebgpu": "WebGPU در این مرورگر در دسترس نیست — WebLLM به WebGPU نیاز دارد (Chrome/Edge را امتحان کنید یا پرچمها را فعال کنید).", - "settings.ai.testError.unknownProvider": "ارائهدهنده ناشناخته", + "settings.ai.testError.pluginUnavailable": "شبکهسازی سرور محلی در دسترس نیست: بارگذاری افزونه HTTP دسکتاپ ناموفق بود.", + "settings.ai.testError.timeout": "زمان اتصال به پایان رسید ({{url}})", "settings.ai.testError.unexpected": "خطای غیرمنتظرهای رخ داد. لطفاً دوباره امتحان کنید.", + "settings.ai.testError.unknownProvider": "ارائهدهنده ناشناخته", + "settings.ai.testError.unreachable": "در دسترس نیست ({{url}})", "settings.ai.title": "پیکربندی هوش مصنوعی", "settings.ai.transformers.hint": "هر مدل HuggingFace سازگار با Xenova را به صورت محلی از طریق WebAssembly یا WebGPU اجرا می کند.", "settings.ai.transformers.modelId": "شناسه مدل (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "وقتی فعال باشد، OpenRouter برای تماسهای ابری AI ترجیح داده میشود، مگر اینکه حالت فعال ابر را ممنوع کند.", "settings.openRouter.errors.generic": "یک خطای غیرمنتظره OpenRouter رخ داد", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (رایگان)", + "settings.openRouter.freeModel.fallbackNotice": "نمایش فهرست جایگزین ثابت — کاتالوگ زنده OpenRouter در حال حاضر در دسترس نیست.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (رایگان)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (رایگان)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (رایگان)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "کاتالوگ مدل بارگیری نشد", "settings.openRouter.modelFetch.loading": "در حال بارگیری کاتالوگ مدل…", "settings.openRouter.modelPlaceholder": "یک مدل را انتخاب یا جستجو کنید", + "settings.openRouter.modelUnavailable": "این مدل در کاتالوگ فعلی وجود ندارد.", "settings.openRouter.paidModelNote": "مدلهای پولی به اعتبار حساب OpenRouter شما نیاز دارند.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter مسدود شده است زیرا «فقط ذخیرهسازی محلی» روشن است. Turn it off in Privacy & Data to allow cloud AI.", "settings.openRouter.policyBlocked.mode": "در حالی که حالت هوش مصنوعی Local یا Eco است، OpenRouter در دسترس نیست. برای استفاده از آن، در هوش مصنوعی و مدلها به Hybrid یا Cloud بروید.", "settings.openRouter.preferredModel": "مدل ترجیحی", + "settings.openRouter.refreshModels": "بهروزرسانی مدلها", + "settings.openRouter.refreshModelsAriaLabel": "بهروزرسانی کاتالوگ مدلهای OpenRouter", "settings.openRouter.resetCircuit": "بازنشانی کنید", "settings.openRouter.resetCircuitAria": "قطع کننده مدار OpenRouter را بازنشانی کنید", "settings.openRouter.rpmLabel": "درخواست ها / دقیقه (60 ثانیه گذشته)", "settings.openRouter.saveKey": "ذخیره", + "settings.openRouter.switchToAvailableModel": "تغییر به یک مدل رایگان در دسترس", "settings.openRouter.testConnection": "تست اتصال", "settings.openRouter.testConnectionFailed": "اتصال ناموفق بود", "settings.openRouter.testConnectionOk": "اتصال با موفقیت انجام شد", diff --git a/public/locales/fi/bundle.json b/public/locales/fi/bundle.json index bba50bfe4..306b5ac75 100644 --- a/public/locales/fi/bundle.json +++ b/public/locales/fi/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Luova", "settings.ai.temperature.precise": "0 – Tarkka", "settings.ai.testConnection": "Testaa yhteys", - "settings.ai.testError.noApiKey": "{{provider}}-API-avainta ei ole asetettu", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Yhteys aikakatkaistiin ({{url}})", - "settings.ai.testError.unreachable": "Ei tavoiteta ({{url}})", - "settings.ai.testError.pluginUnavailable": "Paikallisen palvelimen verkko ei ole käytettävissä: työpöydän HTTP-lisäosan lataus epäonnistui.", - "settings.ai.testError.desktopRequired": "Ollama ja paikalliset OpenAI-yhteensopivat palvelimet ovat käytettävissä vain työpöytäsovelluksessa. Selaimet estävät suorat yhteydet verkkosivuilta osoitteeseen localhost (CORS ja Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude vaatii taustajärjestelmän välityspalvelimen (CORS-rajoitus)", + "settings.ai.testError.desktopRequired": "Ollama ja paikalliset OpenAI-yhteensopivat palvelimet ovat käytettävissä vain työpöytäsovelluksessa. Selaimet estävät suorat yhteydet verkkosivuilta osoitteeseen localhost (CORS ja Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}}-API-avainta ei ole asetettu", "settings.ai.testError.noWebgpu": "WebGPU ei ole käytettävissä tässä selaimessa — WebLLM tarvitsee WebGPU:n (kokeile Chromea/Edgeä tai ota liput käyttöön).", - "settings.ai.testError.unknownProvider": "Tuntematon palveluntarjoaja", + "settings.ai.testError.pluginUnavailable": "Paikallisen palvelimen verkko ei ole käytettävissä: työpöydän HTTP-lisäosan lataus epäonnistui.", + "settings.ai.testError.timeout": "Yhteys aikakatkaistiin ({{url}})", "settings.ai.testError.unexpected": "Tapahtui odottamaton virhe. Yritä uudelleen.", + "settings.ai.testError.unknownProvider": "Tuntematon palveluntarjoaja", + "settings.ai.testError.unreachable": "Ei tavoiteta ({{url}})", "settings.ai.title": "AI-kokoonpano", "settings.ai.transformers.hint": "Suorittaa mitä tahansa Xenova-yhteensopivaa HuggingFace-mallia paikallisesti WebAssemblyn tai WebGPU:n kautta.", "settings.ai.transformers.modelId": "Mallin tunnus (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Kun OpenRouter on käytössä, sitä suositellaan pilvi-AI-kutsuille, ellei aktiivinen tila estä pilven käyttöä.", "settings.openRouter.errors.generic": "Tapahtui odottamaton OpenRouter-virhe", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ilmainen)", + "settings.openRouter.freeModel.fallbackNotice": "Näytetään staattinen varaluettelo — OpenRouterin reaaliaikainen luettelo ei ole juuri nyt käytettävissä.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ilmainen)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ilmainen)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ilmainen)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Malliluetteloa ei voitu ladata", "settings.openRouter.modelFetch.loading": "Ladataan malliluetteloa…", "settings.openRouter.modelPlaceholder": "Valitse tai etsi malli", + "settings.openRouter.modelUnavailable": "Tämä malli ei ole nykyisessä luettelossa.", "settings.openRouter.paidModelNote": "Maksulliset mallit vaativat hyvitystä OpenRouter-tililläsi.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter on estetty, koska \"Vain paikallinen tallennus\" on päällä. Ota se käyttöön Privacy & Data -kohdassa salliaksesi pilvi-AI.", "settings.openRouter.policyBlocked.mode": "OpenRouter ei ole käytettävissä, kun AI-tila on Local tai Eco. Käytä tekoälyssä ja malleissa hybridi- tai pilvipalvelua.", "settings.openRouter.preferredModel": "Suosittu malli", + "settings.openRouter.refreshModels": "Päivitä mallit", + "settings.openRouter.refreshModelsAriaLabel": "Päivitä OpenRouter-malliluettelo", "settings.openRouter.resetCircuit": "Nollaa", "settings.openRouter.resetCircuitAria": "Nollaa OpenRouter-katkaisija", "settings.openRouter.rpmLabel": "Pyynnöt/min (viimeiset 60 s)", "settings.openRouter.saveKey": "Tallenna", + "settings.openRouter.switchToAvailableModel": "Vaihda saatavilla olevaan ilmaiseen malliin", "settings.openRouter.testConnection": "Testaa yhteys", "settings.openRouter.testConnectionFailed": "Yhteys epäonnistui", "settings.openRouter.testConnectionOk": "Yhteys onnistui", diff --git a/public/locales/fr/bundle.json b/public/locales/fr/bundle.json index 88a638063..a7d24f71c 100644 --- a/public/locales/fr/bundle.json +++ b/public/locales/fr/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Créatif", "settings.ai.temperature.precise": "0 – Précis", "settings.ai.testConnection": "Tester la connexion", - "settings.ai.testError.noApiKey": "Aucune clé API {{provider}} définie", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Délai de connexion dépassé ({{url}})", - "settings.ai.testError.unreachable": "Injoignable ({{url}})", - "settings.ai.testError.pluginUnavailable": "Le réseau des serveurs locaux est indisponible : le plugin HTTP du bureau n'a pas pu se charger.", - "settings.ai.testError.desktopRequired": "Ollama et les serveurs locaux compatibles OpenAI ne sont disponibles que dans l'application de bureau. Les navigateurs bloquent les connexions directes des pages web vers localhost (CORS et Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude nécessite un proxy backend (restriction CORS)", + "settings.ai.testError.desktopRequired": "Ollama et les serveurs locaux compatibles OpenAI ne sont disponibles que dans l'application de bureau. Les navigateurs bloquent les connexions directes des pages web vers localhost (CORS et Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Aucune clé API {{provider}} définie", "settings.ai.testError.noWebgpu": "WebGPU indisponible dans ce navigateur — WebLLM nécessite WebGPU (essayez Chrome/Edge ou activez les indicateurs).", - "settings.ai.testError.unknownProvider": "Fournisseur inconnu", + "settings.ai.testError.pluginUnavailable": "Le réseau des serveurs locaux est indisponible : le plugin HTTP du bureau n'a pas pu se charger.", + "settings.ai.testError.timeout": "Délai de connexion dépassé ({{url}})", "settings.ai.testError.unexpected": "Une erreur inattendue s'est produite. Veuillez réessayer.", + "settings.ai.testError.unknownProvider": "Fournisseur inconnu", + "settings.ai.testError.unreachable": "Injoignable ({{url}})", "settings.ai.title": "Configuration de l'IA", "settings.ai.transformers.hint": "Exécute tout modèle HuggingFace compatible Xenova localement via WebAssembly ou WebGPU.", "settings.ai.transformers.modelId": "ID du modèle (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Lorsqu'il est activé, OpenRouter est privilégié pour les appels d'IA cloud, sauf si le mode actif interdit le cloud.", "settings.openRouter.errors.generic": "Une erreur OpenRouter inattendue s'est produite", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratuit)", + "settings.openRouter.freeModel.fallbackNotice": "Affichage de la liste de secours statique — le catalogue OpenRouter en direct n'est pas disponible pour le moment.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratuit)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratuit)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratuit)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Impossible de charger le catalogue de modèles", "settings.openRouter.modelFetch.loading": "Chargement du catalogue de modèles…", "settings.openRouter.modelPlaceholder": "Sélectionner ou rechercher un modèle", + "settings.openRouter.modelUnavailable": "Ce modèle ne figure pas dans le catalogue actuel.", "settings.openRouter.paidModelNote": "Les modèles payants nécessitent des crédits sur votre compte OpenRouter.", "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.refreshModels": "Actualiser les modèles", + "settings.openRouter.refreshModelsAriaLabel": "Actualiser le catalogue de modèles OpenRouter", "settings.openRouter.resetCircuit": "Réinitialiser", "settings.openRouter.resetCircuitAria": "Réinitialiser le disjoncteur OpenRouter", "settings.openRouter.rpmLabel": "Requêtes / min (60 dernières s)", "settings.openRouter.saveKey": "Enregistrer", + "settings.openRouter.switchToAvailableModel": "Passer à un modèle gratuit disponible", "settings.openRouter.testConnection": "Tester la connexion", "settings.openRouter.testConnectionFailed": "Échec de la connexion", "settings.openRouter.testConnectionOk": "Connexion réussie", diff --git a/public/locales/he/bundle.json b/public/locales/he/bundle.json index da33b39e5..77035a293 100644 --- a/public/locales/he/bundle.json +++ b/public/locales/he/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – יצירתי", "settings.ai.temperature.precise": "0 – מדויק", "settings.ai.testConnection": "בדיקת חיבור", - "settings.ai.testError.noApiKey": "לא הוגדר מפתח API עבור {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "פסק הזמן של החיבור פג ({{url}})", - "settings.ai.testError.unreachable": "לא ניתן להגיע ({{url}})", - "settings.ai.testError.pluginUnavailable": "רשת השרת המקומי אינה זמינה: תוסף ה-HTTP של שולחן העבודה נכשל בטעינה.", - "settings.ai.testError.desktopRequired": "Ollama ושרתים מקומיים תואמי OpenAI זמינים רק באפליקציית שולחן העבודה. דפדפנים חוסמים חיבורים ישירים מדפי אינטרנט אל localhost (CORS ו-Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude דורש שרת proxy (הגבלת CORS)", + "settings.ai.testError.desktopRequired": "Ollama ושרתים מקומיים תואמי OpenAI זמינים רק באפליקציית שולחן העבודה. דפדפנים חוסמים חיבורים ישירים מדפי אינטרנט אל localhost (CORS ו-Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "לא הוגדר מפתח API עבור {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU אינו זמין בדפדפן זה — WebLLM דורש WebGPU (נסה Chrome/Edge או הפעל דגלים).", - "settings.ai.testError.unknownProvider": "ספק לא ידוע", + "settings.ai.testError.pluginUnavailable": "רשת השרת המקומי אינה זמינה: תוסף ה-HTTP של שולחן העבודה נכשל בטעינה.", + "settings.ai.testError.timeout": "פסק הזמן של החיבור פג ({{url}})", "settings.ai.testError.unexpected": "אירעה שגיאה בלתי צפויה. נסה שוב.", + "settings.ai.testError.unknownProvider": "ספק לא ידוע", + "settings.ai.testError.unreachable": "לא ניתן להגיע ({{url}})", "settings.ai.title": "תצורת AI", "settings.ai.transformers.hint": "מריץ כל מודל HuggingFace תואם‑Xenova מקומית דרך WebAssembly או WebGPU.", "settings.ai.transformers.modelId": "מזהה מודל (HuggingFace)", @@ -2207,6 +2207,7 @@ "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.fallbackNotice": "מוצגת רשימת גיבוי סטטית — קטלוג ה-OpenRouter החי אינו זמין כרגע.", "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)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Could not load model catalog", "settings.openRouter.modelFetch.loading": "Loading model catalog…", "settings.openRouter.modelPlaceholder": "deepseek/deepseek-r1:free", + "settings.openRouter.modelUnavailable": "דגם זה אינו נמצא בקטלוג הנוכחי.", "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.refreshModels": "רענון דגמים", + "settings.openRouter.refreshModelsAriaLabel": "רענון קטלוג הדגמים של OpenRouter", "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.switchToAvailableModel": "מעבר לדגם חינמי זמין", "settings.openRouter.testConnection": "Test connection", "settings.openRouter.testConnectionFailed": "Connection failed", "settings.openRouter.testConnectionOk": "Connection successful", diff --git a/public/locales/hu/bundle.json b/public/locales/hu/bundle.json index 3b838e723..dada5bb60 100644 --- a/public/locales/hu/bundle.json +++ b/public/locales/hu/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Kreatív", "settings.ai.temperature.precise": "0 – Pontos", "settings.ai.testConnection": "Kapcsolat tesztelése", - "settings.ai.testError.noApiKey": "Nincs beállítva {{provider}} API-kulcs", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "A kapcsolat túllépte az időkorlátot ({{url}})", - "settings.ai.testError.unreachable": "Nem érhető el ({{url}})", - "settings.ai.testError.pluginUnavailable": "A helyi kiszolgálóhálózat nem érhető el: az asztali HTTP bővítmény betöltése sikertelen.", - "settings.ai.testError.desktopRequired": "Az Ollama és a helyi OpenAI-kompatibilis kiszolgálók csak az asztali alkalmazásban érhetők el. A böngészők blokkolják a weboldalak közvetlen kapcsolatait a localhosttal (CORS és Private Network Access).", "settings.ai.testError.backendProxyRequired": "A Claude háttérproxyt igényel (CORS-korlátozás)", + "settings.ai.testError.desktopRequired": "Az Ollama és a helyi OpenAI-kompatibilis kiszolgálók csak az asztali alkalmazásban érhetők el. A böngészők blokkolják a weboldalak közvetlen kapcsolatait a localhosttal (CORS és Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nincs beállítva {{provider}} API-kulcs", "settings.ai.testError.noWebgpu": "A WebGPU nem érhető el ebben a böngészőben — a WebLLM-nek WebGPU-ra van szüksége (próbáld a Chrome-ot/Edge-et, vagy engedélyezd a jelzőket).", - "settings.ai.testError.unknownProvider": "Ismeretlen szolgáltató", + "settings.ai.testError.pluginUnavailable": "A helyi kiszolgálóhálózat nem érhető el: az asztali HTTP bővítmény betöltése sikertelen.", + "settings.ai.testError.timeout": "A kapcsolat túllépte az időkorlátot ({{url}})", "settings.ai.testError.unexpected": "Váratlan hiba történt. Kérjük, próbálja újra.", + "settings.ai.testError.unknownProvider": "Ismeretlen szolgáltató", + "settings.ai.testError.unreachable": "Nem érhető el ({{url}})", "settings.ai.title": "AI konfiguráció", "settings.ai.transformers.hint": "Bármilyen Xenova-kompatibilis HuggingFace modellt futtat helyileg a WebAssembly vagy WebGPU segítségével.", "settings.ai.transformers.modelId": "Modellazonosító (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Ha engedélyezve van, az OpenRouter előnyben részesíti a felhőalapú mesterséges intelligencia hívásait, hacsak az aktív mód nem tiltja a felhőt.", "settings.openRouter.errors.generic": "Váratlan OpenRouter hiba történt", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ingyenes)", + "settings.openRouter.freeModel.fallbackNotice": "A statikus tartalék lista jelenik meg — az élő OpenRouter katalógus jelenleg nem érhető el.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ingyenes)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ingyenes)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ingyenes)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Nem sikerült betölteni a modellkatalógust", "settings.openRouter.modelFetch.loading": "Modellkatalógus betöltése…", "settings.openRouter.modelPlaceholder": "Válasszon vagy keressen egy modellt", + "settings.openRouter.modelUnavailable": "Ez a modell nincs a jelenlegi katalógusban.", "settings.openRouter.paidModelNote": "A fizetős modellekhez jóváírásra van szükség az OpenRouter-fiókjában.", "settings.openRouter.policyBlocked.localOnly": "Az OpenRouter le van tiltva, mert a „Csak helyi tárhely” be van kapcsolva. A felhő AI engedélyezéséhez kapcsolja ki az Adatvédelem és adatok részben.", "settings.openRouter.policyBlocked.mode": "Az OpenRouter nem érhető el, ha az AI mód Helyi vagy Eco. A használatához váltson hibridre vagy felhőre az AI és modellekben.", "settings.openRouter.preferredModel": "Preferált modell", - "settings.openRouter.resetCircuit": "Reset", + "settings.openRouter.refreshModels": "Modellek frissítése", + "settings.openRouter.refreshModelsAriaLabel": "Az OpenRouter modellkatalógus frissítése", + "settings.openRouter.resetCircuit": "Visszaállítás", "settings.openRouter.resetCircuitAria": "Állítsa vissza az OpenRouter megszakítót", "settings.openRouter.rpmLabel": "Kérések / perc (legutóbbi 60 mp)", "settings.openRouter.saveKey": "Mentés", + "settings.openRouter.switchToAvailableModel": "Váltás egy elérhető ingyenes modellre", "settings.openRouter.testConnection": "Kapcsolat tesztelése", "settings.openRouter.testConnectionFailed": "A csatlakozás sikertelen", "settings.openRouter.testConnectionOk": "Sikeres csatlakozás", diff --git a/public/locales/is/bundle.json b/public/locales/is/bundle.json index feec2bc7d..d94ffd56f 100644 --- a/public/locales/is/bundle.json +++ b/public/locales/is/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 - Skapandi", "settings.ai.temperature.precise": "0 - Nákvæmt", "settings.ai.testConnection": "Prófaðu tengingu", - "settings.ai.testError.noApiKey": "Enginn {{provider}} API lykill stilltur", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tengingin féll á tíma ({{url}})", - "settings.ai.testError.unreachable": "Næst ekki ({{url}})", - "settings.ai.testError.pluginUnavailable": "Staðbundið netþjónasamband ekki tiltækt: ekki tókst að hlaða HTTP-viðbót skjáborðs.", - "settings.ai.testError.desktopRequired": "Ollama og staðbundnir OpenAI-samhæfir netþjónar eru aðeins tiltækir í skjáborðsforritinu. Vafrar loka fyrir bein tengsl frá vefsíðum við localhost (CORS og Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude þarfnast bakenda-milliþjóns (CORS-takmörkun)", + "settings.ai.testError.desktopRequired": "Ollama og staðbundnir OpenAI-samhæfir netþjónar eru aðeins tiltækir í skjáborðsforritinu. Vafrar loka fyrir bein tengsl frá vefsíðum við localhost (CORS og Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Enginn {{provider}} API lykill stilltur", "settings.ai.testError.noWebgpu": "WebGPU er ekki tiltækt í þessum vafra — WebLLM þarfnast WebGPU (prófaðu Chrome/Edge eða virkjaðu flögg).", - "settings.ai.testError.unknownProvider": "Óþekktur veitandi", + "settings.ai.testError.pluginUnavailable": "Staðbundið netþjónasamband ekki tiltækt: ekki tókst að hlaða HTTP-viðbót skjáborðs.", + "settings.ai.testError.timeout": "Tengingin féll á tíma ({{url}})", "settings.ai.testError.unexpected": "Óvænt villa kom upp. Reyndu aftur.", + "settings.ai.testError.unknownProvider": "Óþekktur veitandi", + "settings.ai.testError.unreachable": "Næst ekki ({{url}})", "settings.ai.title": "AI stillingar", "settings.ai.transformers.hint": "Keyrir hvaða Xenova-samhæfða HuggingFace líkan sem er á staðnum í gegnum WebAssembly eða WebGPU.", "settings.ai.transformers.modelId": "Auðkenni fyrirmyndar (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Þegar það er virkt er OpenRouter valinn fyrir gervigreindarsímtöl í skýi nema virka stillingin banni ský.", "settings.openRouter.errors.generic": "Óvænt OpenRouter villa kom upp", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (ókeypis)", + "settings.openRouter.freeModel.fallbackNotice": "Sýnir kyrrstæðan varalista — beinn OpenRouter-listi er ekki tiltækur núna.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (ókeypis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (ókeypis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (ókeypis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Gat ekki hlaðið módelskrá", "settings.openRouter.modelFetch.loading": "Hleður líkanaskrá...", "settings.openRouter.modelPlaceholder": "Veldu eða leitaðu að gerð", + "settings.openRouter.modelUnavailable": "Þetta líkan er ekki í núverandi lista.", "settings.openRouter.paidModelNote": "Greiddar gerðir þurfa inneign á OpenRouter reikningnum þínum.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter er læst vegna þess að kveikt er á „Staðbundin geymsla“. Slökktu á því í Privacy & Data til að leyfa gervigreind í skýi.", "settings.openRouter.policyBlocked.mode": "OpenRouter er ekki tiltækur á meðan gervigreindarstillingin er Local eða Eco. Skiptu yfir í Hybrid eða Cloud í gervigreind og módel til að nota það.", "settings.openRouter.preferredModel": "Ákjósanleg gerð", + "settings.openRouter.refreshModels": "Uppfæra líkön", + "settings.openRouter.refreshModelsAriaLabel": "Uppfæra OpenRouter líkanalistann", "settings.openRouter.resetCircuit": "Endurstilla", "settings.openRouter.resetCircuitAria": "Endurstilla OpenRouter aflrofa", "settings.openRouter.rpmLabel": "Beiðnir / mín. (síðustu 60 s)", "settings.openRouter.saveKey": "Vista", + "settings.openRouter.switchToAvailableModel": "Skipta yfir í tiltækt ókeypis líkan", "settings.openRouter.testConnection": "Prófaðu tengingu", "settings.openRouter.testConnectionFailed": "Tenging mistókst", "settings.openRouter.testConnectionOk": "Tenging tókst", diff --git a/public/locales/it/bundle.json b/public/locales/it/bundle.json index 0f09d26e8..8e85bde59 100644 --- a/public/locales/it/bundle.json +++ b/public/locales/it/bundle.json @@ -877,7 +877,7 @@ "copilot.you": "Tu", "dashboard.authorInsights.readability": "Leggibilità (Gulpease, euristica IT)", "dashboard.authorInsights.readabilityFootnote": "Punteggi più alti sono spesso più facili da leggere; calibra sul genere.", - "dashboard.authorInsights.readabilityTooltip": "Scala di leggibilità Flesch 0–100: più alto = più facile da leggere (60–70 è linguaggio comune). È un indicatore approssimativo, non un voto normativo.", + "dashboard.authorInsights.readabilityTooltip": "Indice di leggibilità Gulpease 0–100: più alto = più facile da leggere (soglia ~60 per la scuola media, ~80 per la scuola elementare). È un indicatore approssimativo, non un voto normativo.", "dashboard.authorInsights.readabilityScaleSuffix": "/100", "dashboard.logline.updated": "Logline aggiornata", "dashboard.logline.updatedUndo": "Premi Ctrl+Z per annullare.", @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Creativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Testa la connessione", - "settings.ai.testError.noApiKey": "Nessuna chiave API {{provider}} impostata", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Connessione scaduta ({{url}})", - "settings.ai.testError.unreachable": "Non raggiungibile ({{url}})", - "settings.ai.testError.pluginUnavailable": "Rete dei server locali non disponibile: il plugin HTTP desktop non è stato caricato.", - "settings.ai.testError.desktopRequired": "Ollama e i server locali compatibili con OpenAI sono disponibili solo nell'app desktop. I browser bloccano le connessioni dirette dalle pagine web a localhost (CORS e Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude richiede un proxy backend (restrizione CORS)", + "settings.ai.testError.desktopRequired": "Ollama e i server locali compatibili con OpenAI sono disponibili solo nell'app desktop. I browser bloccano le connessioni dirette dalle pagine web a localhost (CORS e Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nessuna chiave API {{provider}} impostata", "settings.ai.testError.noWebgpu": "WebGPU non disponibile in questo browser — WebLLM richiede WebGPU (prova Chrome/Edge o abilita i flag).", - "settings.ai.testError.unknownProvider": "Provider sconosciuto", + "settings.ai.testError.pluginUnavailable": "Rete dei server locali non disponibile: il plugin HTTP desktop non è stato caricato.", + "settings.ai.testError.timeout": "Connessione scaduta ({{url}})", "settings.ai.testError.unexpected": "Si è verificato un errore imprevisto. Riprova.", + "settings.ai.testError.unknownProvider": "Provider sconosciuto", + "settings.ai.testError.unreachable": "Non raggiungibile ({{url}})", "settings.ai.title": "Configurazione IA", "settings.ai.transformers.hint": "Esegue qualsiasi modello HuggingFace compatibile con Xenova localmente via WebAssembly o WebGPU.", "settings.ai.transformers.modelId": "ID modello (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Se abilitato, OpenRouter è preferito per le chiamate IA cloud, a meno che la modalità attiva non vieti il cloud.", "settings.openRouter.errors.generic": "Si è verificato un errore imprevisto di OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Visualizzazione dell'elenco di riserva statico — il catalogo OpenRouter in tempo reale non è disponibile al momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Impossibile caricare il catalogo modelli", "settings.openRouter.modelFetch.loading": "Caricamento del catalogo modelli…", "settings.openRouter.modelPlaceholder": "Seleziona o cerca un modello", + "settings.openRouter.modelUnavailable": "Questo modello non è presente nel catalogo attuale.", "settings.openRouter.paidModelNote": "I modelli a pagamento richiedono crediti sul tuo account OpenRouter.", "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.refreshModels": "Aggiorna modelli", + "settings.openRouter.refreshModelsAriaLabel": "Aggiorna il catalogo dei modelli OpenRouter", "settings.openRouter.resetCircuit": "Reimposta", "settings.openRouter.resetCircuitAria": "Reimposta l'interruttore di OpenRouter", "settings.openRouter.rpmLabel": "Richieste / min (ultimi 60 s)", "settings.openRouter.saveKey": "Salva", + "settings.openRouter.switchToAvailableModel": "Passa a un modello gratuito disponibile", "settings.openRouter.testConnection": "Prova connessione", "settings.openRouter.testConnectionFailed": "Connessione non riuscita", "settings.openRouter.testConnectionOk": "Connessione riuscita", diff --git a/public/locales/ja/bundle.json b/public/locales/ja/bundle.json index 8f3344b74..2d8ba81f9 100644 --- a/public/locales/ja/bundle.json +++ b/public/locales/ja/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – クリエイティブ", "settings.ai.temperature.precise": "0 – 正確", "settings.ai.testConnection": "テスト接続", - "settings.ai.testError.noApiKey": "{{provider}} の API キーが設定されていません", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "接続がタイムアウトしました ({{url}})", - "settings.ai.testError.unreachable": "到達できません ({{url}})", - "settings.ai.testError.pluginUnavailable": "ローカルサーバーへの接続が利用できません: デスクトップ HTTP プラグインの読み込みに失敗しました。", - "settings.ai.testError.desktopRequired": "Ollama およびローカルの OpenAI 互換サーバーはデスクトップアプリでのみ利用できます。ブラウザは Web ページから localhost への直接接続をブロックします(CORS および Private Network Access)。", "settings.ai.testError.backendProxyRequired": "Claude にはバックエンドプロキシが必要です(CORS 制限)", + "settings.ai.testError.desktopRequired": "Ollama およびローカルの OpenAI 互換サーバーはデスクトップアプリでのみ利用できます。ブラウザは Web ページから localhost への直接接続をブロックします(CORS および Private Network Access)。", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}} の API キーが設定されていません", "settings.ai.testError.noWebgpu": "このブラウザでは WebGPU が利用できません — WebLLM には WebGPU が必要です(Chrome/Edge を試すかフラグを有効にしてください)。", - "settings.ai.testError.unknownProvider": "不明なプロバイダー", + "settings.ai.testError.pluginUnavailable": "ローカルサーバーへの接続が利用できません: デスクトップ HTTP プラグインの読み込みに失敗しました。", + "settings.ai.testError.timeout": "接続がタイムアウトしました ({{url}})", "settings.ai.testError.unexpected": "予期しないエラーが発生しました。もう一度お試しください。", + "settings.ai.testError.unknownProvider": "不明なプロバイダー", + "settings.ai.testError.unreachable": "到達できません ({{url}})", "settings.ai.title": "AIの構成", "settings.ai.transformers.hint": "WebAssembly または WebGPU を介して Xenova 互換の HuggingFace モデルをローカルで実行します。", "settings.ai.transformers.modelId": "モデルID (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "有効にすると、アクティブなモードがクラウドを禁止しない限り、クラウドAI呼び出しにOpenRouterが優先されます。", "settings.openRouter.errors.generic": "予期しないOpenRouterエラーが発生しました", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (無料)", + "settings.openRouter.freeModel.fallbackNotice": "静的なフォールバックリストを表示しています — OpenRouterのライブカタログは現在利用できません。", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (無料)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (無料)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (無料)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "モデルカタログを読み込めませんでした", "settings.openRouter.modelFetch.loading": "モデルカタログを読み込み中…", "settings.openRouter.modelPlaceholder": "モデルを選択または検索", + "settings.openRouter.modelUnavailable": "このモデルは現在のカタログにありません。", "settings.openRouter.paidModelNote": "有料モデルにはOpenRouterアカウントのクレジットが必要です。", "settings.openRouter.policyBlocked.localOnly": "「ローカルストレージのみ」がオンのため OpenRouter はブロックされています。クラウド AI を許可するには「プライバシーとデータ」でオフにしてください。", "settings.openRouter.policyBlocked.mode": "AIモードが「ローカル」または「エコ」の間は OpenRouter を利用できません。利用するには「AI とモデル」で「ハイブリッド」または「クラウド」に切り替えてください。", "settings.openRouter.preferredModel": "優先モデル", + "settings.openRouter.refreshModels": "モデルを更新", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouterモデルカタログを更新", "settings.openRouter.resetCircuit": "リセット", "settings.openRouter.resetCircuitAria": "OpenRouterサーキットブレーカーをリセット", "settings.openRouter.rpmLabel": "リクエスト/分(直近60秒)", "settings.openRouter.saveKey": "保存", + "settings.openRouter.switchToAvailableModel": "利用可能な無料モデルに切り替える", "settings.openRouter.testConnection": "接続をテスト", "settings.openRouter.testConnectionFailed": "接続に失敗しました", "settings.openRouter.testConnectionOk": "接続に成功しました", diff --git a/public/locales/ko/bundle.json b/public/locales/ko/bundle.json index 85a815292..3bd4499fb 100644 --- a/public/locales/ko/bundle.json +++ b/public/locales/ko/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – 창의적", "settings.ai.temperature.precise": "0 – 정확함", "settings.ai.testConnection": "연결 테스트", - "settings.ai.testError.noApiKey": "{{provider}} API 키가 설정되지 않았습니다", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "연결 시간이 초과되었습니다 ({{url}})", - "settings.ai.testError.unreachable": "연결할 수 없습니다 ({{url}})", - "settings.ai.testError.pluginUnavailable": "로컬 서버 네트워킹을 사용할 수 없습니다: 데스크톱 HTTP 플러그인을 불러오지 못했습니다.", - "settings.ai.testError.desktopRequired": "Ollama 및 로컬 OpenAI 호환 서버는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저는 웹 페이지에서 localhost로의 직접 연결을 차단합니다(CORS 및 Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude에는 백엔드 프록시가 필요합니다(CORS 제한)", + "settings.ai.testError.desktopRequired": "Ollama 및 로컬 OpenAI 호환 서버는 데스크톱 앱에서만 사용할 수 있습니다. 브라우저는 웹 페이지에서 localhost로의 직접 연결을 차단합니다(CORS 및 Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "{{provider}} API 키가 설정되지 않았습니다", "settings.ai.testError.noWebgpu": "이 브라우저에서는 WebGPU를 사용할 수 없습니다 — WebLLM에는 WebGPU가 필요합니다(Chrome/Edge를 사용하거나 플래그를 활성화하세요).", - "settings.ai.testError.unknownProvider": "알 수 없는 제공자", + "settings.ai.testError.pluginUnavailable": "로컬 서버 네트워킹을 사용할 수 없습니다: 데스크톱 HTTP 플러그인을 불러오지 못했습니다.", + "settings.ai.testError.timeout": "연결 시간이 초과되었습니다 ({{url}})", "settings.ai.testError.unexpected": "예기치 않은 오류가 발생했습니다. 다시 시도해 주세요.", + "settings.ai.testError.unknownProvider": "알 수 없는 제공자", + "settings.ai.testError.unreachable": "연결할 수 없습니다 ({{url}})", "settings.ai.title": "AI 구성", "settings.ai.transformers.hint": "WebAssembly 또는 WebGPU를 통해 Xenova 호환 HuggingFace 모델을 로컬로 실행합니다.", "settings.ai.transformers.modelId": "모델 ID(HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "활성화되면 활성 모드가 클라우드를 금지하지 않는 한 클라우드 AI 호출에 OpenRouter가 선호됩니다.", "settings.openRouter.errors.generic": "예상치 못한 OpenRouter 오류가 발생했습니다.", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (무료)", + "settings.openRouter.freeModel.fallbackNotice": "정적 대체 목록을 표시하고 있습니다 — 실시간 OpenRouter 카탈로그를 현재 사용할 수 없습니다.", "settings.openRouter.freeModel.gemma327b": "젬마 3 27B IT(무료)", "settings.openRouter.freeModel.llama3370b": "라마 3.3 70B 교육(무료)", "settings.openRouter.freeModel.mistral7b": "미스트랄 7B 교육(무료)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "모델 카탈로그를 로드할 수 없습니다.", "settings.openRouter.modelFetch.loading": "모델 카탈로그 로드 중…", "settings.openRouter.modelPlaceholder": "모델 선택 또는 검색", + "settings.openRouter.modelUnavailable": "이 모델은 현재 카탈로그에 없습니다.", "settings.openRouter.paidModelNote": "유료 모델을 사용하려면 OpenRouter 계정에 크레딧이 필요합니다.", "settings.openRouter.policyBlocked.localOnly": "\"로컬 저장소만\"이 켜져 있으므로 OpenRouter가 차단되었습니다. 클라우드 AI를 허용하려면 개인 정보 보호 및 데이터에서 이 기능을 끄세요.", "settings.openRouter.policyBlocked.mode": "AI 모드가 Local 또는 Eco인 동안에는 OpenRouter를 사용할 수 없습니다. AI 및 모델에서 하이브리드 또는 클라우드로 전환하여 사용하세요.", "settings.openRouter.preferredModel": "선호하는 모델", + "settings.openRouter.refreshModels": "모델 새로고침", + "settings.openRouter.refreshModelsAriaLabel": "OpenRouter 모델 카탈로그 새로고침", "settings.openRouter.resetCircuit": "다시 놓기", "settings.openRouter.resetCircuitAria": "OpenRouter 회로 차단기 재설정", "settings.openRouter.rpmLabel": "요청/분(지난 60초)", "settings.openRouter.saveKey": "저장", + "settings.openRouter.switchToAvailableModel": "사용 가능한 무료 모델로 전환", "settings.openRouter.testConnection": "연결 테스트", "settings.openRouter.testConnectionFailed": "연결 실패", "settings.openRouter.testConnectionOk": "연결 성공", diff --git a/public/locales/pt/bundle.json b/public/locales/pt/bundle.json index fa1ef1776..ffff2afdc 100644 --- a/public/locales/pt/bundle.json +++ b/public/locales/pt/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Criativo", "settings.ai.temperature.precise": "0 – Preciso", "settings.ai.testConnection": "Conexão de teste", - "settings.ai.testError.noApiKey": "Nenhuma chave de API {{provider}} definida", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Tempo limite de conexão excedido ({{url}})", - "settings.ai.testError.unreachable": "Inacessível ({{url}})", - "settings.ai.testError.pluginUnavailable": "A rede do servidor local não está disponível: o plugin HTTP de ambiente de trabalho falhou ao carregar.", - "settings.ai.testError.desktopRequired": "O Ollama e os servidores locais compatíveis com OpenAI só estão disponíveis na aplicação de ambiente de trabalho. Os navegadores bloqueiam ligações diretas de páginas web ao localhost (CORS e Private Network Access).", "settings.ai.testError.backendProxyRequired": "O Claude requer um proxy de backend (restrição CORS)", + "settings.ai.testError.desktopRequired": "O Ollama e os servidores locais compatíveis com OpenAI só estão disponíveis na aplicação de ambiente de trabalho. Os navegadores bloqueiam ligações diretas de páginas web ao localhost (CORS e Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Nenhuma chave de API {{provider}} definida", "settings.ai.testError.noWebgpu": "WebGPU indisponível neste navegador — o WebLLM necessita de WebGPU (experimente o Chrome/Edge ou ative as flags).", - "settings.ai.testError.unknownProvider": "Fornecedor desconhecido", + "settings.ai.testError.pluginUnavailable": "A rede do servidor local não está disponível: o plugin HTTP de ambiente de trabalho falhou ao carregar.", + "settings.ai.testError.timeout": "Tempo limite de conexão excedido ({{url}})", "settings.ai.testError.unexpected": "Ocorreu um erro inesperado. Tente novamente.", + "settings.ai.testError.unknownProvider": "Fornecedor desconhecido", + "settings.ai.testError.unreachable": "Inacessível ({{url}})", "settings.ai.title": "IA Configuration", "settings.ai.transformers.hint": "Executa qualquer modelo HuggingFace compatível com Xenova localmente via WebAssembly ou WebGPU.", "settings.ai.transformers.modelId": "ID do modelo (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Quando ativado, o OpenRouter é preferido para chamadas de IA na cloud, exceto se o modo ativo proibir a cloud.", "settings.openRouter.errors.generic": "Ocorreu um erro inesperado do OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (grátis)", + "settings.openRouter.freeModel.fallbackNotice": "A mostrar a lista de reserva estática — o catálogo em direto do OpenRouter não está disponível de momento.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (grátis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (grátis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (grátis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Não foi possível carregar o catálogo de modelos", "settings.openRouter.modelFetch.loading": "A carregar o catálogo de modelos…", "settings.openRouter.modelPlaceholder": "Seleciona ou procura um modelo", + "settings.openRouter.modelUnavailable": "Este modelo não está no catálogo atual.", "settings.openRouter.paidModelNote": "Os modelos pagos requerem créditos na tua conta OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "O OpenRouter está bloqueado porque “Apenas armazenamento local” está ativado. Desative-o em Privacidade e Dados para permitir a IA na nuvem.", "settings.openRouter.policyBlocked.mode": "O OpenRouter não está disponível enquanto o modo de IA for Local ou Eco. Mude para Híbrido ou Nuvem em IA e Modelos para o utilizar.", "settings.openRouter.preferredModel": "Modelo preferido", + "settings.openRouter.refreshModels": "Atualizar modelos", + "settings.openRouter.refreshModelsAriaLabel": "Atualizar o catálogo de modelos OpenRouter", "settings.openRouter.resetCircuit": "Repor", "settings.openRouter.resetCircuitAria": "Repor o disjuntor do OpenRouter", "settings.openRouter.rpmLabel": "Pedidos / min (últimos 60 s)", "settings.openRouter.saveKey": "Guardar", + "settings.openRouter.switchToAvailableModel": "Mudar para um modelo gratuito disponível", "settings.openRouter.testConnection": "Testar ligação", "settings.openRouter.testConnectionFailed": "Falha na ligação", "settings.openRouter.testConnectionOk": "Ligação bem-sucedida", diff --git a/public/locales/ru/bundle.json b/public/locales/ru/bundle.json index f4ffe6144..3a1a32ff0 100644 --- a/public/locales/ru/bundle.json +++ b/public/locales/ru/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Креатив", "settings.ai.temperature.precise": "0 – Точный", "settings.ai.testConnection": "Тестовое соединение", - "settings.ai.testError.noApiKey": "Не задан ключ API {{provider}}", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Тайм-аут соединения ({{url}})", - "settings.ai.testError.unreachable": "Недоступно ({{url}})", - "settings.ai.testError.pluginUnavailable": "Сеть локального сервера недоступна: не удалось загрузить настольный HTTP-плагин.", - "settings.ai.testError.desktopRequired": "Ollama и локальные серверы, совместимые с OpenAI, доступны только в настольном приложении. Браузеры блокируют прямые подключения с веб-страниц к localhost (CORS и Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude требует backend-прокси (ограничение CORS)", + "settings.ai.testError.desktopRequired": "Ollama и локальные серверы, совместимые с OpenAI, доступны только в настольном приложении. Браузеры блокируют прямые подключения с веб-страниц к localhost (CORS и Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Не задан ключ API {{provider}}", "settings.ai.testError.noWebgpu": "WebGPU недоступен в этом браузере — WebLLM требует WebGPU (попробуйте Chrome/Edge или включите флаги).", - "settings.ai.testError.unknownProvider": "Неизвестный провайдер", + "settings.ai.testError.pluginUnavailable": "Сеть локального сервера недоступна: не удалось загрузить настольный HTTP-плагин.", + "settings.ai.testError.timeout": "Тайм-аут соединения ({{url}})", "settings.ai.testError.unexpected": "Произошла непредвиденная ошибка. Повторите попытку.", + "settings.ai.testError.unknownProvider": "Неизвестный провайдер", + "settings.ai.testError.unreachable": "Недоступно ({{url}})", "settings.ai.title": "Конфигурация ИИ", "settings.ai.transformers.hint": "Запускает любую Xenova-совместимую модель HuggingFace локально через WebAssembly или WebGPU.", "settings.ai.transformers.modelId": "Идентификатор модели (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "Если этот параметр включен, OpenRouter предпочтителен для вызовов облачного ИИ, если только активный режим не запрещает облако.", "settings.openRouter.errors.generic": "Произошла непредвиденная ошибка OpenRouter", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (бесплатно)", + "settings.openRouter.freeModel.fallbackNotice": "Отображается статический резервный список — прямой каталог OpenRouter сейчас недоступен.", "settings.openRouter.freeModel.gemma327b": "Джемма 3 27Б ИТ (бесплатно)", "settings.openRouter.freeModel.llama3370b": "Лама 3.3 70Б Инструкция (бесплатно)", "settings.openRouter.freeModel.mistral7b": "Мистраль 7Б Инструкт (бесплатно)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Не удалось загрузить каталог моделей.", "settings.openRouter.modelFetch.loading": "Загрузка каталога моделей…", "settings.openRouter.modelPlaceholder": "Выберите или найдите модель", + "settings.openRouter.modelUnavailable": "Эта модель отсутствует в текущем каталоге.", "settings.openRouter.paidModelNote": "Платные модели требуют кредитов на вашей учетной записи OpenRouter.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter заблокирован, поскольку включено «Только локальное хранилище». Отключите его в разделе «Конфиденциальность и данные», чтобы разрешить облачный искусственный интеллект.", "settings.openRouter.policyBlocked.mode": "OpenRouter недоступен, если режим AI локальный или эко. Чтобы использовать его, переключитесь на гибридный или облачный режим в разделе «ИИ и модели».", "settings.openRouter.preferredModel": "Предпочтительная модель", + "settings.openRouter.refreshModels": "Обновить модели", + "settings.openRouter.refreshModelsAriaLabel": "Обновить каталог моделей OpenRouter", "settings.openRouter.resetCircuit": "Перезагрузить", "settings.openRouter.resetCircuitAria": "Сброс автоматического выключателя OpenRouter", "settings.openRouter.rpmLabel": "Запросов/мин (последние 60 с)", "settings.openRouter.saveKey": "Сохранить", + "settings.openRouter.switchToAvailableModel": "Переключиться на доступную бесплатную модель", "settings.openRouter.testConnection": "Тестовое соединение", "settings.openRouter.testConnectionFailed": "Соединение не удалось", "settings.openRouter.testConnectionOk": "Соединение успешно", diff --git a/public/locales/sv/bundle.json b/public/locales/sv/bundle.json index 38d3ec0e5..bf4e2b066 100644 --- a/public/locales/sv/bundle.json +++ b/public/locales/sv/bundle.json @@ -463,7 +463,7 @@ "proforge.progress.metric.totalTime": "Total tid", "proforge.progress.metric.totalTokens": "Totala tokens", "proforge.progress.noneRunning": "Ingen pipeline igång.", - "proforge.progress.stageDetails": "Scendetaljer: {{stage}}", + "proforge.progress.stageDetails": "Stegdetaljer: {{stage}}", "proforge.progress.statusLabel": "Status", "proforge.progress.totals": "Rörledningssummor", "proforge.review.accept": "Acceptera", @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – Kreativt", "settings.ai.temperature.precise": "0 – Exakt", "settings.ai.testConnection": "Testa anslutningen", - "settings.ai.testError.noApiKey": "Ingen {{provider}}-API-nyckel angiven", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "Anslutningen fick timeout ({{url}})", - "settings.ai.testError.unreachable": "Ej nåbar ({{url}})", - "settings.ai.testError.pluginUnavailable": "Lokal servernätverksanslutning ej tillgänglig: skrivbordets HTTP-plugin misslyckades med att läsas in.", - "settings.ai.testError.desktopRequired": "Ollama och lokala OpenAI-kompatibla servrar är endast tillgängliga i skrivbordsappen. Webbläsare blockerar direkta anslutningar från webbsidor till localhost (CORS och Private Network Access).", "settings.ai.testError.backendProxyRequired": "Claude kräver en backend-proxy (CORS-begränsning)", + "settings.ai.testError.desktopRequired": "Ollama och lokala OpenAI-kompatibla servrar är endast tillgängliga i skrivbordsappen. Webbläsare blockerar direkta anslutningar från webbsidor till localhost (CORS och Private Network Access).", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "Ingen {{provider}}-API-nyckel angiven", "settings.ai.testError.noWebgpu": "WebGPU är inte tillgängligt i den här webbläsaren — WebLLM behöver WebGPU (prova Chrome/Edge eller aktivera flaggor).", - "settings.ai.testError.unknownProvider": "Okänd leverantör", + "settings.ai.testError.pluginUnavailable": "Lokal servernätverksanslutning ej tillgänglig: skrivbordets HTTP-plugin misslyckades med att läsas in.", + "settings.ai.testError.timeout": "Anslutningen fick timeout ({{url}})", "settings.ai.testError.unexpected": "Ett oväntat fel inträffade. Försök igen.", + "settings.ai.testError.unknownProvider": "Okänd leverantör", + "settings.ai.testError.unreachable": "Ej nåbar ({{url}})", "settings.ai.title": "AI-konfiguration", "settings.ai.transformers.hint": "Kör valfri Xenova-kompatibel HuggingFace-modell lokalt via WebAssembly eller WebGPU.", "settings.ai.transformers.modelId": "Modell-ID (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "När den är aktiverad är OpenRouter att föredra för moln AI-samtal om inte det aktiva läget förbjuder moln.", "settings.openRouter.errors.generic": "Ett oväntat OpenRouter-fel inträffade", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (gratis)", + "settings.openRouter.freeModel.fallbackNotice": "Visar den statiska reservlistan — OpenRouters direktkatalog är inte tillgänglig just nu.", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (gratis)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (gratis)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (gratis)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "Det gick inte att ladda modellkatalogen", "settings.openRouter.modelFetch.loading": "Laddar modellkatalog...", "settings.openRouter.modelPlaceholder": "Välj eller sök efter en modell", + "settings.openRouter.modelUnavailable": "Den här modellen finns inte i den aktuella katalogen.", "settings.openRouter.paidModelNote": "Betalmodeller kräver krediter på ditt OpenRouter-konto.", "settings.openRouter.policyBlocked.localOnly": "OpenRouter är blockerad eftersom \"Endast lokal lagring\" är på. Stäng av den i Sekretess och data för att tillåta moln-AI.", "settings.openRouter.policyBlocked.mode": "OpenRouter är inte tillgängligt när AI-läget är lokalt eller eko. Byt till Hybrid eller Cloud i AI och modeller för att använda det.", "settings.openRouter.preferredModel": "Föredragen modell", + "settings.openRouter.refreshModels": "Uppdatera modeller", + "settings.openRouter.refreshModelsAriaLabel": "Uppdatera OpenRouter-modellkatalogen", "settings.openRouter.resetCircuit": "Återställa", "settings.openRouter.resetCircuitAria": "Återställ OpenRouter-strömbrytaren", "settings.openRouter.rpmLabel": "Förfrågningar/min (senaste 60 s)", "settings.openRouter.saveKey": "Spara", + "settings.openRouter.switchToAvailableModel": "Byt till en tillgänglig gratismodell", "settings.openRouter.testConnection": "Testa anslutningen", "settings.openRouter.testConnectionFailed": "Anslutning misslyckades", "settings.openRouter.testConnectionOk": "Anslutningen lyckades", diff --git a/public/locales/zh/bundle.json b/public/locales/zh/bundle.json index b66a09cef..e0e54f7a9 100644 --- a/public/locales/zh/bundle.json +++ b/public/locales/zh/bundle.json @@ -1856,16 +1856,16 @@ "settings.ai.temperature.creative": "2 – 创意", "settings.ai.temperature.precise": "0 – 精确", "settings.ai.testConnection": "测试连接", - "settings.ai.testError.noApiKey": "未设置 {{provider}} API 密钥", - "settings.ai.testError.httpError": "HTTP {{status}}", - "settings.ai.testError.timeout": "连接超时 ({{url}})", - "settings.ai.testError.unreachable": "无法访问 ({{url}})", - "settings.ai.testError.pluginUnavailable": "本地服务器网络不可用:桌面 HTTP 插件加载失败。", - "settings.ai.testError.desktopRequired": "Ollama 和本地 OpenAI 兼容服务器仅在桌面应用中可用。浏览器会阻止网页直接连接到 localhost(CORS 和 Private Network Access)。", "settings.ai.testError.backendProxyRequired": "Claude 需要后端代理(CORS 限制)", + "settings.ai.testError.desktopRequired": "Ollama 和本地 OpenAI 兼容服务器仅在桌面应用中可用。浏览器会阻止网页直接连接到 localhost(CORS 和 Private Network Access)。", + "settings.ai.testError.httpError": "HTTP {{status}}", + "settings.ai.testError.noApiKey": "未设置 {{provider}} API 密钥", "settings.ai.testError.noWebgpu": "此浏览器不支持 WebGPU — WebLLM 需要 WebGPU(请尝试 Chrome/Edge 或启用相关标志)。", - "settings.ai.testError.unknownProvider": "未知的提供商", + "settings.ai.testError.pluginUnavailable": "本地服务器网络不可用:桌面 HTTP 插件加载失败。", + "settings.ai.testError.timeout": "连接超时 ({{url}})", "settings.ai.testError.unexpected": "发生意外错误。请重试。", + "settings.ai.testError.unknownProvider": "未知的提供商", + "settings.ai.testError.unreachable": "无法访问 ({{url}})", "settings.ai.title": "人工智能配置", "settings.ai.transformers.hint": "通过 WebAssembly 或 WebGPU 在本地运行任何 Xenova 兼容的 HuggingFace 模型。", "settings.ai.transformers.modelId": "型号 ID (HuggingFace)", @@ -2207,6 +2207,7 @@ "settings.openRouter.enabledHint": "启用后,除非当前模式禁止云端,否则云端 AI 调用将优先使用 OpenRouter。", "settings.openRouter.errors.generic": "发生了意外的 OpenRouter 错误", "settings.openRouter.freeModel.deepseekR1": "DeepSeek R1 (免费)", + "settings.openRouter.freeModel.fallbackNotice": "正在显示静态后备列表 — 实时 OpenRouter 目录目前不可用。", "settings.openRouter.freeModel.gemma327b": "Gemma 3 27B IT (免费)", "settings.openRouter.freeModel.llama3370b": "Llama 3.3 70B Instruct (免费)", "settings.openRouter.freeModel.mistral7b": "Mistral 7B Instruct (免费)", @@ -2229,14 +2230,18 @@ "settings.openRouter.modelFetch.failed": "无法加载模型目录", "settings.openRouter.modelFetch.loading": "正在加载模型目录…", "settings.openRouter.modelPlaceholder": "选择或搜索模型", + "settings.openRouter.modelUnavailable": "该模型不在当前目录中。", "settings.openRouter.paidModelNote": "付费模型需要你的 OpenRouter 账户额度。", "settings.openRouter.policyBlocked.localOnly": "由于「仅本地存储」已开启,OpenRouter 被阻止。请在「隐私与数据」中将其关闭以允许云端 AI。", "settings.openRouter.policyBlocked.mode": "当 AI 模式为「本地」或「Eco」时,OpenRouter 不可用。请在「AI 与模型」中切换为「混合」或「云端」以使用它。", "settings.openRouter.preferredModel": "首选模型", + "settings.openRouter.refreshModels": "刷新模型", + "settings.openRouter.refreshModelsAriaLabel": "刷新 OpenRouter 模型目录", "settings.openRouter.resetCircuit": "重置", "settings.openRouter.resetCircuitAria": "重置 OpenRouter 断路器", "settings.openRouter.rpmLabel": "请求 / 分钟(最近 60 秒)", "settings.openRouter.saveKey": "保存", + "settings.openRouter.switchToAvailableModel": "切换到可用的免费模型", "settings.openRouter.testConnection": "测试连接", "settings.openRouter.testConnectionFailed": "连接失败", "settings.openRouter.testConnectionOk": "连接成功", diff --git a/services/ai/index.ts b/services/ai/index.ts index a30d38989..4fdc6a3ab 100644 --- a/services/ai/index.ts +++ b/services/ai/index.ts @@ -107,7 +107,7 @@ export { export { getApproxRpm, isCircuitOpen, - OPENROUTER_FREE_MODELS, + OPENROUTER_FREE_MODEL_FALLBACK, type OpenRouterFreeModel, resetOpenRouterCircuit, } from './providers/openrouterProvider'; diff --git a/services/ai/openrouterModels.ts b/services/ai/openrouterModels.ts index 0e95bedc4..660550eb7 100644 --- a/services/ai/openrouterModels.ts +++ b/services/ai/openrouterModels.ts @@ -38,7 +38,7 @@ interface CacheEntry { // QNBS-v3: Whether this catalog was fetched with an API key. Buckets the cache by credential // scope (anonymous vs. authenticated) so an anonymous catalog is never served to an authenticated // request, and vice-versa. A plain boolean — NO key-derived material is ever written to storage. - authed?: boolean; + authed?: boolean | undefined; } function isBrowser(): boolean { @@ -73,7 +73,7 @@ function readCache(expectedAuthed: boolean): CacheEntry | null { const normalized = (parsed.models as unknown[]) .map(normalizeModel) .filter((m): m is OpenRouterModel => m !== null); - return { fetchedAt: parsed.fetchedAt, models: normalized }; + return { fetchedAt: parsed.fetchedAt, models: normalized, authed: parsed.authed }; } catch { return null; } @@ -221,3 +221,14 @@ export function clearOpenRouterModelCache(): void { export function isOpenRouterFreeModel(modelId: string): boolean { return modelId.endsWith(':free'); } + +/** + * Test-only accessor for the private readCache(). `authed` isn't read by any current caller of + * fetchOpenRouterModels() (only `.models` is used), so the OR-6 fix — readCache() returning the + * full CacheEntry instead of silently dropping `authed` — has no behavior observable through the + * public API. Exposed here (matching the __*ForTest convention in providers/openrouterProvider.ts) + * so the round-trip can still be asserted directly. + */ +export function __readCacheForTest(expectedAuthed: boolean): CacheEntry | null { + return readCache(expectedAuthed); +} diff --git a/services/ai/providers/openrouterProvider.ts b/services/ai/providers/openrouterProvider.ts index 0195af5fd..a685ecfe1 100644 --- a/services/ai/providers/openrouterProvider.ts +++ b/services/ai/providers/openrouterProvider.ts @@ -29,11 +29,16 @@ const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1'; const SITE_URL = 'https://github.com/qnbs/WorldScript-Studio'; const SITE_TITLE = 'WorldScript Studio'; -// ─── Free-tier model catalog ───────────────────────────────────────────────── - -// QNBS-v3: Strong free-tier models with `:free` suffix. Fallback order matters: -// DeepSeek R1 is best for reasoning; Llama 70B is best for creative writing. -export const OPENROUTER_FREE_MODELS = [ +// ─── Free-tier model fallback ──────────────────────────────────────────────── + +// QNBS-v3: Offline/fetch-failure FALLBACK ONLY — never a primary source. The Settings UI derives +// the free-tier group from the live-fetched catalog (services/ai/openrouterModels.ts) and only +// falls back to this frozen list when that fetch fails or returns no free models. OpenRouter's +// free tier rotates weekly; a hardcoded list used as the primary source silently drops new free +// models from the UI, which is the bug this fallback role (renamed from a former primary-source +// role) exists to avoid repeating. Fallback order matters: DeepSeek R1 is best for reasoning; +// Llama 70B is best for creative writing. +export const OPENROUTER_FREE_MODEL_FALLBACK = [ 'deepseek/deepseek-r1:free', 'meta-llama/llama-3.3-70b-instruct:free', 'qwen/qwen2.5-72b-instruct:free', @@ -41,7 +46,7 @@ export const OPENROUTER_FREE_MODELS = [ 'mistralai/mistral-7b-instruct:free', ] as const; -export type OpenRouterFreeModel = (typeof OPENROUTER_FREE_MODELS)[number]; +export type OpenRouterFreeModel = (typeof OPENROUTER_FREE_MODEL_FALLBACK)[number]; export { isOpenRouterFreeModel }; diff --git a/tests/unit/ai/openrouterModels.test.ts b/tests/unit/ai/openrouterModels.test.ts index 23440d92d..becd812d7 100644 --- a/tests/unit/ai/openrouterModels.test.ts +++ b/tests/unit/ai/openrouterModels.test.ts @@ -5,6 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { + __readCacheForTest, clearOpenRouterModelCache, fetchOpenRouterModels, validateOpenRouterKey, @@ -102,6 +103,19 @@ describe('openrouterModels', () => { expect(models).toEqual([{ id: 'authed/model' }]); }); + it('preserves the authed flag across a cache round-trip (OR-6 regression)', () => { + // QNBS-v3: readCache() previously returned { fetchedAt, models } only, silently dropping + // `authed` from the typed CacheEntry even though the credential-scope check above already + // depends on it being present on the STORED entry. This asserts the RETURNED entry also + // carries it, honoring the full CacheEntry type. + localStorage.setItem( + CACHE_KEY, + JSON.stringify({ fetchedAt: FIXED_NOW, authed: true, models: [{ id: 'x/y:free' }] }), + ); + const entry = __readCacheForTest(true); + expect(entry?.authed).toBe(true); + }); + it('ignores stale cached entries', async () => { localStorage.setItem( CACHE_KEY, diff --git a/tests/unit/ai/openrouterProvider.test.ts b/tests/unit/ai/openrouterProvider.test.ts index 3699c2a7f..731b9ccf6 100644 --- a/tests/unit/ai/openrouterProvider.test.ts +++ b/tests/unit/ai/openrouterProvider.test.ts @@ -12,7 +12,7 @@ import { getApproxRpm, isCircuitOpen, isOpenRouterFreeModel, - OPENROUTER_FREE_MODELS, + OPENROUTER_FREE_MODEL_FALLBACK, resetOpenRouterCircuit, streamOpenRouter, } from '../../../services/ai/providers/openrouterProvider'; @@ -78,11 +78,15 @@ describe('isOpenRouterFreeModel()', () => { expect(isOpenRouterFreeModel('openai/gpt-4o')).toBe(false); }); - it('all OPENROUTER_FREE_MODELS entries are free models', () => { - for (const model of OPENROUTER_FREE_MODELS) { + it('all OPENROUTER_FREE_MODEL_FALLBACK entries are free models', () => { + for (const model of OPENROUTER_FREE_MODEL_FALLBACK) { expect(isOpenRouterFreeModel(model)).toBe(true); } }); + + it('the offline fallback list is never empty (it is the last resort when the live catalog fails)', () => { + expect(OPENROUTER_FREE_MODEL_FALLBACK.length).toBeGreaterThan(0); + }); }); describe('isCircuitOpen()', () => { diff --git a/tests/unit/settings/OpenRouterSection.test.tsx b/tests/unit/settings/OpenRouterSection.test.tsx index 57b4b2e4d..ce6fca791 100644 --- a/tests/unit/settings/OpenRouterSection.test.tsx +++ b/tests/unit/settings/OpenRouterSection.test.tsx @@ -4,7 +4,7 @@ * circuit reset, and cloud AI policy gating. */ -import { render, screen, waitFor } from '@testing-library/react'; +import { render, screen, waitFor, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { beforeEach, describe, expect, it, vi } from 'vitest'; @@ -60,7 +60,7 @@ vi.mock('../../../services/ai/openrouterModels', () => ({ vi.mock('../../../services/ai/providers/openrouterProvider', () => ({ getApproxRpm: () => 0, isCircuitOpen: () => mocks.isCircuitOpen(), - OPENROUTER_FREE_MODELS: [ + OPENROUTER_FREE_MODEL_FALLBACK: [ 'deepseek/deepseek-r1:free', 'meta-llama/llama-3.3-70b-instruct:free', 'qwen/qwen2.5-72b-instruct:free', @@ -357,4 +357,128 @@ describe('OpenRouterSection', () => { await user.click(resetBtn); expect(mocks.resetCircuit).toHaveBeenCalled(); }); + + // --------------------------------------------------------------------------- + // WS-4: live catalog derives the free-tier group (OR-1..OR-5 regressions) + // --------------------------------------------------------------------------- + + it('shows a live-fetched free model that is not in the offline fallback list (OR-1 regression)', async () => { + mocks.settingsState.openRouter = { enabled: false, preferredModel: 'brand-new/model:free' }; + mocks.fetchModels.mockResolvedValue([ + { id: 'brand-new/model:free', name: 'Brand New Model (free)' }, + ]); + render(); + const select = await waitFor(() => screen.getByLabelText('settings.openRouter.modelAriaLabel')); + await waitFor(() => { + expect(within(select).getByText('Brand New Model (free)')).toBeInTheDocument(); + }); + }); + + it('selectValue matches a live-fetched free model instead of falling back to custom (OR-3 regression)', async () => { + mocks.settingsState.openRouter = { enabled: false, preferredModel: 'brand-new/model:free' }; + mocks.fetchModels.mockResolvedValue([ + { id: 'brand-new/model:free', name: 'Brand New Model (free)' }, + ]); + render(); + const select = (await waitFor(() => + screen.getByLabelText('settings.openRouter.modelAriaLabel'), + )) as HTMLSelectElement; + await waitFor(() => { + expect(select.value).toBe('brand-new/model:free'); + }); + // A matched, non-custom model must not show the free-form custom input. + expect( + screen.queryByLabelText('settings.openRouter.customModelAriaLabel'), + ).not.toBeInTheDocument(); + }); + + it('falls back to the offline list and shows a notice when the live catalog fetch fails', async () => { + mocks.fetchModels.mockRejectedValue(new Error('network down')); + render(); + await waitFor(() => { + expect(screen.getByText('settings.openRouter.freeModel.fallbackNotice')).toBeInTheDocument(); + }); + const select = screen.getByLabelText('settings.openRouter.modelAriaLabel'); + expect( + within(select).getByText('settings.openRouter.freeModel.deepseekR1'), + ).toBeInTheDocument(); + }); + + it('shows a stale-model warning and offers a one-click switch when preferredModel is missing from a successfully fetched catalog (OR-2 regression)', async () => { + mocks.settingsState.openRouter = { enabled: false, preferredModel: 'now-gone/model:free' }; + mocks.fetchModels.mockResolvedValue([ + { id: 'still-here/model:free', name: 'Still Here (free)' }, + ]); + const user = userEvent.setup(); + render(); + await waitFor(() => { + expect(screen.getByText('settings.openRouter.modelUnavailable')).toBeInTheDocument(); + }); + await user.click(screen.getByText('settings.openRouter.switchToAvailableModel')); + expect(mocks.dispatch).toHaveBeenCalledWith( + settingsActions.setOpenRouter({ preferredModel: 'still-here/model:free' }), + ); + }); + + it('does not show a stale-model warning for a deliberately entered custom model ID (CodeRabbit regression)', async () => { + // QNBS-v3: a custom ID is never in the catalog by definition — must not be flagged as stale. + mocks.settingsState.openRouter = { enabled: false, preferredModel: 'my-team/private-model' }; + mocks.fetchModels.mockResolvedValue([{ id: 'other/model:free', name: 'Other Model (free)' }]); + const user = userEvent.setup(); + render(); + + const customInput = await waitFor(() => + screen.getByLabelText('settings.openRouter.customModelAriaLabel'), + ); + expect(customInput).toHaveValue('my-team/private-model'); + + // Explicitly commit the same custom ID — this is what marks it "deliberately custom". + await user.clear(customInput); + await user.type(customInput, 'my-team/private-model'); + await user.tab(); + + const select = screen.getByLabelText('settings.openRouter.modelAriaLabel'); + await waitFor(() => { + expect(within(select).getByText('Other Model (free)')).toBeInTheDocument(); + }); + expect(screen.queryByText('settings.openRouter.modelUnavailable')).not.toBeInTheDocument(); + }); + + it('a catalog refresh mid-edit does not stomp an uncommitted custom-model keystroke (CodeRabbit regression)', async () => { + // QNBS-v3: a refresh gives knownOptionIds a new Set identity — must not be read as an external preferredModel change and overwrite what the user is actively typing. + const user = userEvent.setup(); + render(); + const select = await waitFor(() => screen.getByLabelText('settings.openRouter.modelAriaLabel')); + await user.selectOptions(select, '__custom__'); + const customInput = screen.getByLabelText('settings.openRouter.customModelAriaLabel'); + + await user.type(customInput, 'still-typing/not-committed-yet'); + mocks.fetchModels.mockClear(); + await user.click( + screen.getByRole('button', { name: 'settings.openRouter.refreshModelsAriaLabel' }), + ); + await waitFor(() => expect(mocks.fetchModels).toHaveBeenCalled()); + + // QNBS-v3: re-query the live DOM node — a captured pre-refresh reference could pass even if the component remounted the field and reset it. + await waitFor(() => { + expect(screen.getByLabelText('settings.openRouter.customModelAriaLabel')).toHaveValue( + 'still-typing/not-committed-yet', + ); + }); + }); + + it('refresh button clears the cache and re-fetches the catalog', async () => { + const user = userEvent.setup(); + render(); + await waitFor(() => screen.getByLabelText('settings.openRouter.modelAriaLabel')); + mocks.clearCache.mockClear(); + mocks.fetchModels.mockClear(); + await user.click( + screen.getByRole('button', { name: 'settings.openRouter.refreshModelsAriaLabel' }), + ); + await waitFor(() => { + expect(mocks.clearCache).toHaveBeenCalled(); + expect(mocks.fetchModels).toHaveBeenCalled(); + }); + }); });
+ {t('settings.openRouter.freeModel.fallbackNotice')} +
+ {t('settings.openRouter.modelUnavailable')} +
{t('settings.openRouter.freeTierNote')}