diff --git a/changelog.d/features/9752-one-click-free-providers.md b/changelog.d/features/9752-one-click-free-providers.md
new file mode 100644
index 0000000000..f8c06d4603
--- /dev/null
+++ b/changelog.d/features/9752-one-click-free-providers.md
@@ -0,0 +1,4 @@
+- **Onboarding:** add an explicit, reviewable one-click setup for eligible no-auth LLM providers,
+ with per-provider caution links, selectable confirmation, idempotent creation, and safe partial
+ retries. Existing provider connections are never changed and setup completion never enables
+ providers silently. ([#9752](https://github.com/diegosouzapw/OmniRoute/issues/9752))
diff --git a/docs/getting-started/PROVIDERS-GUIDE.md b/docs/getting-started/PROVIDERS-GUIDE.md
index c1c237862e..f725baa6df 100644
--- a/docs/getting-started/PROVIDERS-GUIDE.md
+++ b/docs/getting-started/PROVIDERS-GUIDE.md
@@ -30,6 +30,18 @@ See **[WEB-COOKIE-GUIDE.md](./WEB-COOKIE-GUIDE.md)** for general setup instructi
## Quick Start: Connect Your First Provider
+### Optional first-run free-provider setup
+
+The first-run wizard offers an explicit **Set up free providers** card. It derives the current
+eligible list from OmniRoute's no-auth provider registry, then lets you review and deselect each
+provider before confirming. OmniRoute shows the provider's caution notice and a link to its site
+so you can review third-party terms, privacy, availability, and rate limits first.
+
+This action is optional: finishing the wizard never creates free-provider connections silently.
+It creates only providers that are still missing, leaves existing customized connections
+untouched, and reports created, already-configured, and failed providers individually. You can
+safely retry only the failures after a partial result.
+
### Option A: Free Provider (No Credit Card)
1. Open the dashboard at `http://localhost:20128`
diff --git a/src/app/(dashboard)/dashboard/onboarding/page.tsx b/src/app/(dashboard)/dashboard/onboarding/page.tsx
index 7385bc0a86..f0164d63ac 100644
--- a/src/app/(dashboard)/dashboard/onboarding/page.tsx
+++ b/src/app/(dashboard)/dashboard/onboarding/page.tsx
@@ -4,6 +4,7 @@ import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useDisplayBaseUrl } from "@/shared/hooks";
+import { FreeProviderOnboardingCard } from "./steps/FreeProviderOnboardingCard";
import { TierTour } from "./steps/TierTour";
const STEP_IDS = ["welcome", "tiers", "security", "provider", "test", "done"];
@@ -357,6 +358,12 @@ export default function OnboardingWizard() {
{currentStep.id === "provider" && (
{t("providerDesc")}
+
+
+
+ {t("freeProviders.orUseApiKey")}
+
+
{COMMON_PROVIDERS.map((p) => (
> {
+ return (await response.json().catch(() => ({}))) as Record;
+}
+
+export function FreeProviderOnboardingCard() {
+ const t = useTranslations("onboarding.freeProviders");
+ const [providers, setProviders] = useState([]);
+ const [selectedIds, setSelectedIds] = useState([]);
+ const [confirmed, setConfirmed] = useState(false);
+ const [loading, setLoading] = useState(true);
+ const [submitting, setSubmitting] = useState(false);
+ const [error, setError] = useState("");
+ const [results, setResults] = useState([]);
+
+ useEffect(() => {
+ let active = true;
+ void fetch("/api/providers/free-onboarding")
+ .then(async (response) => {
+ const data = await readJson(response);
+ if (!response.ok) throw new Error("load-failed");
+ const options = Array.isArray(data.providers)
+ ? (data.providers as FreeProviderOption[])
+ : [];
+ if (!active) return;
+ setProviders(options);
+ setSelectedIds(options.map((provider) => provider.id).sort());
+ })
+ .catch(() => {
+ if (active) setError(t("loadFailed"));
+ })
+ .finally(() => {
+ if (active) setLoading(false);
+ });
+ return () => {
+ active = false;
+ };
+ }, [t]);
+
+ const failedIds = useMemo(
+ () => results.filter((result) => result.status === "failed").map((result) => result.providerId),
+ [results]
+ );
+
+ const toggleProvider = (providerId: string) => {
+ setSelectedIds((current) =>
+ current.includes(providerId)
+ ? current.filter((id) => id !== providerId)
+ : [...current, providerId].sort()
+ );
+ setConfirmed(false);
+ };
+
+ const submit = async (providerIds = selectedIds) => {
+ setSubmitting(true);
+ setError("");
+ try {
+ const response = await fetch("/api/providers/free-onboarding", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ providerIds, confirmed: true }),
+ });
+ const data = await readJson(response);
+ if (!response.ok) throw new Error("setup-failed");
+ setResults(Array.isArray(data.results) ? (data.results as SetupResult[]) : []);
+ } catch {
+ setError(t("setupFailed"));
+ } finally {
+ setSubmitting(false);
+ }
+ };
+
+ if (loading) return {t("loading")}
;
+ if (providers.length === 0 && !error) {
+ return {t("alreadyConfigured")}
;
+ }
+
+ return (
+
+
+
{t("title")}
+
{t("description")}
+
+
+
+
+
+ setConfirmed(event.target.checked)}
+ className="mt-0.5 accent-primary"
+ />
+ {t("confirmation")}
+
+
+ {error && {error}
}
+ {results.length > 0 && (
+
+ {results.map((result) => (
+
+ {result.providerId}: {t(`result.${result.status}`)}
+
+ ))}
+
+ )}
+
+
+ void submit()}
+ className="rounded-lg bg-primary px-4 py-2 text-xs font-medium text-white disabled:cursor-not-allowed disabled:opacity-50"
+ >
+ {submitting ? t("settingUp") : t("setupSelected")}
+
+ {failedIds.length > 0 && (
+ void submit(failedIds)}
+ className="rounded-lg border border-white/10 px-4 py-2 text-xs text-text-main disabled:opacity-50"
+ >
+ {t("retryFailed")}
+
+ )}
+
+
+ );
+}
diff --git a/src/app/api/providers/free-onboarding/route.ts b/src/app/api/providers/free-onboarding/route.ts
new file mode 100644
index 0000000000..dd22cb99ca
--- /dev/null
+++ b/src/app/api/providers/free-onboarding/route.ts
@@ -0,0 +1,69 @@
+import { NextResponse } from "next/server";
+import { z } from "zod";
+
+import { requireManagementAuth } from "@/lib/api/requireManagementAuth";
+import { createProviderConnection, getProviderConnections } from "@/lib/db/providers";
+import {
+ getEligibleFreeOnboardingProviders,
+ selectUnconfiguredFreeOnboardingProviders,
+ setupFreeProviderConnections,
+ withFreeProviderSetupLock,
+} from "@/lib/providers/freeOnboarding";
+import { isValidationFailure, validateBody } from "@/shared/validation/helpers";
+
+const setupSchema = z.object({
+ providerIds: z.array(z.string().trim().min(1)).min(1).max(20),
+ confirmed: z.literal(true),
+});
+
+export async function GET(request: Request) {
+ const authError = await requireManagementAuth(request);
+ if (authError) return authError;
+
+ try {
+ const candidates = getEligibleFreeOnboardingProviders();
+ const connections = await getProviderConnections();
+ return NextResponse.json({
+ providers: selectUnconfiguredFreeOnboardingProviders(candidates, connections),
+ });
+ } catch {
+ return NextResponse.json({ error: "Failed to load free providers" }, { status: 500 });
+ }
+}
+
+export async function POST(request: Request) {
+ const authError = await requireManagementAuth(request);
+ if (authError) return authError;
+
+ let rawBody: unknown;
+ try {
+ rawBody = await request.json();
+ } catch {
+ return NextResponse.json({ error: "Invalid JSON body" }, { status: 400 });
+ }
+
+ const validation = validateBody(setupSchema, rawBody);
+ if (isValidationFailure(validation)) {
+ return NextResponse.json({ error: validation.error }, { status: 400 });
+ }
+
+ try {
+ const result = await withFreeProviderSetupLock(() =>
+ setupFreeProviderConnections({
+ requestedIds: validation.data.providerIds,
+ candidates: getEligibleFreeOnboardingProviders(),
+ listExisting: () => getProviderConnections(),
+ create: (input) => createProviderConnection(input),
+ })
+ );
+ return NextResponse.json(result);
+ } catch (error) {
+ if (error instanceof Error && error.message.startsWith("Ineligible free provider IDs:")) {
+ return NextResponse.json(
+ { error: "One or more providers are not eligible" },
+ { status: 400 }
+ );
+ }
+ return NextResponse.json({ error: "Failed to set up free providers" }, { status: 500 });
+ }
+}
diff --git a/src/i18n/messages/ar.json b/src/i18n/messages/ar.json
index 93bfb067ef..6c98e5d525 100644
--- a/src/i18n/messages/ar.json
+++ b/src/i18n/messages/ar.json
@@ -4744,7 +4744,26 @@
"configure": "تكوين مقدمي الخدمات"
},
"tierFlowDiagramAlt": "OmniRoute مخطط احتياطي ثلاثي الطبقات",
- "apiKeyMgmt": "إدارة مفتاح واجهة برمجة التطبيقات (API)"
+ "apiKeyMgmt": "إدارة مفتاح واجهة برمجة التطبيقات (API)",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "المزودون",
diff --git a/src/i18n/messages/az.json b/src/i18n/messages/az.json
index 7f1c6e9cb2..56d431f998 100644
--- a/src/i18n/messages/az.json
+++ b/src/i18n/messages/az.json
@@ -4744,7 +4744,26 @@
"configure": "Provayderləri konfiqurasiya edin"
},
"tierFlowDiagramAlt": "OmniRoute 3 səviyyəli ehtiyat diaqramı",
- "apiKeyMgmt": "API Açar İdarəetmə"
+ "apiKeyMgmt": "API Açar İdarəetmə",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/bg.json b/src/i18n/messages/bg.json
index f9cfd6e34f..e6ca4d2dac 100644
--- a/src/i18n/messages/bg.json
+++ b/src/i18n/messages/bg.json
@@ -4744,7 +4744,26 @@
"configure": "Конфигурирайте доставчици"
},
"tierFlowDiagramAlt": "3-степенна резервна диаграма на OmniRoute",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Доставчици",
diff --git a/src/i18n/messages/bn.json b/src/i18n/messages/bn.json
index 58146ad7d0..5335d58074 100644
--- a/src/i18n/messages/bn.json
+++ b/src/i18n/messages/bn.json
@@ -4744,7 +4744,26 @@
"configure": "প্রদানকারী কনফিগার করুন"
},
"tierFlowDiagramAlt": "OmniRoute 3-স্তরের ফলব্যাক ডায়াগ্রাম",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/cs.json b/src/i18n/messages/cs.json
index bfb6f40bd7..457eccc154 100644
--- a/src/i18n/messages/cs.json
+++ b/src/i18n/messages/cs.json
@@ -4744,7 +4744,26 @@
"configure": "Nakonfigurujte poskytovatele"
},
"tierFlowDiagramAlt": "Třívrstvý záložní diagram OmniRoute",
- "apiKeyMgmt": "Správa API klíčů"
+ "apiKeyMgmt": "Správa API klíčů",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Poskytovatelé",
diff --git a/src/i18n/messages/da.json b/src/i18n/messages/da.json
index 8c5d27f542..cfb3d08689 100644
--- a/src/i18n/messages/da.json
+++ b/src/i18n/messages/da.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurer udbydere"
},
"tierFlowDiagramAlt": "OmniRoute 3-tiers fallback diagram",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Udbydere",
diff --git a/src/i18n/messages/de.json b/src/i18n/messages/de.json
index eb410b6107..54de1c4c4a 100644
--- a/src/i18n/messages/de.json
+++ b/src/i18n/messages/de.json
@@ -4744,7 +4744,26 @@
"configure": "Anbieter konfigurieren"
},
"tierFlowDiagramAlt": "OmniRoute 3-Stufen-Fallback-Diagramm",
- "apiKeyMgmt": "API-Schlüsselverwaltung"
+ "apiKeyMgmt": "API-Schlüsselverwaltung",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Anbieter",
diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json
index 3dd99218d4..0e35cfcc8c 100644
--- a/src/i18n/messages/en.json
+++ b/src/i18n/messages/en.json
@@ -4750,7 +4750,26 @@
"configure": "Configure providers"
},
"tierFlowDiagramAlt": "OmniRoute 3-tier fallback diagram",
- "apiKeyMgmt": "API Key Management"
+ "apiKeyMgmt": "API Key Management",
+ "freeProviders": {
+ "title": "Set up free providers",
+ "description": "Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "Loading free providers...",
+ "loadFailed": "Could not load free providers.",
+ "alreadyConfigured": "All eligible free providers are already configured.",
+ "reviewProviderSite": "Review provider site and terms",
+ "confirmation": "I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "Set up selected providers",
+ "settingUp": "Setting up...",
+ "setupFailed": "Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "Retry failed providers",
+ "orUseApiKey": "or connect with an API key",
+ "result": {
+ "created": "created",
+ "skipped": "already configured",
+ "failed": "failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/es.json b/src/i18n/messages/es.json
index 5a8e4533b2..753428fee9 100644
--- a/src/i18n/messages/es.json
+++ b/src/i18n/messages/es.json
@@ -4744,7 +4744,26 @@
"configure": "Configurar proveedores"
},
"tierFlowDiagramAlt": "Diagrama alternativo de 3 niveles de OmniRoute",
- "apiKeyMgmt": "Gestión de claves API"
+ "apiKeyMgmt": "Gestión de claves API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Proveedores",
diff --git a/src/i18n/messages/fa.json b/src/i18n/messages/fa.json
index a685d117ba..e14d12dc1f 100644
--- a/src/i18n/messages/fa.json
+++ b/src/i18n/messages/fa.json
@@ -4744,7 +4744,26 @@
"configure": "ارائه دهندگان را پیکربندی کنید"
},
"tierFlowDiagramAlt": "نمودار بازگشتی 3 لایه OmniRoute",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/fi.json b/src/i18n/messages/fi.json
index a969f27b86..7772b6c7a8 100644
--- a/src/i18n/messages/fi.json
+++ b/src/i18n/messages/fi.json
@@ -4744,7 +4744,26 @@
"configure": "Määritä palveluntarjoajat"
},
"tierFlowDiagramAlt": "OmniRoute 3-tasoinen varakaavio",
- "apiKeyMgmt": "API-avainhallinta"
+ "apiKeyMgmt": "API-avainhallinta",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Palveluntarjoajat",
diff --git a/src/i18n/messages/fr.json b/src/i18n/messages/fr.json
index d0a23dc6fb..72977a8ac9 100644
--- a/src/i18n/messages/fr.json
+++ b/src/i18n/messages/fr.json
@@ -4744,7 +4744,26 @@
"configure": "Configurer les fournisseurs"
},
"tierFlowDiagramAlt": "Diagramme de secours OmniRoute à 3 niveaux",
- "apiKeyMgmt": "Gestion des clés API"
+ "apiKeyMgmt": "Gestion des clés API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Fournisseurs",
diff --git a/src/i18n/messages/gu.json b/src/i18n/messages/gu.json
index 4a4f3ca7d0..fc080fbbb0 100644
--- a/src/i18n/messages/gu.json
+++ b/src/i18n/messages/gu.json
@@ -4744,7 +4744,26 @@
"configure": "પ્રદાતાઓને ગોઠવો"
},
"tierFlowDiagramAlt": "OmniRoute 3-ટાયર ફોલબેક ડાયાગ્રામ",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/he.json b/src/i18n/messages/he.json
index 1117b62ec0..54633d032f 100644
--- a/src/i18n/messages/he.json
+++ b/src/i18n/messages/he.json
@@ -4744,7 +4744,26 @@
"configure": "הגדר ספקים"
},
"tierFlowDiagramAlt": "דיאגרמת OmniRoute 3-tier fallback",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "ספקים",
diff --git a/src/i18n/messages/hi.json b/src/i18n/messages/hi.json
index 10cd712a10..6b2c5b4ea3 100644
--- a/src/i18n/messages/hi.json
+++ b/src/i18n/messages/hi.json
@@ -4744,7 +4744,26 @@
"configure": "प्रदाताओं को कॉन्फ़िगर करें"
},
"tierFlowDiagramAlt": "ओम्निरूट 3-स्तरीय फ़ॉलबैक आरेख",
- "apiKeyMgmt": "एपीआई कुंजी प्रबंधन"
+ "apiKeyMgmt": "एपीआई कुंजी प्रबंधन",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "प्रदाता",
diff --git a/src/i18n/messages/hu.json b/src/i18n/messages/hu.json
index 4fb34eb273..8bf0feabc1 100644
--- a/src/i18n/messages/hu.json
+++ b/src/i18n/messages/hu.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurálja a szolgáltatókat"
},
"tierFlowDiagramAlt": "OmniRoute 3-szintű tartalék diagram",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Szolgáltatók",
diff --git a/src/i18n/messages/id.json b/src/i18n/messages/id.json
index e07abb08e2..f7d2a08e36 100644
--- a/src/i18n/messages/id.json
+++ b/src/i18n/messages/id.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurasikan penyedia"
},
"tierFlowDiagramAlt": "Diagram cadangan 3 tingkat OmniRoute",
- "apiKeyMgmt": "Manajemen Kunci API"
+ "apiKeyMgmt": "Manajemen Kunci API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Penyedia",
diff --git a/src/i18n/messages/in.json b/src/i18n/messages/in.json
index 068f6ab2df..af4cfddf38 100644
--- a/src/i18n/messages/in.json
+++ b/src/i18n/messages/in.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurasikan penyedia"
},
"tierFlowDiagramAlt": "Diagram cadangan 3 tingkat OmniRoute",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/it.json b/src/i18n/messages/it.json
index 1ba03c3cce..4b24a63806 100644
--- a/src/i18n/messages/it.json
+++ b/src/i18n/messages/it.json
@@ -4744,7 +4744,26 @@
"configure": "Configura i fornitori"
},
"tierFlowDiagramAlt": "Diagramma di fallback a 3 livelli di OmniRoute",
- "apiKeyMgmt": "Gestione chiave API"
+ "apiKeyMgmt": "Gestione chiave API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Fornitori",
diff --git a/src/i18n/messages/ja.json b/src/i18n/messages/ja.json
index c8e3ab75cd..fa2d728ce9 100644
--- a/src/i18n/messages/ja.json
+++ b/src/i18n/messages/ja.json
@@ -4744,7 +4744,26 @@
"configure": "プロバイダーの構成"
},
"tierFlowDiagramAlt": "OmniRoute 3 層フォールバック図",
- "apiKeyMgmt": "APIキー管理"
+ "apiKeyMgmt": "APIキー管理",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "プロバイダー",
diff --git a/src/i18n/messages/ko.json b/src/i18n/messages/ko.json
index 3465d4dd4d..4d5d2bc422 100644
--- a/src/i18n/messages/ko.json
+++ b/src/i18n/messages/ko.json
@@ -4744,7 +4744,26 @@
"configure": "공급자 구성"
},
"tierFlowDiagramAlt": "OmniRoute 3계층 대체 다이어그램",
- "apiKeyMgmt": "API 키 관리"
+ "apiKeyMgmt": "API 키 관리",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "공급자",
diff --git a/src/i18n/messages/mr.json b/src/i18n/messages/mr.json
index 181829d6e5..c1bf3dbb77 100644
--- a/src/i18n/messages/mr.json
+++ b/src/i18n/messages/mr.json
@@ -4744,7 +4744,26 @@
"configure": "प्रदाते कॉन्फिगर करा"
},
"tierFlowDiagramAlt": "OmniRoute 3-स्तरीय फॉलबॅक आकृती",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/ms.json b/src/i18n/messages/ms.json
index fab7dc22c3..20af75597c 100644
--- a/src/i18n/messages/ms.json
+++ b/src/i18n/messages/ms.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurasikan pembekal"
},
"tierFlowDiagramAlt": "Gambar rajah sandar 3 peringkat OmniRoute",
- "apiKeyMgmt": "Mgmt Kunci API"
+ "apiKeyMgmt": "Mgmt Kunci API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Pembekal",
diff --git a/src/i18n/messages/nl.json b/src/i18n/messages/nl.json
index 834c8aae6d..6675e33a45 100644
--- a/src/i18n/messages/nl.json
+++ b/src/i18n/messages/nl.json
@@ -4744,7 +4744,26 @@
"configure": "Configureer aanbieders"
},
"tierFlowDiagramAlt": "OmniRoute fallback-diagram met 3 niveaus",
- "apiKeyMgmt": "API-sleutelbeheer"
+ "apiKeyMgmt": "API-sleutelbeheer",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Aanbieders",
diff --git a/src/i18n/messages/no.json b/src/i18n/messages/no.json
index 58789e2514..b3aa989d89 100644
--- a/src/i18n/messages/no.json
+++ b/src/i18n/messages/no.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurer leverandører"
},
"tierFlowDiagramAlt": "OmniRoute 3-lags reservediagram",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Leverandører",
diff --git a/src/i18n/messages/phi.json b/src/i18n/messages/phi.json
index 4fd30f026c..9efe7facb6 100644
--- a/src/i18n/messages/phi.json
+++ b/src/i18n/messages/phi.json
@@ -4744,7 +4744,26 @@
"configure": "I-configure ang mga provider"
},
"tierFlowDiagramAlt": "OmniRoute 3-tier fallback diagram",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Mga provider",
diff --git a/src/i18n/messages/pl.json b/src/i18n/messages/pl.json
index f0604529d2..22b7fcd8df 100644
--- a/src/i18n/messages/pl.json
+++ b/src/i18n/messages/pl.json
@@ -4744,7 +4744,26 @@
"configure": "Skonfiguruj providers"
},
"tierFlowDiagramAlt": "Schemat fallback 3-poziomowego OmniRoute",
- "apiKeyMgmt": "Zarządzanie kluczami API"
+ "apiKeyMgmt": "Zarządzanie kluczami API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/pt-BR.json b/src/i18n/messages/pt-BR.json
index ecd5691af5..b1f281d9a8 100644
--- a/src/i18n/messages/pt-BR.json
+++ b/src/i18n/messages/pt-BR.json
@@ -4750,7 +4750,26 @@
"configure": "Configurar provedores"
},
"tierFlowDiagramAlt": "Diagrama de fallback de 3 camadas do OmniRoute",
- "apiKeyMgmt": "Ger. de Chaves API"
+ "apiKeyMgmt": "Ger. de Chaves API",
+ "freeProviders": {
+ "title": "Configurar provedores gratuitos",
+ "description": "Opcionalmente, ative provedores selecionados que não exigem cadastro. Revise o aviso e o site de cada provedor antes de continuar; disponibilidade e limites são controlados por terceiros.",
+ "loading": "Carregando provedores gratuitos...",
+ "loadFailed": "Não foi possível carregar os provedores gratuitos.",
+ "alreadyConfigured": "Todos os provedores gratuitos elegíveis já estão configurados.",
+ "reviewProviderSite": "Revisar site e termos do provedor",
+ "confirmation": "Revisei estes provedores de terceiros e quero que o OmniRoute crie as conexões selecionadas.",
+ "setupSelected": "Configurar provedores selecionados",
+ "settingUp": "Configurando...",
+ "setupFailed": "Não foi possível configurar os provedores selecionados. Nenhuma conexão existente foi alterada.",
+ "retryFailed": "Tentar novamente os provedores com falha",
+ "orUseApiKey": "ou conectar com uma chave de API",
+ "result": {
+ "created": "criado",
+ "skipped": "já configurado",
+ "failed": "falhou"
+ }
+ }
},
"providers": {
"title": "Provedores",
diff --git a/src/i18n/messages/pt.json b/src/i18n/messages/pt.json
index 9fbfc1c65b..6e0922cbe1 100644
--- a/src/i18n/messages/pt.json
+++ b/src/i18n/messages/pt.json
@@ -4744,7 +4744,26 @@
"configure": "Configurar provedores"
},
"tierFlowDiagramAlt": "Diagrama de fallback de 3 camadas do OmniRoute",
- "apiKeyMgmt": "Gerenciamento de chave de API"
+ "apiKeyMgmt": "Gerenciamento de chave de API",
+ "freeProviders": {
+ "title": "Configurar fornecedores gratuitos",
+ "description": "Opcionalmente, ative fornecedores selecionados que não exigem registo. Reveja o aviso e o site de cada fornecedor antes de continuar; a disponibilidade e os limites são controlados por terceiros.",
+ "loading": "A carregar fornecedores gratuitos...",
+ "loadFailed": "Não foi possível carregar os fornecedores gratuitos.",
+ "alreadyConfigured": "Todos os fornecedores gratuitos elegíveis já estão configurados.",
+ "reviewProviderSite": "Rever site e termos do fornecedor",
+ "confirmation": "Revi estes fornecedores de terceiros e quero que o OmniRoute crie as ligações selecionadas.",
+ "setupSelected": "Configurar fornecedores selecionados",
+ "settingUp": "A configurar...",
+ "setupFailed": "Não foi possível configurar os fornecedores selecionados. Nenhuma ligação existente foi alterada.",
+ "retryFailed": "Tentar novamente os fornecedores com falha",
+ "orUseApiKey": "ou ligar com uma chave de API",
+ "result": {
+ "created": "criado",
+ "skipped": "já configurado",
+ "failed": "falhou"
+ }
+ }
},
"providers": {
"title": "Provedores",
diff --git a/src/i18n/messages/ro.json b/src/i18n/messages/ro.json
index 2fa29eebaf..bcb3f5f21c 100644
--- a/src/i18n/messages/ro.json
+++ b/src/i18n/messages/ro.json
@@ -4744,7 +4744,26 @@
"configure": "Configurați furnizorii"
},
"tierFlowDiagramAlt": "Diagrama de rezervă pe 3 niveluri OmniRoute",
- "apiKeyMgmt": "Gestiunea cheii API"
+ "apiKeyMgmt": "Gestiunea cheii API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Furnizorii",
diff --git a/src/i18n/messages/ru.json b/src/i18n/messages/ru.json
index 85f1156799..88ee259461 100644
--- a/src/i18n/messages/ru.json
+++ b/src/i18n/messages/ru.json
@@ -4744,7 +4744,26 @@
"configure": "Настройка поставщиков"
},
"tierFlowDiagramAlt": "Трехуровневая резервная схема OmniRoute",
- "apiKeyMgmt": "Управление ключами API"
+ "apiKeyMgmt": "Управление ключами API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Провайдеры",
diff --git a/src/i18n/messages/sk.json b/src/i18n/messages/sk.json
index 7d939a5de8..a77c8b24f7 100644
--- a/src/i18n/messages/sk.json
+++ b/src/i18n/messages/sk.json
@@ -4744,7 +4744,26 @@
"configure": "Nakonfigurujte poskytovateľov"
},
"tierFlowDiagramAlt": "3-vrstvový záložný diagram OmniRoute",
- "apiKeyMgmt": "API kľúč Mgmt"
+ "apiKeyMgmt": "API kľúč Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Poskytovatelia",
diff --git a/src/i18n/messages/sv.json b/src/i18n/messages/sv.json
index 7f08d920c0..389aa28c8d 100644
--- a/src/i18n/messages/sv.json
+++ b/src/i18n/messages/sv.json
@@ -4744,7 +4744,26 @@
"configure": "Konfigurera leverantörer"
},
"tierFlowDiagramAlt": "OmniRoute 3-nivå reservdiagram",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Leverantörer",
diff --git a/src/i18n/messages/sw.json b/src/i18n/messages/sw.json
index ec8b508d9b..ae054603a4 100644
--- a/src/i18n/messages/sw.json
+++ b/src/i18n/messages/sw.json
@@ -4744,7 +4744,26 @@
"configure": "Sanidi watoa huduma"
},
"tierFlowDiagramAlt": "Mchoro wa kurudi nyuma wa ngazi 3 wa OmniRoute",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/ta.json b/src/i18n/messages/ta.json
index 1e75091675..50e26bed31 100644
--- a/src/i18n/messages/ta.json
+++ b/src/i18n/messages/ta.json
@@ -4744,7 +4744,26 @@
"configure": "வழங்குநர்களை உள்ளமைக்கவும்"
},
"tierFlowDiagramAlt": "OmniRoute 3-அடுக்கு ஃபால்பேக் வரைபடம்",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/te.json b/src/i18n/messages/te.json
index 39ca6eaa71..5c8323aa78 100644
--- a/src/i18n/messages/te.json
+++ b/src/i18n/messages/te.json
@@ -4744,7 +4744,26 @@
"configure": "ప్రొవైడర్లను కాన్ఫిగర్ చేయండి"
},
"tierFlowDiagramAlt": "OmniRoute 3-టైర్ ఫాల్బ్యాక్ రేఖాచిత్రం",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/th.json b/src/i18n/messages/th.json
index 3e8d03dc7f..8236930553 100644
--- a/src/i18n/messages/th.json
+++ b/src/i18n/messages/th.json
@@ -4744,7 +4744,26 @@
"configure": "กำหนดค่าผู้ให้บริการ"
},
"tierFlowDiagramAlt": "แผนภาพทางเลือก OmniRoute 3 ระดับ",
- "apiKeyMgmt": "การจัดการคีย์ API"
+ "apiKeyMgmt": "การจัดการคีย์ API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "ผู้ให้บริการ",
diff --git a/src/i18n/messages/tr.json b/src/i18n/messages/tr.json
index 62ca2a4517..46e4a89ec8 100644
--- a/src/i18n/messages/tr.json
+++ b/src/i18n/messages/tr.json
@@ -4744,7 +4744,26 @@
"configure": "Sağlayıcıları yapılandırma"
},
"tierFlowDiagramAlt": "OmniRoute 3 katmanlı geri dönüş diyagramı",
- "apiKeyMgmt": "API Anahtarı Yönetimi"
+ "apiKeyMgmt": "API Anahtarı Yönetimi",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Sağlayıcılar",
diff --git a/src/i18n/messages/uk-UA.json b/src/i18n/messages/uk-UA.json
index 1931707ada..08f004aa06 100644
--- a/src/i18n/messages/uk-UA.json
+++ b/src/i18n/messages/uk-UA.json
@@ -4744,7 +4744,26 @@
"configure": "Налаштувати провайдерів"
},
"tierFlowDiagramAlt": "3-рівнева резервна схема OmniRoute",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Провайдери",
diff --git a/src/i18n/messages/ur.json b/src/i18n/messages/ur.json
index 5bc9e630a0..22aad14287 100644
--- a/src/i18n/messages/ur.json
+++ b/src/i18n/messages/ur.json
@@ -4744,7 +4744,26 @@
"configure": "فراہم کنندگان کو ترتیب دیں۔"
},
"tierFlowDiagramAlt": "OmniRoute 3 درجے کا فال بیک ڈایاگرام",
- "apiKeyMgmt": "API Key Mgmt"
+ "apiKeyMgmt": "API Key Mgmt",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Providers",
diff --git a/src/i18n/messages/vi.json b/src/i18n/messages/vi.json
index 0a52f43c79..de62323a3c 100644
--- a/src/i18n/messages/vi.json
+++ b/src/i18n/messages/vi.json
@@ -4744,7 +4744,26 @@
"configure": "Cấu hình nhà cung cấp"
},
"tierFlowDiagramAlt": "Sơ đồ dự phòng 3 cấp của OmniRoute",
- "apiKeyMgmt": "Quản lý khóa API"
+ "apiKeyMgmt": "Quản lý khóa API",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "Nhà cung cấp",
diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json
index 478f5f2b49..a8e39e279a 100644
--- a/src/i18n/messages/zh-CN.json
+++ b/src/i18n/messages/zh-CN.json
@@ -4744,7 +4744,26 @@
"configure": "配置提供者"
},
"tierFlowDiagramAlt": "OmniRoute 3 层回退图",
- "apiKeyMgmt": "API密钥管理"
+ "apiKeyMgmt": "API密钥管理",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "提供者",
diff --git a/src/i18n/messages/zh-TW.json b/src/i18n/messages/zh-TW.json
index cfa907d4c5..408738fc13 100644
--- a/src/i18n/messages/zh-TW.json
+++ b/src/i18n/messages/zh-TW.json
@@ -4744,7 +4744,26 @@
"configure": "設定提供者"
},
"tierFlowDiagramAlt": "OmniRoute 3 層回退圖",
- "apiKeyMgmt": "API金鑰管理"
+ "apiKeyMgmt": "API金鑰管理",
+ "freeProviders": {
+ "title": "__MISSING__:Set up free providers",
+ "description": "__MISSING__:Optionally enable selected no-signup providers. Review each provider's notice and site before continuing; availability and rate limits are controlled by third parties.",
+ "loading": "__MISSING__:Loading free providers...",
+ "loadFailed": "__MISSING__:Could not load free providers.",
+ "alreadyConfigured": "__MISSING__:All eligible free providers are already configured.",
+ "reviewProviderSite": "__MISSING__:Review provider site and terms",
+ "confirmation": "__MISSING__:I reviewed these third-party providers and want OmniRoute to create the selected connections.",
+ "setupSelected": "__MISSING__:Set up selected providers",
+ "settingUp": "__MISSING__:Setting up...",
+ "setupFailed": "__MISSING__:Could not set up the selected providers. Nothing existing was changed.",
+ "retryFailed": "__MISSING__:Retry failed providers",
+ "orUseApiKey": "__MISSING__:or connect with an API key",
+ "result": {
+ "created": "__MISSING__:created",
+ "skipped": "__MISSING__:already configured",
+ "failed": "__MISSING__:failed"
+ }
+ }
},
"providers": {
"title": "提供者",
diff --git a/src/lib/providers/freeOnboarding.ts b/src/lib/providers/freeOnboarding.ts
new file mode 100644
index 0000000000..6c69c396f3
--- /dev/null
+++ b/src/lib/providers/freeOnboarding.ts
@@ -0,0 +1,164 @@
+import { NOAUTH_PROVIDERS } from "@/shared/constants/providers";
+import { REGISTRY } from "@omniroute/open-sse/config/providerRegistry";
+
+interface NoAuthOnboardingMetadata {
+ id: string;
+ name: string;
+ website?: string;
+ noAuth?: boolean;
+ hasFree?: boolean;
+ isLocalCli?: boolean;
+ serviceKinds?: string[];
+ authHint?: string;
+ freeNote?: string;
+ notice?: { text?: string };
+ deprecated?: boolean;
+ disabled?: boolean;
+ unsafe?: boolean;
+ hiddenFromDashboard?: boolean;
+}
+
+export interface FreeOnboardingProvider {
+ id: string;
+ name: string;
+ website: string;
+ caution: string;
+ defaultModel?: string;
+}
+
+export interface ExistingProviderConnection {
+ provider?: unknown;
+}
+
+export interface FreeProviderConnectionInput {
+ provider: string;
+ authType: "no-auth";
+ name: string;
+ isActive: true;
+ testStatus: "unknown";
+ defaultModel?: string;
+}
+
+export type FreeProviderSetupResult =
+ | { providerId: string; status: "created"; connectionId: string }
+ | { providerId: string; status: "skipped"; reason: "already-configured" }
+ | { providerId: string; status: "failed"; reason: "Failed to create provider" };
+
+function isEligibleProvider(provider: NoAuthOnboardingMetadata): boolean {
+ return (
+ provider.noAuth === true &&
+ provider.hasFree === true &&
+ provider.isLocalCli !== true &&
+ provider.serviceKinds?.includes("llm") === true &&
+ provider.deprecated !== true &&
+ provider.disabled !== true &&
+ provider.unsafe !== true &&
+ provider.hiddenFromDashboard !== true
+ );
+}
+
+function toOnboardingProvider(provider: NoAuthOnboardingMetadata): FreeOnboardingProvider {
+ const defaultModel = REGISTRY[provider.id]?.models?.[0]?.id;
+ return {
+ id: provider.id,
+ name: provider.name,
+ website: provider.website || "",
+ caution:
+ provider.notice?.text ||
+ provider.freeNote ||
+ provider.authHint ||
+ "This provider is operated by a third party and may enforce its own terms and limits.",
+ ...(defaultModel ? { defaultModel } : {}),
+ };
+}
+
+export function getEligibleFreeOnboardingProviders(): FreeOnboardingProvider[] {
+ return Object.values(NOAUTH_PROVIDERS as Record)
+ .filter(isEligibleProvider)
+ .map(toOnboardingProvider)
+ .sort((left, right) => left.id.localeCompare(right.id));
+}
+
+export function selectUnconfiguredFreeOnboardingProviders(
+ candidates: FreeOnboardingProvider[],
+ connections: ExistingProviderConnection[]
+): FreeOnboardingProvider[] {
+ const configured = new Set(
+ connections
+ .map((connection) => connection.provider)
+ .filter((provider): provider is string => typeof provider === "string")
+ );
+ return candidates.filter((candidate) => !configured.has(candidate.id));
+}
+
+interface SetupFreeProviderConnectionsOptions {
+ requestedIds: string[];
+ candidates: FreeOnboardingProvider[];
+ listExisting: () => Promise;
+ create: (input: FreeProviderConnectionInput) => Promise<{ id?: unknown } | null>;
+}
+
+function validateRequestedIds(
+ requestedIds: string[],
+ candidates: FreeOnboardingProvider[]
+): Map {
+ const candidatesById = new Map(candidates.map((candidate) => [candidate.id, candidate]));
+ const invalidIds = [...new Set(requestedIds)]
+ .filter((providerId) => !candidatesById.has(providerId))
+ .sort((left, right) => left.localeCompare(right));
+ if (invalidIds.length > 0) {
+ throw new Error(`Ineligible free provider IDs: ${invalidIds.join(", ")}`);
+ }
+ return candidatesById;
+}
+
+export async function setupFreeProviderConnections(
+ options: SetupFreeProviderConnectionsOptions
+): Promise<{ results: FreeProviderSetupResult[] }> {
+ const candidatesById = validateRequestedIds(options.requestedIds, options.candidates);
+ const results: FreeProviderSetupResult[] = [];
+
+ for (const providerId of [...new Set(options.requestedIds)]) {
+ const existing = await options.listExisting();
+ if (existing.some((connection) => connection.provider === providerId)) {
+ results.push({ providerId, status: "skipped", reason: "already-configured" });
+ continue;
+ }
+
+ const candidate = candidatesById.get(providerId)!;
+ try {
+ const connection = await options.create({
+ provider: providerId,
+ authType: "no-auth",
+ name: candidate.name,
+ isActive: true,
+ testStatus: "unknown",
+ ...(candidate.defaultModel ? { defaultModel: candidate.defaultModel } : {}),
+ });
+ if (!connection || typeof connection.id !== "string") {
+ throw new Error("Provider connection was not persisted");
+ }
+ results.push({ providerId, status: "created", connectionId: connection.id });
+ } catch {
+ results.push({ providerId, status: "failed", reason: "Failed to create provider" });
+ }
+ }
+
+ return { results };
+}
+
+let freeProviderSetupQueue: Promise = Promise.resolve();
+
+export async function withFreeProviderSetupLock(operation: () => Promise): Promise {
+ const previous = freeProviderSetupQueue;
+ let release: () => void = () => {};
+ freeProviderSetupQueue = new Promise((resolve) => {
+ release = resolve;
+ });
+ await previous;
+ try {
+ return await operation();
+ } finally {
+ release();
+ }
+}
diff --git a/tests/unit/free-provider-onboarding-selector.test.ts b/tests/unit/free-provider-onboarding-selector.test.ts
new file mode 100644
index 0000000000..3bd45bc50f
--- /dev/null
+++ b/tests/unit/free-provider-onboarding-selector.test.ts
@@ -0,0 +1,43 @@
+import assert from "node:assert/strict";
+import test from "node:test";
+
+import {
+ getEligibleFreeOnboardingProviders,
+ selectUnconfiguredFreeOnboardingProviders,
+} from "../../src/lib/providers/freeOnboarding.ts";
+
+test("free onboarding candidates come from the no-auth registry and exclude local/non-LLM entries", () => {
+ const providers = getEligibleFreeOnboardingProviders();
+ const ids = providers.map((provider) => provider.id);
+
+ assert.deepEqual(
+ ids,
+ [...ids].sort((a, b) => a.localeCompare(b))
+ );
+ assert.ok(ids.includes("opencode"));
+ assert.ok(ids.includes("duckduckgo-web"));
+ assert.ok(ids.includes("felo-web"));
+ assert.ok(ids.includes("theoldllm"));
+ assert.ok(ids.includes("chipotle"));
+ assert.ok(ids.includes("mimocode"));
+ assert.ok(ids.includes("aihorde"));
+ assert.ok(!ids.includes("devin-cli-agentic"));
+ assert.ok(!ids.includes("auggie"));
+ assert.ok(!ids.includes("veoaifree-web"));
+ assert.ok(providers.every((provider) => provider.caution.length > 0));
+ assert.ok(providers.every((provider) => provider.website.startsWith("https://")));
+});
+
+test("already configured providers are removed without changing registry candidates", () => {
+ const all = getEligibleFreeOnboardingProviders();
+ const available = selectUnconfiguredFreeOnboardingProviders(all, [
+ { provider: "opencode" },
+ { provider: "openai" },
+ ]);
+
+ assert.ok(!available.some((provider) => provider.id === "opencode"));
+ assert.equal(
+ all.some((provider) => provider.id === "opencode"),
+ true
+ );
+});
diff --git a/tests/unit/free-provider-onboarding-setup.test.ts b/tests/unit/free-provider-onboarding-setup.test.ts
new file mode 100644
index 0000000000..3afdbe8fd7
--- /dev/null
+++ b/tests/unit/free-provider-onboarding-setup.test.ts
@@ -0,0 +1,89 @@
+import assert from "node:assert/strict";
+import test from "node:test";
+
+import {
+ getEligibleFreeOnboardingProviders,
+ setupFreeProviderConnections,
+} from "../../src/lib/providers/freeOnboarding.ts";
+
+test("batch setup creates missing providers, skips existing ones, and is retry-safe", async () => {
+ const existing = [{ provider: "opencode", name: "My customized OpenCode" }];
+ const created: Array<{ provider: string; name: string }> = [];
+ const candidates = getEligibleFreeOnboardingProviders();
+ const requestedIds = ["opencode", "mimocode"];
+
+ const first = await setupFreeProviderConnections({
+ requestedIds,
+ candidates,
+ listExisting: async () => [...existing, ...created],
+ create: async (input) => {
+ created.push({ provider: input.provider, name: input.name });
+ return { id: `created-${input.provider}` };
+ },
+ });
+ const second = await setupFreeProviderConnections({
+ requestedIds,
+ candidates,
+ listExisting: async () => [...existing, ...created],
+ create: async (input) => {
+ created.push({ provider: input.provider, name: input.name });
+ return { id: `created-${input.provider}` };
+ },
+ });
+
+ assert.deepEqual(first.results, [
+ { providerId: "opencode", status: "skipped", reason: "already-configured" },
+ { providerId: "mimocode", status: "created", connectionId: "created-mimocode" },
+ ]);
+ assert.deepEqual(second.results, [
+ { providerId: "opencode", status: "skipped", reason: "already-configured" },
+ { providerId: "mimocode", status: "skipped", reason: "already-configured" },
+ ]);
+ assert.deepEqual(existing, [{ provider: "opencode", name: "My customized OpenCode" }]);
+ assert.deepEqual(created, [{ provider: "mimocode", name: "MiMoCode (Free)" }]);
+});
+
+test("batch setup rejects unknown or ineligible IDs before creating anything", async () => {
+ let createCalls = 0;
+
+ await assert.rejects(
+ setupFreeProviderConnections({
+ requestedIds: ["openai", "missing-provider"],
+ candidates: getEligibleFreeOnboardingProviders(),
+ listExisting: async () => [],
+ create: async () => {
+ createCalls += 1;
+ return { id: "unexpected" };
+ },
+ }),
+ /Ineligible free provider IDs: missing-provider, openai/
+ );
+ assert.equal(createCalls, 0);
+});
+
+test("partial failures are reported per provider and can be retried", async () => {
+ const created = new Set();
+ let mimocodeAttempts = 0;
+ const input = {
+ requestedIds: ["opencode", "mimocode"],
+ candidates: getEligibleFreeOnboardingProviders(),
+ listExisting: async () => [...created].map((provider) => ({ provider })),
+ create: async ({ provider }: { provider: string }) => {
+ if (provider === "mimocode" && mimocodeAttempts++ === 0) throw new Error("upstream detail");
+ created.add(provider);
+ return { id: `created-${provider}` };
+ },
+ };
+
+ const first = await setupFreeProviderConnections(input);
+ const retry = await setupFreeProviderConnections(input);
+
+ assert.deepEqual(first.results, [
+ { providerId: "opencode", status: "created", connectionId: "created-opencode" },
+ { providerId: "mimocode", status: "failed", reason: "Failed to create provider" },
+ ]);
+ assert.deepEqual(retry.results, [
+ { providerId: "opencode", status: "skipped", reason: "already-configured" },
+ { providerId: "mimocode", status: "created", connectionId: "created-mimocode" },
+ ]);
+});
diff --git a/tests/unit/ui/free-provider-onboarding.test.tsx b/tests/unit/ui/free-provider-onboarding.test.tsx
new file mode 100644
index 0000000000..1d43eaa68f
--- /dev/null
+++ b/tests/unit/ui/free-provider-onboarding.test.tsx
@@ -0,0 +1,128 @@
+// @vitest-environment jsdom
+import React, { act } from "react";
+import { createRoot, type Root } from "react-dom/client";
+import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
+
+const translate = (key: string) => key;
+
+vi.mock("next-intl", () => ({
+ useTranslations: () => translate,
+}));
+
+describe("FreeProviderOnboardingCard", () => {
+ let container: HTMLDivElement;
+ let root: Root;
+
+ beforeEach(() => {
+ container = document.createElement("div");
+ document.body.appendChild(container);
+ root = createRoot(container);
+ vi.stubGlobal(
+ "fetch",
+ vi.fn().mockResolvedValue({
+ ok: true,
+ json: async () => ({
+ providers: [
+ {
+ id: "opencode",
+ name: "OpenCode Free",
+ website: "https://opencode.ai",
+ caution: "Public endpoint. Rate limits apply.",
+ defaultModel: "big-pickle",
+ },
+ ],
+ }),
+ })
+ );
+ (
+ globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
+ ).IS_REACT_ACT_ENVIRONMENT = true;
+ });
+
+ afterEach(async () => {
+ await act(async () => root.unmount());
+ container.remove();
+ vi.unstubAllGlobals();
+ vi.clearAllMocks();
+ });
+
+ it("shows caution metadata and requires explicit confirmation before setup", async () => {
+ const { FreeProviderOnboardingCard } =
+ await import("../../../src/app/(dashboard)/dashboard/onboarding/steps/FreeProviderOnboardingCard");
+
+ await act(async () => root.render( ));
+ await act(async () => Promise.resolve());
+
+ expect(container.textContent).toContain("OpenCode Free");
+ expect(container.textContent).toContain("Public endpoint. Rate limits apply.");
+ expect(container.querySelector('a[href="https://opencode.ai"]')).not.toBeNull();
+
+ const setupButton = container.querySelector(
+ '[data-testid="setup-free-providers"]'
+ );
+ expect(setupButton?.disabled).toBe(true);
+
+ const confirmation = container.querySelector(
+ '[data-testid="free-provider-confirmation"]'
+ );
+ await act(async () => confirmation?.click());
+ expect(setupButton?.disabled).toBe(false);
+ });
+
+ it("posts selected IDs only after confirmation and renders partial results for retry", async () => {
+ const fetchMock = vi.mocked(fetch);
+ fetchMock
+ .mockResolvedValueOnce({
+ ok: true,
+ json: async () => ({
+ providers: [
+ {
+ id: "opencode",
+ name: "OpenCode Free",
+ website: "https://opencode.ai",
+ caution: "Rate limits apply.",
+ },
+ {
+ id: "mimocode",
+ name: "MiMoCode",
+ website: "https://mimo.mi.com",
+ caution: "Bootstrap authentication.",
+ },
+ ],
+ }),
+ } as Response)
+ .mockResolvedValueOnce({
+ ok: true,
+ json: async () => ({
+ results: [
+ { providerId: "opencode", status: "created", connectionId: "one" },
+ { providerId: "mimocode", status: "failed", reason: "Failed to create provider" },
+ ],
+ }),
+ } as Response);
+ const { FreeProviderOnboardingCard } =
+ await import("../../../src/app/(dashboard)/dashboard/onboarding/steps/FreeProviderOnboardingCard");
+
+ await act(async () => root.render( ));
+ await act(async () => Promise.resolve());
+ await act(async () =>
+ container
+ .querySelector('[data-testid="free-provider-confirmation"]')
+ ?.click()
+ );
+ await act(async () =>
+ container.querySelector('[data-testid="setup-free-providers"]')?.click()
+ );
+
+ expect(fetchMock).toHaveBeenLastCalledWith(
+ "/api/providers/free-onboarding",
+ expect.objectContaining({
+ method: "POST",
+ body: JSON.stringify({ providerIds: ["mimocode", "opencode"], confirmed: true }),
+ })
+ );
+ expect(container.textContent).toContain("result.created");
+ expect(container.textContent).toContain("result.failed");
+ expect(container.textContent).toContain("retryFailed");
+ });
+});