feat(tts): add Xiaomi MiMo text-to-speech support
Adds mimo-v2.5-tts as a Media Provider TTS through the existing OpenAI-compatible chat-completions endpoint. Voice is selected via the top-level audio.voice field, and an optional style/language hint is threaded through tts.js -> ttsCore.js -> the new adapter.
This commit is contained in:
parent
d0751bcff7
commit
c570fe33ae
44 changed files with 396 additions and 20 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
# v0.5.45 (2026-07-30)
|
# v0.5.45 (2026-07-30)
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
- **TTS**: add Xiaomi MiMo text-to-speech (preset voices 冰糖/茉莉/苏打/白桦/Mia/Chloe/Milo/Dean, style control, language hint dropdown with Auto-detect, i18n for Style label/placeholder)
|
||||||
- **Providers**: add Poolside (OpenAI-compatible)
|
- **Providers**: add Poolside (OpenAI-compatible)
|
||||||
- **Providers**: add api-airforce, baidu, bazaarlink, bluesminds, kilo-gateway, llm7, morph, sambanova, tencent
|
- **Providers**: add api-airforce, baidu, bazaarlink, bluesminds, kilo-gateway, llm7, morph, sambanova, tencent
|
||||||
- **OAuth**: zed / trae / windsurf providers + harden callback proxies
|
- **OAuth**: zed / trae / windsurf providers + harden callback proxies
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,21 @@ const GEMINI_VOICES = [
|
||||||
"Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat",
|
"Vindemiatrix", "Sadachbia", "Sadaltager", "Sulafat",
|
||||||
].map((id) => ({ id, name: id, type: "tts" }));
|
].map((id) => ({ id, name: id, type: "tts" }));
|
||||||
|
|
||||||
|
// Xiaomi MiMo preset voices (from https://mimo.mi.com/docs/zh-CN/quick-start/usage-guide/audio/speech-synthesis-v2.5).
|
||||||
|
// Voice id is passed via `audio.voice`; `mimo_default` = default (冰糖 on CN cluster, Mia elsewhere).
|
||||||
|
// Voices are language-independent — the spoken language is a separate hint, not bound to the voice.
|
||||||
|
const MIMO_VOICES = [
|
||||||
|
{ id: "mimo_default", name: "mimo_default" },
|
||||||
|
{ id: "冰糖", name: "冰糖" },
|
||||||
|
{ id: "茉莉", name: "茉莉" },
|
||||||
|
{ id: "苏打", name: "苏打" },
|
||||||
|
{ id: "白桦", name: "白桦" },
|
||||||
|
{ id: "Mia", name: "Mia" },
|
||||||
|
{ id: "Chloe", name: "Chloe" },
|
||||||
|
{ id: "Milo", name: "Milo" },
|
||||||
|
{ id: "Dean", name: "Dean" },
|
||||||
|
].map((v) => ({ type: "tts", ...v }));
|
||||||
|
|
||||||
// ── TTS Config (config-driven, single source of truth) ─────────────────────
|
// ── TTS Config (config-driven, single source of truth) ─────────────────────
|
||||||
export const TTS_MODELS_CONFIG = {
|
export const TTS_MODELS_CONFIG = {
|
||||||
openai: {
|
openai: {
|
||||||
|
|
@ -107,6 +122,14 @@ export const TTS_MODELS_CONFIG = {
|
||||||
},
|
},
|
||||||
allVoices: GEMINI_VOICES,
|
allVoices: GEMINI_VOICES,
|
||||||
},
|
},
|
||||||
|
"xiaomi-mimo": {
|
||||||
|
models: [
|
||||||
|
{ id: "mimo-v2.5-tts", name: "MiMo V2.5 TTS", type: "tts" },
|
||||||
|
],
|
||||||
|
voices: {
|
||||||
|
"mimo-v2.5-tts": MIMO_VOICES,
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// ── Helper: get voices for a specific model ────────────────────────────────
|
// ── Helper: get voices for a specific model ────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -48,16 +48,16 @@ function createTtsResponse(base64Audio, format, responseFormat) {
|
||||||
*
|
*
|
||||||
* @returns {Promise<{success, response, status?, error?}>}
|
* @returns {Promise<{success, response, status?, error?}>}
|
||||||
*/
|
*/
|
||||||
export async function handleTtsCore({ provider, model, input, credentials, responseFormat = "mp3", language }) {
|
export async function handleTtsCore({ provider, model, input, credentials, responseFormat = "mp3", language, style }) {
|
||||||
if (!input?.trim()) {
|
if (!input?.trim()) {
|
||||||
return createErrorResult(HTTP_STATUS.BAD_REQUEST, "Missing required field: input");
|
return createErrorResult(HTTP_STATUS.BAD_REQUEST, "Missing required field: input");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Special-case adapters (google-tts, edge-tts, local-device, elevenlabs, openai, openrouter, gemini)
|
// Special-case adapters (google-tts, edge-tts, local-device, elevenlabs, openai, openrouter, gemini, xiaomi-mimo)
|
||||||
const adapter = getTtsAdapter(provider);
|
const adapter = getTtsAdapter(provider);
|
||||||
if (adapter) {
|
if (adapter) {
|
||||||
const result = await adapter.synthesize(input.trim(), model, credentials, responseFormat, { language });
|
const result = await adapter.synthesize(input.trim(), model, credentials, responseFormat, { language, style });
|
||||||
// Adapter may return a full {success, response} (legacy) or {base64, format}
|
// Adapter may return a full {success, response} (legacy) or {base64, format}
|
||||||
if (result.success !== undefined) return result;
|
if (result.success !== undefined) return result;
|
||||||
return createTtsResponse(result.base64, result.format, responseFormat);
|
return createTtsResponse(result.base64, result.format, responseFormat);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import elevenlabs, { fetchElevenLabsVoices } from "./elevenlabs.js";
|
||||||
import openai from "./openai.js";
|
import openai from "./openai.js";
|
||||||
import openrouter from "./openrouter.js";
|
import openrouter from "./openrouter.js";
|
||||||
import gemini, { fetchGeminiVoices } from "./gemini.js";
|
import gemini, { fetchGeminiVoices } from "./gemini.js";
|
||||||
|
import xiaomiMimo from "./xiaomi-mimo.js";
|
||||||
import { FORMAT_HANDLERS } from "./genericFormats.js";
|
import { FORMAT_HANDLERS } from "./genericFormats.js";
|
||||||
import { parseModelVoice } from "./_base.js";
|
import { parseModelVoice } from "./_base.js";
|
||||||
|
|
||||||
|
|
@ -18,6 +19,7 @@ const SPECIAL_ADAPTERS = {
|
||||||
openai,
|
openai,
|
||||||
openrouter,
|
openrouter,
|
||||||
gemini,
|
gemini,
|
||||||
|
"xiaomi-mimo": xiaomiMimo,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getTtsAdapter(provider) {
|
export function getTtsAdapter(provider) {
|
||||||
|
|
|
||||||
65
open-sse/handlers/ttsProviders/xiaomi-mimo.js
Normal file
65
open-sse/handlers/ttsProviders/xiaomi-mimo.js
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
// Xiaomi MiMo TTS — via OpenAI-compatible chat completions (non-streaming).
|
||||||
|
// Docs: https://mimo.mi.com/docs/zh-CN/quick-start/usage-guide/audio/speech-synthesis-v2.5
|
||||||
|
// Message contract: target text in `role: assistant` content, style/voice
|
||||||
|
// instructions in `role: user` content. Voice is selected via the top-level
|
||||||
|
// `audio.voice` field (NOT embedded in the model name).
|
||||||
|
import { parseModelVoice } from "./_base.js";
|
||||||
|
|
||||||
|
const DEFAULT_MODEL = "mimo-v2.5-tts";
|
||||||
|
const DEFAULT_VOICE = "mimo_default";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
synthesize(text, model, credentials, responseFormat, { style, language } = {}) {
|
||||||
|
if (!credentials?.apiKey) throw new Error("xiaomi-mimo API key required");
|
||||||
|
return synthesizeMiMo(text, model, credentials.apiKey, style, language);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function synthesizeMiMo(text, model, apiKey, style, language) {
|
||||||
|
const { modelId, voiceId } = parseModelVoice(model, DEFAULT_MODEL, DEFAULT_VOICE, [DEFAULT_MODEL]);
|
||||||
|
|
||||||
|
// Language and style are soft instructions → prepend as a role:user message.
|
||||||
|
// MiMo auto-detects the spoken language of the text; the hint only nudges it
|
||||||
|
// (e.g. "Speak in English.") and is independent of the chosen voice.
|
||||||
|
const instructions = [];
|
||||||
|
if (language) instructions.push(`Speak in ${language}.`);
|
||||||
|
if (style) instructions.push(style);
|
||||||
|
|
||||||
|
const messages = [{ role: "assistant", content: text }];
|
||||||
|
if (instructions.length) messages.unshift({ role: "user", content: instructions.join(" ") });
|
||||||
|
|
||||||
|
const res = await fetch("https://api.xiaomimimo.com/v1/chat/completions", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Authorization": `Bearer ${apiKey}`,
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: modelId,
|
||||||
|
stream: false,
|
||||||
|
messages,
|
||||||
|
audio: {
|
||||||
|
format: "wav",
|
||||||
|
voice: voiceId || DEFAULT_VOICE,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const rawText = await res.text();
|
||||||
|
let data = {};
|
||||||
|
if (rawText) {
|
||||||
|
try { data = JSON.parse(rawText); } catch { data = {}; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(data?.error?.message || rawText || `MiMo TTS error (${res.status})`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const audio = data?.choices?.[0]?.message?.audio?.data;
|
||||||
|
if (!audio) throw new Error(data?.error?.message || "MiMo TTS returned no audio");
|
||||||
|
|
||||||
|
return {
|
||||||
|
base64: audio,
|
||||||
|
format: data?.choices?.[0]?.message?.audio?.format || "wav",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -15,10 +15,11 @@ export default {
|
||||||
textIcon: "XM",
|
textIcon: "XM",
|
||||||
website: "https://xiaomimimo.com",
|
website: "https://xiaomimimo.com",
|
||||||
notice: {
|
notice: {
|
||||||
apiKeyUrl: "https://xiaomimimo.com",
|
apiKeyUrl: "https://platform.xiaomimimo.com/console/api-keys",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
category: "apikey",
|
category: "apikey",
|
||||||
|
serviceKinds: ["llm", "tts"],
|
||||||
transport: {
|
transport: {
|
||||||
baseUrl: "https://api.xiaomimimo.com/v1/chat/completions",
|
baseUrl: "https://api.xiaomimimo.com/v1/chat/completions",
|
||||||
validateUrl: "https://api.xiaomimimo.com/v1/models",
|
validateUrl: "https://api.xiaomimimo.com/v1/models",
|
||||||
|
|
@ -42,5 +43,12 @@ export default {
|
||||||
{ id: "mimo-v2.5", name: "MiMo V2.5" },
|
{ id: "mimo-v2.5", name: "MiMo V2.5" },
|
||||||
{ id: "mimo-v2-omni", name: "MiMo V2 Omni" },
|
{ id: "mimo-v2-omni", name: "MiMo V2 Omni" },
|
||||||
{ id: "mimo-v2-flash", name: "MiMo V2 Flash" },
|
{ id: "mimo-v2-flash", name: "MiMo V2 Flash" },
|
||||||
|
{ id: "mimo-v2.5-tts", name: "MiMo V2.5 TTS", kind: "tts" },
|
||||||
],
|
],
|
||||||
|
ttsConfig: {
|
||||||
|
baseUrl: "https://api.xiaomimimo.com/v1/chat/completions",
|
||||||
|
authType: "apikey",
|
||||||
|
authHeader: "bearer",
|
||||||
|
format: "xiaomi-mimo-tts",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "تسجيل الخروج",
|
"Logout": "تسجيل الخروج",
|
||||||
"Login": "تسجيل الدخول",
|
"Login": "تسجيل الدخول",
|
||||||
"Providers": "الموفرون",
|
"Providers": "الموفرون",
|
||||||
|
"Style": "النمط",
|
||||||
"Usage": "الإحصائيات",
|
"Usage": "الإحصائيات",
|
||||||
"API Key": "مفتاح API",
|
"API Key": "مفتاح API",
|
||||||
"Connected": "متصل",
|
"Connected": "متصل",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "كيف يعمل:",
|
"How it works:": "كيف يعمل:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "طلب Antigravity/Copilot IDE → إعادة توجيه DNS إلى localhost:443 → يعترض وكيل MITM → 9Router → الرد إلى Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "طلب Antigravity/Copilot IDE → إعادة توجيه DNS إلى localhost:443 → يعترض وكيل MITM → 9Router → الرد إلى Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "لا توجد مفاتيح API — قم بإنشاء واحدة في صفحة المفاتيح",
|
"No API keys — create one in Keys page": "لا توجد مفاتيح API — قم بإنشاء واحدة في صفحة المفاتيح",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "مثال: صوت دافئ ولطيف، يتحدث ببطء بلهجة بريطانية",
|
||||||
"sk_9router (default)": "sk_9router (افتراضي)",
|
"sk_9router (default)": "sk_9router (افتراضي)",
|
||||||
"Server started": "تم بدء الخادم",
|
"Server started": "تم بدء الخادم",
|
||||||
"Failed to start server": "فشل في بدء الخادم",
|
"Failed to start server": "فشل في بدء الخادم",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "লগ আউট",
|
"Logout": "লগ আউট",
|
||||||
"Login": "লগ ইন",
|
"Login": "লগ ইন",
|
||||||
"Providers": "সরবরাহকারী",
|
"Providers": "সরবরাহকারী",
|
||||||
|
"Style": "শৈলী",
|
||||||
"Usage": "ব্যবহারের পরিসংখ্যান",
|
"Usage": "ব্যবহারের পরিসংখ্যান",
|
||||||
"API Key": "API কী",
|
"API Key": "API কী",
|
||||||
"Connected": "সংযুক্ত",
|
"Connected": "সংযুক্ত",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "এটি কীভাবে কাজ করে:",
|
"How it works:": "এটি কীভাবে কাজ করে:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE অনুরোধ → DNS কে localhost:443 তে রিডিরেক্ট করুন → MITM প্রক্সি ইন্টারসেপ্ট করে → 9Router → Antigravity/Copilot এ প্রতিক্রিয়া",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE অনুরোধ → DNS কে localhost:443 তে রিডিরেক্ট করুন → MITM প্রক্সি ইন্টারসেপ্ট করে → 9Router → Antigravity/Copilot এ প্রতিক্রিয়া",
|
||||||
"No API keys — create one in Keys page": "কোন API কী নেই — Keys পৃষ্ঠায় একটি তৈরি করুন",
|
"No API keys — create one in Keys page": "কোন API কী নেই — Keys পৃষ্ঠায় একটি তৈরি করুন",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "যেমন: উষ্ণ, মৃদু কণ্ঠস্বর, ব্রিটিশ উচ্চারণে ধীরে ধীরে কথা বলা",
|
||||||
"sk_9router (default)": "sk_9router (ডিফল্ট)",
|
"sk_9router (default)": "sk_9router (ডিফল্ট)",
|
||||||
"Server started": "সার্ভার শুরু হয়েছে",
|
"Server started": "সার্ভার শুরু হয়েছে",
|
||||||
"Failed to start server": "সার্ভার শুরু করতে ব্যর্থ",
|
"Failed to start server": "সার্ভার শুরু করতে ব্যর্থ",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Odhlásit se",
|
"Logout": "Odhlásit se",
|
||||||
"Login": "Přihlásit se",
|
"Login": "Přihlásit se",
|
||||||
"Providers": "Poskytovatelé",
|
"Providers": "Poskytovatelé",
|
||||||
|
"Style": "Styl",
|
||||||
"Usage": "Statistika",
|
"Usage": "Statistika",
|
||||||
"API Key": "Klíč API",
|
"API Key": "Klíč API",
|
||||||
"Connected": "Připojeno",
|
"Connected": "Připojeno",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Jak to funguje:",
|
"How it works:": "Jak to funguje:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Požadavek Antigravity/Copilot IDE → Přesměrování DNS na localhost:443 → Proxy MITM zachycuje → 9Router → odpověď na Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Požadavek Antigravity/Copilot IDE → Přesměrování DNS na localhost:443 → Proxy MITM zachycuje → 9Router → odpověď na Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Žádné klíče API — vytvořte jeden na stránce Klíče",
|
"No API keys — create one in Keys page": "Žádné klíče API — vytvořte jeden na stránce Klíče",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "např.: teplý, jemný hlas, mluvící pomalu s britským přízvukem",
|
||||||
"sk_9router (default)": "sk_9router (výchozí)",
|
"sk_9router (default)": "sk_9router (výchozí)",
|
||||||
"Server started": "Server spuštěn",
|
"Server started": "Server spuštěn",
|
||||||
"Failed to start server": "Spuštění serveru se nezdařilo",
|
"Failed to start server": "Spuštění serveru se nezdařilo",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Log ud",
|
"Logout": "Log ud",
|
||||||
"Login": "Log ind",
|
"Login": "Log ind",
|
||||||
"Providers": "Udbydere",
|
"Providers": "Udbydere",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Forbrugsstatistik",
|
"Usage": "Forbrugsstatistik",
|
||||||
"API Key": "API-nøgle",
|
"API Key": "API-nøgle",
|
||||||
"Connected": "Forbundet",
|
"Connected": "Forbundet",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Sådan virker det:",
|
"How it works:": "Sådan virker det:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-anmodning → DNS-omdirigering til localhost:443 → MITM-proxy aflytter → 9Router → svar til Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-anmodning → DNS-omdirigering til localhost:443 → MITM-proxy aflytter → 9Router → svar til Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Ingen API-nøgler — opret en på Keys-siden",
|
"No API keys — create one in Keys page": "Ingen API-nøgler — opret en på Keys-siden",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "fx.: en varm, blød stemme, der taler langsomt med britisk accent",
|
||||||
"sk_9router (default)": "sk_9router (standard)",
|
"sk_9router (default)": "sk_9router (standard)",
|
||||||
"Server started": "Server startet",
|
"Server started": "Server startet",
|
||||||
"Failed to start server": "Fejl ved start af server",
|
"Failed to start server": "Fejl ved start af server",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Abmelden",
|
"Logout": "Abmelden",
|
||||||
"Login": "Anmelden",
|
"Login": "Anmelden",
|
||||||
"Providers": "Anbieter",
|
"Providers": "Anbieter",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Statistiken",
|
"Usage": "Statistiken",
|
||||||
"API Key": "API-Schlüssel",
|
"API Key": "API-Schlüssel",
|
||||||
"Connected": "Verbunden",
|
"Connected": "Verbunden",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "So funktioniert es:",
|
"How it works:": "So funktioniert es:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-Anforderung → DNS-Umleitung auf localhost:443 → MITM-Proxy abfangen → 9Router → Antwort auf Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-Anforderung → DNS-Umleitung auf localhost:443 → MITM-Proxy abfangen → 9Router → Antwort auf Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Keine API-Schlüssel — erstellen Sie einen auf der Seite Schlüssel",
|
"No API keys — create one in Keys page": "Keine API-Schlüssel — erstellen Sie einen auf der Seite Schlüssel",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "z. B.: eine warme, sanfte Stimme, die langsam mit britischem Akzent spricht",
|
||||||
"sk_9router (default)": "sk_9router (Standard)",
|
"sk_9router (default)": "sk_9router (Standard)",
|
||||||
"Server started": "Server gestartet",
|
"Server started": "Server gestartet",
|
||||||
"Failed to start server": "Server konnte nicht gestartet werden",
|
"Failed to start server": "Server konnte nicht gestartet werden",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Έξοδος",
|
"Logout": "Έξοδος",
|
||||||
"Login": "Σύνδεση",
|
"Login": "Σύνδεση",
|
||||||
"Providers": "Παρόχοι",
|
"Providers": "Παρόχοι",
|
||||||
|
"Style": "Στυλ",
|
||||||
"Usage": "Στατιστικά χρήσης",
|
"Usage": "Στατιστικά χρήσης",
|
||||||
"API Key": "Κλειδί API",
|
"API Key": "Κλειδί API",
|
||||||
"Connected": "Συνδεδεμένο",
|
"Connected": "Συνδεδεμένο",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Πώς λειτουργεί:",
|
"How it works:": "Πώς λειτουργεί:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Αίτημα Antigravity/Copilot IDE → Ανακατεύθυνση DNS στο localhost:443 → Ο διακομιστής μεσολάβησης MITM παρεμβαίνει → 9Router → απάντηση στο Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Αίτημα Antigravity/Copilot IDE → Ανακατεύθυνση DNS στο localhost:443 → Ο διακομιστής μεσολάβησης MITM παρεμβαίνει → 9Router → απάντηση στο Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Δεν υπάρχουν κλειδιά API — δημιουργήστε ένα στη σελίδα Keys",
|
"No API keys — create one in Keys page": "Δεν υπάρχουν κλειδιά API — δημιουργήστε ένα στη σελίδα Keys",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "π.χ.: μια ζεστή, απαλή φωνή, που μιλάει αργά με βρετανική προφορά",
|
||||||
"sk_9router (default)": "sk_9router (προεπιλεγμένο)",
|
"sk_9router (default)": "sk_9router (προεπιλεγμένο)",
|
||||||
"Server started": "Ο διακομιστής ξεκίνησε",
|
"Server started": "Ο διακομιστής ξεκίνησε",
|
||||||
"Failed to start server": "Αποτυχία εκκίνησης διακομιστή",
|
"Failed to start server": "Αποτυχία εκκίνησης διακομιστή",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Cerrar sesión",
|
"Logout": "Cerrar sesión",
|
||||||
"Login": "Iniciar sesión",
|
"Login": "Iniciar sesión",
|
||||||
"Providers": "Proveedores",
|
"Providers": "Proveedores",
|
||||||
|
"Style": "Estilo",
|
||||||
"Usage": "Estadísticas",
|
"Usage": "Estadísticas",
|
||||||
"API Key": "Clave API",
|
"API Key": "Clave API",
|
||||||
"Connected": "Conectado",
|
"Connected": "Conectado",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Cómo funciona:",
|
"How it works:": "Cómo funciona:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Solicitud de Antigravity/Copilot IDE → Redireccionamiento DNS a localhost:443 → El proxy MITM intercepta → 9Router → respuesta a Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Solicitud de Antigravity/Copilot IDE → Redireccionamiento DNS a localhost:443 → El proxy MITM intercepta → 9Router → respuesta a Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Sin claves API — cree una en la página Claves",
|
"No API keys — create one in Keys page": "Sin claves API — cree una en la página Claves",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "p. ej.: voz cálida y suave, hablando lentamente con acento británico",
|
||||||
"sk_9router (default)": "sk_9router (predeterminado)",
|
"sk_9router (default)": "sk_9router (predeterminado)",
|
||||||
"Server started": "Servidor iniciado",
|
"Server started": "Servidor iniciado",
|
||||||
"Failed to start server": "Error al iniciar el servidor",
|
"Failed to start server": "Error al iniciar el servidor",
|
||||||
|
|
|
||||||
|
|
@ -1119,6 +1119,7 @@
|
||||||
"Stop Server": "توقف سرور",
|
"Stop Server": "توقف سرور",
|
||||||
"Stopped": "متوقف شد",
|
"Stopped": "متوقف شد",
|
||||||
"Strict Proxy": "پروکسی سختگیرانه",
|
"Strict Proxy": "پروکسی سختگیرانه",
|
||||||
|
"Style": "سبک",
|
||||||
"Subagent Model": "مدل زیرعامل",
|
"Subagent Model": "مدل زیرعامل",
|
||||||
"Sudo Password Required": "رمز عبور sudo الزامی است",
|
"Sudo Password Required": "رمز عبور sudo الزامی است",
|
||||||
"Sudo password is required": "رمز عبور sudo الزامی است",
|
"Sudo password is required": "رمز عبور sudo الزامی است",
|
||||||
|
|
@ -1312,6 +1313,7 @@
|
||||||
"disabled": "غیرفعال",
|
"disabled": "غیرفعال",
|
||||||
"dollars per million tokens": "دلار به ازای هر میلیون توکن",
|
"dollars per million tokens": "دلار به ازای هر میلیون توکن",
|
||||||
"e.g. CwhRBWXzGAHq8TQ4Fs17": "مثلاً CwhRBWXzGAHq8TQ4Fs17",
|
"e.g. CwhRBWXzGAHq8TQ4Fs17": "مثلاً CwhRBWXzGAHq8TQ4Fs17",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "مثلاً: صدای گرم و ملایم که با لهجه بریتانیایی بهآرامی صحبت میکند",
|
||||||
"e.g. claude-opus-4-5": "مثلاً claude-opus-4-5",
|
"e.g. claude-opus-4-5": "مثلاً claude-opus-4-5",
|
||||||
"e.g. my-model-id": "مثلاً my-model-id",
|
"e.g. my-model-id": "مثلاً my-model-id",
|
||||||
"e.g. tts-1-hd": "مثلاً tts-1-hd",
|
"e.g. tts-1-hd": "مثلاً tts-1-hd",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Kirjaudu ulos",
|
"Logout": "Kirjaudu ulos",
|
||||||
"Login": "Kirjaudu sisään",
|
"Login": "Kirjaudu sisään",
|
||||||
"Providers": "Palveluntarjoajat",
|
"Providers": "Palveluntarjoajat",
|
||||||
|
"Style": "Tyyli",
|
||||||
"Usage": "Käyttötilastot",
|
"Usage": "Käyttötilastot",
|
||||||
"API Key": "API-avain",
|
"API Key": "API-avain",
|
||||||
"Connected": "Yhdistetty",
|
"Connected": "Yhdistetty",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Kuinka se toimii:",
|
"How it works:": "Kuinka se toimii:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-pyyntö → DNS-uudelleenohjaus localhost:443:iin → MITM-välityspalvelin sieppaa → 9Router → vastaus Antigravity/Copilot:ille",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-pyyntö → DNS-uudelleenohjaus localhost:443:iin → MITM-välityspalvelin sieppaa → 9Router → vastaus Antigravity/Copilot:ille",
|
||||||
"No API keys — create one in Keys page": "Ei API-avaimia — luo yksi Keys-sivulla",
|
"No API keys — create one in Keys page": "Ei API-avaimia — luo yksi Keys-sivulla",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "esim.: lämmin, pehmeä ääni, joka puhuu hitaasti brittiaksentilla",
|
||||||
"sk_9router (default)": "sk_9router (oletus)",
|
"sk_9router (default)": "sk_9router (oletus)",
|
||||||
"Server started": "Palvelin käynnistetty",
|
"Server started": "Palvelin käynnistetty",
|
||||||
"Failed to start server": "Palvelimen käynnistäminen epäonnistui",
|
"Failed to start server": "Palvelimen käynnistäminen epäonnistui",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Déconnexion",
|
"Logout": "Déconnexion",
|
||||||
"Login": "Connexion",
|
"Login": "Connexion",
|
||||||
"Providers": "Fournisseurs",
|
"Providers": "Fournisseurs",
|
||||||
|
"Style": "Style",
|
||||||
"Usage": "Statistiques",
|
"Usage": "Statistiques",
|
||||||
"API Key": "Clé API",
|
"API Key": "Clé API",
|
||||||
"Connected": "Connecté",
|
"Connected": "Connecté",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Comment ça marche :",
|
"How it works:": "Comment ça marche :",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Demande Antigravity/Copilot IDE → Redirection DNS vers localhost:443 → Le proxy MITM intercepte → 9Router → réponse à Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Demande Antigravity/Copilot IDE → Redirection DNS vers localhost:443 → Le proxy MITM intercepte → 9Router → réponse à Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Aucune clé API — créez-en une dans la page Clés",
|
"No API keys — create one in Keys page": "Aucune clé API — créez-en une dans la page Clés",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "ex. : voix chaleureuse et douce, parlant lentement avec un accent britannique",
|
||||||
"sk_9router (default)": "sk_9router (par défaut)",
|
"sk_9router (default)": "sk_9router (par défaut)",
|
||||||
"Server started": "Serveur démarré",
|
"Server started": "Serveur démarré",
|
||||||
"Failed to start server": "Impossible de démarrer le serveur",
|
"Failed to start server": "Impossible de démarrer le serveur",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "התנתקות",
|
"Logout": "התנתקות",
|
||||||
"Login": "כניסה",
|
"Login": "כניסה",
|
||||||
"Providers": "ספקים",
|
"Providers": "ספקים",
|
||||||
|
"Style": "סגנון",
|
||||||
"Usage": "סטטיסטיקה",
|
"Usage": "סטטיסטיקה",
|
||||||
"API Key": "מפתח API",
|
"API Key": "מפתח API",
|
||||||
"Connected": "מחובר",
|
"Connected": "מחובר",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "איך זה עובד:",
|
"How it works:": "איך זה עובד:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "בקשת Antigravity/Copilot IDE → הפניה DNS ל-localhost:443 → פרוקסי MITM חוטף → 9Router → תגובה ל-Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "בקשת Antigravity/Copilot IDE → הפניה DNS ל-localhost:443 → פרוקסי MITM חוטף → 9Router → תגובה ל-Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "אין מפתחות API — צור אחד בעמוד Keys",
|
"No API keys — create one in Keys page": "אין מפתחות API — צור אחד בעמוד Keys",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "למשל: קול חם ועדין, מדבר לאט במבטא בריטי",
|
||||||
"sk_9router (default)": "sk_9router (ברירת מחדל)",
|
"sk_9router (default)": "sk_9router (ברירת מחדל)",
|
||||||
"Server started": "השרת התחיל",
|
"Server started": "השרת התחיל",
|
||||||
"Failed to start server": "הפעלת השרת נכשלה",
|
"Failed to start server": "הפעלת השרת נכשלה",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "लॉग आउट",
|
"Logout": "लॉग आउट",
|
||||||
"Login": "लॉगिन",
|
"Login": "लॉगिन",
|
||||||
"Providers": "प्रदाता",
|
"Providers": "प्रदाता",
|
||||||
|
"Style": "शैली",
|
||||||
"Usage": "उपयोग के आंकड़े",
|
"Usage": "उपयोग के आंकड़े",
|
||||||
"API Key": "API कुंजी",
|
"API Key": "API कुंजी",
|
||||||
"Connected": "जुड़ा हुआ",
|
"Connected": "जुड़ा हुआ",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "यह कैसे काम करता है:",
|
"How it works:": "यह कैसे काम करता है:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE अनुरोध → DNS को localhost:443 में पुनर्निर्देशित करें → MITM प्रॉक्सी इंटरसेप्ट करता है → 9Router → Antigravity/Copilot को प्रतिक्रिया",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE अनुरोध → DNS को localhost:443 में पुनर्निर्देशित करें → MITM प्रॉक्सी इंटरसेप्ट करता है → 9Router → Antigravity/Copilot को प्रतिक्रिया",
|
||||||
"No API keys — create one in Keys page": "कोई API कुंजी नहीं — Keys पृष्ठ में एक बनाएं",
|
"No API keys — create one in Keys page": "कोई API कुंजी नहीं — Keys पृष्ठ में एक बनाएं",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "जैसे: गर्म, कोमल आवाज़, ब्रिटिश लहजे में धीरे-धीरे बोलते हुए",
|
||||||
"sk_9router (default)": "sk_9router (डिफ़ॉल्ट)",
|
"sk_9router (default)": "sk_9router (डिफ़ॉल्ट)",
|
||||||
"Server started": "सर्वर शुरू किया गया",
|
"Server started": "सर्वर शुरू किया गया",
|
||||||
"Failed to start server": "सर्वर शुरू करने में विफल",
|
"Failed to start server": "सर्वर शुरू करने में विफल",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Kijelentkezés",
|
"Logout": "Kijelentkezés",
|
||||||
"Login": "Bejelentkezés",
|
"Login": "Bejelentkezés",
|
||||||
"Providers": "Szolgáltatók",
|
"Providers": "Szolgáltatók",
|
||||||
|
"Style": "Stílus",
|
||||||
"Usage": "Használati statisztika",
|
"Usage": "Használati statisztika",
|
||||||
"API Key": "API-kulcs",
|
"API Key": "API-kulcs",
|
||||||
"Connected": "Csatlakoztatva",
|
"Connected": "Csatlakoztatva",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Hogyan működik:",
|
"How it works:": "Hogyan működik:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE kérés → DNS átirányítás a localhost:443-ra → MITM proxy elfogja → 9Router → válasz Antigravity/Copilot-nak",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE kérés → DNS átirányítás a localhost:443-ra → MITM proxy elfogja → 9Router → válasz Antigravity/Copilot-nak",
|
||||||
"No API keys — create one in Keys page": "Nincsenek API-kulcsok — hozzon létre egyet a Keys oldalon",
|
"No API keys — create one in Keys page": "Nincsenek API-kulcsok — hozzon létre egyet a Keys oldalon",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "pl.: meleg, lágy hang, lassan beszél brit akcentussal",
|
||||||
"sk_9router (default)": "sk_9router (alapértelmezett)",
|
"sk_9router (default)": "sk_9router (alapértelmezett)",
|
||||||
"Server started": "Szerver elindult",
|
"Server started": "Szerver elindult",
|
||||||
"Failed to start server": "Nem sikerült elindítani a szervert",
|
"Failed to start server": "Nem sikerült elindítani a szervert",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Keluar",
|
"Logout": "Keluar",
|
||||||
"Login": "Masuk",
|
"Login": "Masuk",
|
||||||
"Providers": "Penyedia",
|
"Providers": "Penyedia",
|
||||||
|
"Style": "Gaya",
|
||||||
"Usage": "Statistik Penggunaan",
|
"Usage": "Statistik Penggunaan",
|
||||||
"API Key": "Kunci API",
|
"API Key": "Kunci API",
|
||||||
"Connected": "Terhubung",
|
"Connected": "Terhubung",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Cara kerjanya:",
|
"How it works:": "Cara kerjanya:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Permintaan Antigravity/Copilot IDE → Pengalihan DNS ke localhost:443 → Proxy MITM mengintersep → 9Router → respons ke Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Permintaan Antigravity/Copilot IDE → Pengalihan DNS ke localhost:443 → Proxy MITM mengintersep → 9Router → respons ke Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Tidak ada kunci API — buat satu di halaman Keys",
|
"No API keys — create one in Keys page": "Tidak ada kunci API — buat satu di halaman Keys",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "mis.: suara hangat dan lembut, berbicara pelan dengan aksen Inggris",
|
||||||
"sk_9router (default)": "sk_9router (bawaan)",
|
"sk_9router (default)": "sk_9router (bawaan)",
|
||||||
"Server started": "Server dimulai",
|
"Server started": "Server dimulai",
|
||||||
"Failed to start server": "Gagal memulai server",
|
"Failed to start server": "Gagal memulai server",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Esci",
|
"Logout": "Esci",
|
||||||
"Login": "Accedi",
|
"Login": "Accedi",
|
||||||
"Providers": "Provider",
|
"Providers": "Provider",
|
||||||
|
"Style": "Stile",
|
||||||
"Usage": "Statistiche di utilizzo",
|
"Usage": "Statistiche di utilizzo",
|
||||||
"API Key": "Chiave API",
|
"API Key": "Chiave API",
|
||||||
"Connected": "Connesso",
|
"Connected": "Connesso",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Come funziona:",
|
"How it works:": "Come funziona:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Richiesta Antigravity/Copilot IDE → Reindirizzamento DNS a localhost:443 → Il proxy MITM intercetta → 9Router → Risposta a Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Richiesta Antigravity/Copilot IDE → Reindirizzamento DNS a localhost:443 → Il proxy MITM intercetta → 9Router → Risposta a Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Nessuna chiave API — crearne una nella pagina Chiavi",
|
"No API keys — create one in Keys page": "Nessuna chiave API — crearne una nella pagina Chiavi",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "es.: voce calda e morbida, che parla lentamente con accento britannico",
|
||||||
"sk_9router (default)": "sk_9router (predefinito)",
|
"sk_9router (default)": "sk_9router (predefinito)",
|
||||||
"Server started": "Server avviato",
|
"Server started": "Server avviato",
|
||||||
"Failed to start server": "Impossibile avviare il server",
|
"Failed to start server": "Impossibile avviare il server",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "ログアウト",
|
"Logout": "ログアウト",
|
||||||
"Login": "ログイン",
|
"Login": "ログイン",
|
||||||
"Providers": "プロバイダー",
|
"Providers": "プロバイダー",
|
||||||
|
"Style": "スタイル",
|
||||||
"Usage": "統計",
|
"Usage": "統計",
|
||||||
"API Key": "APIキー",
|
"API Key": "APIキー",
|
||||||
"Connected": "接続済み",
|
"Connected": "接続済み",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "しくみ:",
|
"How it works:": "しくみ:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE リクエスト → localhost:443 への DNS リダイレクト → MITM プロキシが傍受 → 9Router → Antigravity/Copilot への応答",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE リクエスト → localhost:443 への DNS リダイレクト → MITM プロキシが傍受 → 9Router → Antigravity/Copilot への応答",
|
||||||
"No API keys — create one in Keys page": "APIキーがありません — キーページで1つ作成してください",
|
"No API keys — create one in Keys page": "APIキーがありません — キーページで1つ作成してください",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "例:温かく穏やかな声で、イギリス英語のアクセントでゆっくり話す",
|
||||||
"sk_9router (default)": "sk_9router(デフォルト)",
|
"sk_9router (default)": "sk_9router(デフォルト)",
|
||||||
"Server started": "サーバーが開始されました",
|
"Server started": "サーバーが開始されました",
|
||||||
"Failed to start server": "サーバーの開始に失敗しました",
|
"Failed to start server": "サーバーの開始に失敗しました",
|
||||||
|
|
|
||||||
|
|
@ -1121,6 +1121,7 @@
|
||||||
"Stop Server": "បញ្ឈប់ម៉ាស៊ីនមេ",
|
"Stop Server": "បញ្ឈប់ម៉ាស៊ីនមេ",
|
||||||
"Stopped": "បានបញ្ឈប់",
|
"Stopped": "បានបញ្ឈប់",
|
||||||
"Strict Proxy": "Strict Proxy",
|
"Strict Proxy": "Strict Proxy",
|
||||||
|
"Style": "រចនាបទ",
|
||||||
"Subagent Model": "ម៉ូដែល Subagent",
|
"Subagent Model": "ម៉ូដែល Subagent",
|
||||||
"Sudo Password Required": "ត្រូវការពាក្យសម្ងាត់ Sudo",
|
"Sudo Password Required": "ត្រូវការពាក្យសម្ងាត់ Sudo",
|
||||||
"Sudo password is required": "ត្រូវការពាក្យសម្ងាត់ Sudo",
|
"Sudo password is required": "ត្រូវការពាក្យសម្ងាត់ Sudo",
|
||||||
|
|
@ -1317,6 +1318,7 @@
|
||||||
"disabled": "បានបិទ",
|
"disabled": "បានបិទ",
|
||||||
"dollars per million tokens": "ដុល្លារក្នុងមួយលាន Tokens",
|
"dollars per million tokens": "ដុល្លារក្នុងមួយលាន Tokens",
|
||||||
"e.g. CwhRBWXzGAHq8TQ4Fs17": "ឧ. CwhRBWXzGAHq8TQ4Fs17",
|
"e.g. CwhRBWXzGAHq8TQ4Fs17": "ឧ. CwhRBWXzGAHq8TQ4Fs17",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "ឧទាហរណ៍៖ សំឡេងកក់ក្តៅ និងទន់ភ្លន់ និយាយយឺតៗដោយសង្កត់សំឡេងបែបអង់គ្លេស",
|
||||||
"e.g. claude-opus-4-5": "ឧ. claude-opus-4-5",
|
"e.g. claude-opus-4-5": "ឧ. claude-opus-4-5",
|
||||||
"e.g. my-model-id": "ឧ. my-model-id",
|
"e.g. my-model-id": "ឧ. my-model-id",
|
||||||
"e.g. tts-1-hd": "ឧ. tts-1-hd",
|
"e.g. tts-1-hd": "ឧ. tts-1-hd",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "로그아웃",
|
"Logout": "로그아웃",
|
||||||
"Login": "로그인",
|
"Login": "로그인",
|
||||||
"Providers": "제공자",
|
"Providers": "제공자",
|
||||||
|
"Style": "스타일",
|
||||||
"Usage": "통계",
|
"Usage": "통계",
|
||||||
"API Key": "API 키",
|
"API Key": "API 키",
|
||||||
"Connected": "연결됨",
|
"Connected": "연결됨",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "작동 방식:",
|
"How it works:": "작동 방식:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE 요청 → localhost:443로 DNS 리디렉션 → MITM 프록시가 가로챔 → 9Router → Antigravity/Copilot으로 응답",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE 요청 → localhost:443로 DNS 리디렉션 → MITM 프록시가 가로챔 → 9Router → Antigravity/Copilot으로 응답",
|
||||||
"No API keys — create one in Keys page": "API 키 없음 — 키 페이지에서 만들기",
|
"No API keys — create one in Keys page": "API 키 없음 — 키 페이지에서 만들기",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "예: 따뜻하고 부드러운 목소리로 영국식 억양을 쓰며 천천히 말하기",
|
||||||
"sk_9router (default)": "sk_9router (기본값)",
|
"sk_9router (default)": "sk_9router (기본값)",
|
||||||
"Server started": "서버 시작됨",
|
"Server started": "서버 시작됨",
|
||||||
"Failed to start server": "서버 시작 실패",
|
"Failed to start server": "서버 시작 실패",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Afmelden",
|
"Logout": "Afmelden",
|
||||||
"Login": "Aanmelden",
|
"Login": "Aanmelden",
|
||||||
"Providers": "Providers",
|
"Providers": "Providers",
|
||||||
|
"Style": "Stijl",
|
||||||
"Usage": "Statistieken",
|
"Usage": "Statistieken",
|
||||||
"API Key": "API-sleutel",
|
"API Key": "API-sleutel",
|
||||||
"Connected": "Verbonden",
|
"Connected": "Verbonden",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Hoe het werkt:",
|
"How it works:": "Hoe het werkt:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-aanvraag → DNS-omleiding naar localhost:443 → MITM-proxy onderschept → 9Router → antwoord naar Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-aanvraag → DNS-omleiding naar localhost:443 → MITM-proxy onderschept → 9Router → antwoord naar Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Geen API-sleutels — maak er één aan op de pagina Sleutels",
|
"No API keys — create one in Keys page": "Geen API-sleutels — maak er één aan op de pagina Sleutels",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "bijv.: een warme, zachte stem, die langzaam praat met een Brits accent",
|
||||||
"sk_9router (default)": "sk_9router (standaard)",
|
"sk_9router (default)": "sk_9router (standaard)",
|
||||||
"Server started": "Server gestart",
|
"Server started": "Server gestart",
|
||||||
"Failed to start server": "Server starten mislukt",
|
"Failed to start server": "Server starten mislukt",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Logg ut",
|
"Logout": "Logg ut",
|
||||||
"Login": "Logg inn",
|
"Login": "Logg inn",
|
||||||
"Providers": "Leverandører",
|
"Providers": "Leverandører",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Bruksstatistikk",
|
"Usage": "Bruksstatistikk",
|
||||||
"API Key": "API-nøkkel",
|
"API Key": "API-nøkkel",
|
||||||
"Connected": "Tilkoblet",
|
"Connected": "Tilkoblet",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Slik fungerer det:",
|
"How it works:": "Slik fungerer det:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-forespørsel → DNS-omdirigering til localhost:443 → MITM-proxy avlytt → 9Router → svar til Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-forespørsel → DNS-omdirigering til localhost:443 → MITM-proxy avlytt → 9Router → svar til Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Ingen API-nøkler — lag en på Keys-siden",
|
"No API keys — create one in Keys page": "Ingen API-nøkler — lag en på Keys-siden",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "f.eks.: en varm, myk stemme, som snakker sakte med britisk aksent",
|
||||||
"sk_9router (default)": "sk_9router (standard)",
|
"sk_9router (default)": "sk_9router (standard)",
|
||||||
"Server started": "Server startet",
|
"Server started": "Server startet",
|
||||||
"Failed to start server": "Klarte ikke å starte server",
|
"Failed to start server": "Klarte ikke å starte server",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Wyloguj się",
|
"Logout": "Wyloguj się",
|
||||||
"Login": "Zaloguj się",
|
"Login": "Zaloguj się",
|
||||||
"Providers": "Dostawcy",
|
"Providers": "Dostawcy",
|
||||||
|
"Style": "Styl",
|
||||||
"Usage": "Statystyka",
|
"Usage": "Statystyka",
|
||||||
"API Key": "Klucz API",
|
"API Key": "Klucz API",
|
||||||
"Connected": "Połączony",
|
"Connected": "Połączony",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Jak to działa:",
|
"How it works:": "Jak to działa:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Żądanie Antigravity/Copilot IDE → Przekierowanie DNS na localhost:443 → Serwer proxy MITM przechwytuje → 9Router → odpowiedź do Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Żądanie Antigravity/Copilot IDE → Przekierowanie DNS na localhost:443 → Serwer proxy MITM przechwytuje → 9Router → odpowiedź do Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Brak kluczy API — utwórz jeden na stronie Klucze",
|
"No API keys — create one in Keys page": "Brak kluczy API — utwórz jeden na stronie Klucze",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "np.: ciepły, delikatny głos, mówiący powoli z brytyjskim akcentem",
|
||||||
"sk_9router (default)": "sk_9router (domyślnie)",
|
"sk_9router (default)": "sk_9router (domyślnie)",
|
||||||
"Server started": "Serwer uruchomiony",
|
"Server started": "Serwer uruchomiony",
|
||||||
"Failed to start server": "Nie udało się uruchomić serwera",
|
"Failed to start server": "Nie udało się uruchomić serwera",
|
||||||
|
|
|
||||||
|
|
@ -864,6 +864,7 @@
|
||||||
"Stopped": "Parado",
|
"Stopped": "Parado",
|
||||||
"Stopping…": "Parando…",
|
"Stopping…": "Parando…",
|
||||||
"Strict Proxy": "Proxy Estrito",
|
"Strict Proxy": "Proxy Estrito",
|
||||||
|
"Style": "Estilo",
|
||||||
"Subagent Model": "Modelo de Subagente",
|
"Subagent Model": "Modelo de Subagente",
|
||||||
"Subagent model overrides": "Substituições de modelo de subagente",
|
"Subagent model overrides": "Substituições de modelo de subagente",
|
||||||
"Submit": "Enviar",
|
"Submit": "Enviar",
|
||||||
|
|
@ -978,6 +979,7 @@
|
||||||
"Your OAuth application client ID": "ID do cliente do seu aplicativo OAuth",
|
"Your OAuth application client ID": "ID do cliente do seu aplicativo OAuth",
|
||||||
"Your requests start from your favorite tools or our unified SDK.": "Suas requisições começam de suas ferramentas favoritas ou do nosso SDK unificado.",
|
"Your requests start from your favorite tools or our unified SDK.": "Suas requisições começam de suas ferramentas favoritas ou do nosso SDK unificado.",
|
||||||
"[ml] downloads ~1 GB (torch + huggingface-hub). Continue?": "[ml] baixa ~1 GB (torch + huggingface-hub). Continuar?",
|
"[ml] downloads ~1 GB (torch + huggingface-hub). Continue?": "[ml] baixa ~1 GB (torch + huggingface-hub). Continuar?",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "ex.: voz quente e suave, falando devagar com sotaque britânico",
|
||||||
"extras status failed": "falha no status dos extras",
|
"extras status failed": "falha no status dos extras",
|
||||||
"git/grep/ls/tree/logs → 60-90% fewer input tokens": "git/grep/ls/tree/logs → 60-90% menos tokens de entrada",
|
"git/grep/ls/tree/logs → 60-90% fewer input tokens": "git/grep/ls/tree/logs → 60-90% menos tokens de entrada",
|
||||||
"not installed": "não instalado",
|
"not installed": "não instalado",
|
||||||
|
|
@ -985,4 +987,4 @@
|
||||||
"tree-sitter AST compression for code responses": "Compressão AST tree-sitter para respostas de código",
|
"tree-sitter AST compression for code responses": "Compressão AST tree-sitter para respostas de código",
|
||||||
"⚠️ MITM intercepts HTTPS traffic of IDE tools (Antigravity, GitHub Copilot, Kiro) via local CA to redirect requests to your providers. May violate ToS → account ban. Use at your own risk.": "⚠️ MITM intercepta tráfego HTTPS de ferramentas IDE (Antigravity, GitHub Copilot, Kiro) via CA local para redirecionar solicitações aos seus provedores. Pode violar ToS → risco de banimento de conta. Use por sua conta e risco.",
|
"⚠️ MITM intercepts HTTPS traffic of IDE tools (Antigravity, GitHub Copilot, Kiro) via local CA to redirect requests to your providers. May violate ToS → account ban. Use at your own risk.": "⚠️ MITM intercepta tráfego HTTPS de ferramentas IDE (Antigravity, GitHub Copilot, Kiro) via CA local para redirecionar solicitações aos seus provedores. Pode violar ToS → risco de banimento de conta. Use por sua conta e risco.",
|
||||||
"⚠️ Risk Notice: This provider uses a subscription/OAuth session not officially licensed for proxy/router use. Account may be restricted or banned. Use at your own risk.": "⚠️ Aviso de Risco: Este provedor usa uma sessão de assinatura/OAuth não licenciada oficialmente para uso de proxy/roteador. A conta pode ser restrita ou banida. Use por sua conta e risco."
|
"⚠️ Risk Notice: This provider uses a subscription/OAuth session not officially licensed for proxy/router use. Account may be restricted or banned. Use at your own risk.": "⚠️ Aviso de Risco: Este provedor usa uma sessão de assinatura/OAuth não licenciada oficialmente para uso de proxy/roteador. A conta pode ser restrita ou banida. Use por sua conta e risco."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Terminar sessão",
|
"Logout": "Terminar sessão",
|
||||||
"Login": "Iniciar sessão",
|
"Login": "Iniciar sessão",
|
||||||
"Providers": "Fornecedores",
|
"Providers": "Fornecedores",
|
||||||
|
"Style": "Estilo",
|
||||||
"Usage": "Estatísticas",
|
"Usage": "Estatísticas",
|
||||||
"API Key": "Chave API",
|
"API Key": "Chave API",
|
||||||
"Connected": "Ligado",
|
"Connected": "Ligado",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Como funciona:",
|
"How it works:": "Como funciona:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Pedido do Antigravity/Copilot IDE → Redirecionamento DNS para localhost:443 → Proxy MITM interceta → 9Router → resposta para Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Pedido do Antigravity/Copilot IDE → Redirecionamento DNS para localhost:443 → Proxy MITM interceta → 9Router → resposta para Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Sem chaves de API — crie uma na página Chaves",
|
"No API keys — create one in Keys page": "Sem chaves de API — crie uma na página Chaves",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "ex.: voz quente e suave, a falar devagar com sotaque britânico",
|
||||||
"sk_9router (default)": "sk_9router (predefinição)",
|
"sk_9router (default)": "sk_9router (predefinição)",
|
||||||
"Server started": "Servidor iniciado",
|
"Server started": "Servidor iniciado",
|
||||||
"Failed to start server": "Falha ao iniciar o servidor",
|
"Failed to start server": "Falha ao iniciar o servidor",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Ieșire",
|
"Logout": "Ieșire",
|
||||||
"Login": "Conectare",
|
"Login": "Conectare",
|
||||||
"Providers": "Furnizori",
|
"Providers": "Furnizori",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Statistici de utilizare",
|
"Usage": "Statistici de utilizare",
|
||||||
"API Key": "Cheie API",
|
"API Key": "Cheie API",
|
||||||
"Connected": "Conectat",
|
"Connected": "Conectat",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Cum funcționează:",
|
"How it works:": "Cum funcționează:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Solicitare Antigravity/Copilot IDE → Redirecționare DNS la localhost:443 → Proxy MITM interceptează → 9Router → răspuns la Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Solicitare Antigravity/Copilot IDE → Redirecționare DNS la localhost:443 → Proxy MITM interceptează → 9Router → răspuns la Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Nicio cheie API — creați una în pagina Chei",
|
"No API keys — create one in Keys page": "Nicio cheie API — creați una în pagina Chei",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "ex.: voce caldă și blândă, vorbind încet cu accent britanic",
|
||||||
"sk_9router (default)": "sk_9router (implicit)",
|
"sk_9router (default)": "sk_9router (implicit)",
|
||||||
"Server started": "Server pornit",
|
"Server started": "Server pornit",
|
||||||
"Failed to start server": "Nu s-a putut porni serverul",
|
"Failed to start server": "Nu s-a putut porni serverul",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Выход",
|
"Logout": "Выход",
|
||||||
"Login": "Вход",
|
"Login": "Вход",
|
||||||
"Providers": "Провайдеры",
|
"Providers": "Провайдеры",
|
||||||
|
"Style": "Стиль",
|
||||||
"Usage": "Статистика",
|
"Usage": "Статистика",
|
||||||
"API Key": "Ключ API",
|
"API Key": "Ключ API",
|
||||||
"Connected": "Подключено",
|
"Connected": "Подключено",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Как это работает:",
|
"How it works:": "Как это работает:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Запрос Antigravity/Copilot IDE → Перенаправление DNS на localhost:443 → Прокси MITM перехватывает → 9Router → ответ для Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Запрос Antigravity/Copilot IDE → Перенаправление DNS на localhost:443 → Прокси MITM перехватывает → 9Router → ответ для Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Нет ключей API — создайте один на странице ключей",
|
"No API keys — create one in Keys page": "Нет ключей API — создайте один на странице ключей",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "напр.: тёплый мягкий голос, медленно говорящий с британским акцентом",
|
||||||
"sk_9router (default)": "sk_9router (по умолчанию)",
|
"sk_9router (default)": "sk_9router (по умолчанию)",
|
||||||
"Server started": "Сервер запущен",
|
"Server started": "Сервер запущен",
|
||||||
"Failed to start server": "Ошибка при запуске сервера",
|
"Failed to start server": "Ошибка при запуске сервера",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Logga ut",
|
"Logout": "Logga ut",
|
||||||
"Login": "Logga in",
|
"Login": "Logga in",
|
||||||
"Providers": "Leverantörer",
|
"Providers": "Leverantörer",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Användarstatistik",
|
"Usage": "Användarstatistik",
|
||||||
"API Key": "API-nyckel",
|
"API Key": "API-nyckel",
|
||||||
"Connected": "Ansluten",
|
"Connected": "Ansluten",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Hur det fungerar:",
|
"How it works:": "Hur det fungerar:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-begäran → DNS-omdirigering till localhost:443 → MITM-proxy avlyssnar → 9Router → svar till Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE-begäran → DNS-omdirigering till localhost:443 → MITM-proxy avlyssnar → 9Router → svar till Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Inga API-nycklar — skapa en på nyckelsidan",
|
"No API keys — create one in Keys page": "Inga API-nycklar — skapa en på nyckelsidan",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "t.ex.: en varm, mjuk röst som talar långsamt med brittisk accent",
|
||||||
"sk_9router (default)": "sk_9router (standard)",
|
"sk_9router (default)": "sk_9router (standard)",
|
||||||
"Server started": "Servern startad",
|
"Server started": "Servern startad",
|
||||||
"Failed to start server": "Misslyckades att starta servern",
|
"Failed to start server": "Misslyckades att starta servern",
|
||||||
|
|
|
||||||
|
|
@ -1119,6 +1119,7 @@
|
||||||
"Stop Server": "หยุดเซิร์ฟเวอร์",
|
"Stop Server": "หยุดเซิร์ฟเวอร์",
|
||||||
"Stopped": "หยุดแล้ว",
|
"Stopped": "หยุดแล้ว",
|
||||||
"Strict Proxy": "Strict Proxy",
|
"Strict Proxy": "Strict Proxy",
|
||||||
|
"Style": "สไตล์",
|
||||||
"Subagent Model": "Subagent Model",
|
"Subagent Model": "Subagent Model",
|
||||||
"Sudo Password Required": "ต้องใช้ Sudo Password",
|
"Sudo Password Required": "ต้องใช้ Sudo Password",
|
||||||
"Sudo password is required": "ต้องใช้ Sudo password",
|
"Sudo password is required": "ต้องใช้ Sudo password",
|
||||||
|
|
@ -1312,6 +1313,7 @@
|
||||||
"disabled": "ปิดใช้งานแล้ว",
|
"disabled": "ปิดใช้งานแล้ว",
|
||||||
"dollars per million tokens": "ดอลลาร์ต่อล้าน tokens",
|
"dollars per million tokens": "ดอลลาร์ต่อล้าน tokens",
|
||||||
"e.g. CwhRBWXzGAHq8TQ4Fs17": "เช่น CwhRBWXzGAHq8TQ4Fs17",
|
"e.g. CwhRBWXzGAHq8TQ4Fs17": "เช่น CwhRBWXzGAHq8TQ4Fs17",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "เช่น เสียงอบอุ่นนุ่มนวล พูดช้าๆ ด้วยสำเนียงอังกฤษ",
|
||||||
"e.g. claude-opus-4-5": "เช่น claude-opus-4-5",
|
"e.g. claude-opus-4-5": "เช่น claude-opus-4-5",
|
||||||
"e.g. my-model-id": "เช่น my-model-id",
|
"e.g. my-model-id": "เช่น my-model-id",
|
||||||
"e.g. tts-1-hd": "เช่น tts-1-hd",
|
"e.g. tts-1-hd": "เช่น tts-1-hd",
|
||||||
|
|
@ -1388,4 +1390,4 @@
|
||||||
"✓ Confirm Add": "✓ ยืนยันการเพิ่ม",
|
"✓ Confirm Add": "✓ ยืนยันการเพิ่ม",
|
||||||
"📝 Configure providers in dashboard or use environment variables": "📝 กำหนดค่า providers ใน dashboard หรือใช้ environment variables",
|
"📝 Configure providers in dashboard or use environment variables": "📝 กำหนดค่า providers ใน dashboard หรือใช้ environment variables",
|
||||||
"🔐 OAuth required. Add now and authenticate after Apply; tool list will be discovered after first connect.": "🔐 ต้องใช้ OAuth เพิ่มตอนนี้แล้ว authenticate หลัง Apply; รายการเครื่องมือจะถูกค้นพบหลังการเชื่อมต่อครั้งแรก"
|
"🔐 OAuth required. Add now and authenticate after Apply; tool list will be discovered after first connect.": "🔐 ต้องใช้ OAuth เพิ่มตอนนี้แล้ว authenticate หลัง Apply; รายการเครื่องมือจะถูกค้นพบหลังการเชื่อมต่อครั้งแรก"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Maglog out",
|
"Logout": "Maglog out",
|
||||||
"Login": "Magsimula ng sesyon",
|
"Login": "Magsimula ng sesyon",
|
||||||
"Providers": "Mga Provider",
|
"Providers": "Mga Provider",
|
||||||
|
"Style": "Estilo",
|
||||||
"Usage": "Mga Istatistika ng Paggamit",
|
"Usage": "Mga Istatistika ng Paggamit",
|
||||||
"API Key": "Susi ng API",
|
"API Key": "Susi ng API",
|
||||||
"Connected": "Konektado",
|
"Connected": "Konektado",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Paano ito gumagana:",
|
"How it works:": "Paano ito gumagana:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE request → DNS redirect sa localhost:443 → MITM proxy intercepts → 9Router → response sa Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE request → DNS redirect sa localhost:443 → MITM proxy intercepts → 9Router → response sa Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Walang API keys — lumikha ng isa sa Keys page",
|
"No API keys — create one in Keys page": "Walang API keys — lumikha ng isa sa Keys page",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "hal.: mainit at malumanay na boses, dahan-dahang nagsasalita nang may British accent",
|
||||||
"sk_9router (default)": "sk_9router (default)",
|
"sk_9router (default)": "sk_9router (default)",
|
||||||
"Server started": "Ang server ay nagsimula",
|
"Server started": "Ang server ay nagsimula",
|
||||||
"Failed to start server": "Nabigo na magsimula ang server",
|
"Failed to start server": "Nabigo na magsimula ang server",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Çıkış Yap",
|
"Logout": "Çıkış Yap",
|
||||||
"Login": "Giriş Yap",
|
"Login": "Giriş Yap",
|
||||||
"Providers": "Sağlayıcılar",
|
"Providers": "Sağlayıcılar",
|
||||||
|
"Style": "Stil",
|
||||||
"Usage": "Kullanım İstatistikleri",
|
"Usage": "Kullanım İstatistikleri",
|
||||||
"API Key": "API Anahtarı",
|
"API Key": "API Anahtarı",
|
||||||
"Connected": "Bağlı",
|
"Connected": "Bağlı",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Nasıl çalışır:",
|
"How it works:": "Nasıl çalışır:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE isteği → DNS'i localhost:443'e yönlendir → MITM proxy yakalar → 9Router → Antigravity/Copilot'a yanıt",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE isteği → DNS'i localhost:443'e yönlendir → MITM proxy yakalar → 9Router → Antigravity/Copilot'a yanıt",
|
||||||
"No API keys — create one in Keys page": "API anahtarı yok — Keys sayfasında bir tane oluşturun",
|
"No API keys — create one in Keys page": "API anahtarı yok — Keys sayfasında bir tane oluşturun",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "örn.: sıcak ve yumuşak bir ses, İngiliz aksanıyla yavaş konuşuyor",
|
||||||
"sk_9router (default)": "sk_9router (varsayılan)",
|
"sk_9router (default)": "sk_9router (varsayılan)",
|
||||||
"Server started": "Sunucu başlatıldı",
|
"Server started": "Sunucu başlatıldı",
|
||||||
"Failed to start server": "Sunucu başlatılamadı",
|
"Failed to start server": "Sunucu başlatılamadı",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Вийти",
|
"Logout": "Вийти",
|
||||||
"Login": "Увійти",
|
"Login": "Увійти",
|
||||||
"Providers": "Постачальники",
|
"Providers": "Постачальники",
|
||||||
|
"Style": "Стиль",
|
||||||
"Usage": "Статистика використання",
|
"Usage": "Статистика використання",
|
||||||
"API Key": "Ключ API",
|
"API Key": "Ключ API",
|
||||||
"Connected": "Підключено",
|
"Connected": "Підключено",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Як це працює:",
|
"How it works:": "Як це працює:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Запит Antigravity/Copilot IDE → Перенаправлення DNS на localhost:443 → MITM проксі перехопити → 9Router → відповідь на Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Запит Antigravity/Copilot IDE → Перенаправлення DNS на localhost:443 → MITM проксі перехопити → 9Router → відповідь на Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Немає ключів API — створіть один на сторінці ключів",
|
"No API keys — create one in Keys page": "Немає ключів API — створіть один на сторінці ключів",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "напр.: теплий м'який голос, що повільно говорить з британським акцентом",
|
||||||
"sk_9router (default)": "sk_9router (за замовчуванням)",
|
"sk_9router (default)": "sk_9router (за замовчуванням)",
|
||||||
"Server started": "Сервер запущено",
|
"Server started": "Сервер запущено",
|
||||||
"Failed to start server": "Не вдалося запустити сервер",
|
"Failed to start server": "Не вдалося запустити сервер",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "لاگ آؤٹ",
|
"Logout": "لاگ آؤٹ",
|
||||||
"Login": "لاگ ان",
|
"Login": "لاگ ان",
|
||||||
"Providers": "فراہم کنندگان",
|
"Providers": "فراہم کنندگان",
|
||||||
|
"Style": "انداز",
|
||||||
"Usage": "استعمال کے اعدادوشمار",
|
"Usage": "استعمال کے اعدادوشمار",
|
||||||
"API Key": "API کلید",
|
"API Key": "API کلید",
|
||||||
"Connected": "منسلک",
|
"Connected": "منسلک",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "یہ کیسے کام کرتا ہے:",
|
"How it works:": "یہ کیسے کام کرتا ہے:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE درخواست → DNS کو localhost:443 کی طرف ری ڈائریکٹ کریں → MITM پروکسی روکے → 9Router → Antigravity/Copilot کو جواب",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE درخواست → DNS کو localhost:443 کی طرف ری ڈائریکٹ کریں → MITM پروکسی روکے → 9Router → Antigravity/Copilot کو جواب",
|
||||||
"No API keys — create one in Keys page": "کوئی API کلید نہیں — Keys صفحہ میں ایک بنائیں",
|
"No API keys — create one in Keys page": "کوئی API کلید نہیں — Keys صفحہ میں ایک بنائیں",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "مثلاً: گرم، نرم آواز، برطانوی لہجے کے ساتھ آہستہ بولتی ہوئی",
|
||||||
"sk_9router (default)": "sk_9router (ڈیفالٹ)",
|
"sk_9router (default)": "sk_9router (ڈیفالٹ)",
|
||||||
"Server started": "سرور شروع ہوگیا",
|
"Server started": "سرور شروع ہوگیا",
|
||||||
"Failed to start server": "سرور شروع کرنے میں ناکام",
|
"Failed to start server": "سرور شروع کرنے میں ناکام",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "Đăng xuất",
|
"Logout": "Đăng xuất",
|
||||||
"Login": "Đăng nhập",
|
"Login": "Đăng nhập",
|
||||||
"Providers": "Nhà cung cấp",
|
"Providers": "Nhà cung cấp",
|
||||||
|
"Style": "Phong cách",
|
||||||
"Usage": "Thống kê",
|
"Usage": "Thống kê",
|
||||||
"API Key": "Khóa API",
|
"API Key": "Khóa API",
|
||||||
"Connected": " Đã kết nối",
|
"Connected": " Đã kết nối",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "Cách hoạt động:",
|
"How it works:": "Cách hoạt động:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Yêu cầu Antigravity/Copilot IDE → Chuyển hướng DNS đến localhost:443 → MITM proxy chặn → 9Router → phản hồi đến Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Yêu cầu Antigravity/Copilot IDE → Chuyển hướng DNS đến localhost:443 → MITM proxy chặn → 9Router → phản hồi đến Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "Không có khóa API — tạo một khóa trong trang Keys",
|
"No API keys — create one in Keys page": "Không có khóa API — tạo một khóa trong trang Keys",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "vd.: giọng ấm áp, nhẹ nhàng, nói chậm với giọng Anh-Anh",
|
||||||
"sk_9router (default)": "sk_9router (mặc định)",
|
"sk_9router (default)": "sk_9router (mặc định)",
|
||||||
"Server started": "Đã khởi động máy chủ",
|
"Server started": "Đã khởi động máy chủ",
|
||||||
"Failed to start server": "Không thể khởi động máy chủ",
|
"Failed to start server": "Không thể khởi động máy chủ",
|
||||||
|
|
|
||||||
|
|
@ -1119,6 +1119,7 @@
|
||||||
"Stop Server": "停止服务器",
|
"Stop Server": "停止服务器",
|
||||||
"Stopped": "已停止",
|
"Stopped": "已停止",
|
||||||
"Strict Proxy": "严格代理",
|
"Strict Proxy": "严格代理",
|
||||||
|
"Style": "风格",
|
||||||
"Subagent Model": "子代理模型",
|
"Subagent Model": "子代理模型",
|
||||||
"Sudo Password Required": "需要 sudo 密码",
|
"Sudo Password Required": "需要 sudo 密码",
|
||||||
"Sudo password is required": "需要 sudo 密码",
|
"Sudo password is required": "需要 sudo 密码",
|
||||||
|
|
@ -1312,6 +1313,7 @@
|
||||||
"disabled": "已禁用",
|
"disabled": "已禁用",
|
||||||
"dollars per million tokens": "美元 / 百万 Token",
|
"dollars per million tokens": "美元 / 百万 Token",
|
||||||
"e.g. CwhRBWXzGAHq8TQ4Fs17": "例如 CwhRBWXzGAHq8TQ4Fs17",
|
"e.g. CwhRBWXzGAHq8TQ4Fs17": "例如 CwhRBWXzGAHq8TQ4Fs17",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "例如:温暖柔和的嗓音,用英式口音缓慢说话",
|
||||||
"e.g. claude-opus-4-5": "例如 claude-opus-4-5",
|
"e.g. claude-opus-4-5": "例如 claude-opus-4-5",
|
||||||
"e.g. my-model-id": "例如 my-model-id",
|
"e.g. my-model-id": "例如 my-model-id",
|
||||||
"e.g. tts-1-hd": "例如 tts-1-hd",
|
"e.g. tts-1-hd": "例如 tts-1-hd",
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
"Logout": "登出",
|
"Logout": "登出",
|
||||||
"Login": "登錄",
|
"Login": "登錄",
|
||||||
"Providers": "提供者",
|
"Providers": "提供者",
|
||||||
|
"Style": "風格",
|
||||||
"Usage": "統計",
|
"Usage": "統計",
|
||||||
"API Key": "API 金鑰",
|
"API Key": "API 金鑰",
|
||||||
"Connected": "已連接",
|
"Connected": "已連接",
|
||||||
|
|
@ -176,6 +177,7 @@
|
||||||
"How it works:": "工作原理:",
|
"How it works:": "工作原理:",
|
||||||
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE 請求 → DNS 重定向到 localhost:443 → MITM 代理攔截 → 9Router → 响應到 Antigravity/Copilot",
|
"Antigravity/Copilot IDE request → DNS redirect to localhost:443 → MITM proxy intercepts → 9Router → response to Antigravity/Copilot": "Antigravity/Copilot IDE 請求 → DNS 重定向到 localhost:443 → MITM 代理攔截 → 9Router → 响應到 Antigravity/Copilot",
|
||||||
"No API keys — create one in Keys page": "沒有 API 金鑰 — 在金鑰頁面中創建一個",
|
"No API keys — create one in Keys page": "沒有 API 金鑰 — 在金鑰頁面中創建一個",
|
||||||
|
"e.g. a warm, gentle voice, speaking slowly with a British accent": "例如:溫暖柔和的嗓音,用英式口音緩慢說話",
|
||||||
"sk_9router (default)": "sk_9router(默認)",
|
"sk_9router (default)": "sk_9router(默認)",
|
||||||
"Server started": "服務器已啟動",
|
"Server started": "服務器已啟動",
|
||||||
"Failed to start server": "啟動服務器失敗",
|
"Failed to start server": "啟動服務器失敗",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { AI_PROVIDERS, getProviderAlias } from "@/shared/constants/providers";
|
||||||
import { getModelsByProviderId, getModelKind } from "@/shared/constants/models";
|
import { getModelsByProviderId, getModelKind } from "@/shared/constants/models";
|
||||||
import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard";
|
import { useCopyToClipboard } from "@/shared/hooks/useCopyToClipboard";
|
||||||
import { TTS_PROVIDER_CONFIG } from "@/shared/constants/ttsProviders";
|
import { TTS_PROVIDER_CONFIG } from "@/shared/constants/ttsProviders";
|
||||||
|
import { translate } from "@/i18n/runtime";
|
||||||
import { getTtsVoicesForModel } from "open-sse/config/ttsModels.js";
|
import { getTtsVoicesForModel } from "open-sse/config/ttsModels.js";
|
||||||
import { GOOGLE_TTS_LANGUAGES } from "open-sse/config/googleTtsLanguages.js";
|
import { GOOGLE_TTS_LANGUAGES } from "open-sse/config/googleTtsLanguages.js";
|
||||||
import { Row } from "./exampleShared";
|
import { Row } from "./exampleShared";
|
||||||
|
|
@ -40,6 +41,7 @@ export function TtsExampleCard({ providerId }) {
|
||||||
|
|
||||||
// Form state
|
// Form state
|
||||||
const [input, setInput] = useState("Hello, this is a text to speech test.");
|
const [input, setInput] = useState("Hello, this is a text to speech test.");
|
||||||
|
const [style, setStyle] = useState(""); // style/voice instructions (e.g. MiMo voicedesign)
|
||||||
const [apiKey, setApiKey] = useState("");
|
const [apiKey, setApiKey] = useState("");
|
||||||
const [useTunnel, setUseTunnel] = useState(false);
|
const [useTunnel, setUseTunnel] = useState(false);
|
||||||
const [localEndpoint, setLocalEndpoint] = useState("");
|
const [localEndpoint, setLocalEndpoint] = useState("");
|
||||||
|
|
@ -59,8 +61,10 @@ export function TtsExampleCard({ providerId }) {
|
||||||
const [modalSearch, setModalSearch] = useState("");
|
const [modalSearch, setModalSearch] = useState("");
|
||||||
const [modalError, setModalError] = useState("");
|
const [modalError, setModalError] = useState("");
|
||||||
const [byLang, setByLang] = useState({});
|
const [byLang, setByLang] = useState({});
|
||||||
// Language hint (e.g. Gemini): controls the spoken language without affecting voice selection
|
// Language hint (e.g. Gemini/MiMo): guides the spoken language without affecting voice selection
|
||||||
const [languageHint, setLanguageHint] = useState("");
|
const [languageHint, setLanguageHint] = useState("");
|
||||||
|
// Number of stored provider connections (shown when no dashboard API key)
|
||||||
|
const [connectionCount, setConnectionCount] = useState(0);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLocalEndpoint(window.location.origin);
|
setLocalEndpoint(window.location.origin);
|
||||||
|
|
@ -68,6 +72,10 @@ export function TtsExampleCard({ providerId }) {
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((d) => { setApiKey((d.keys || []).find((k) => k.isActive !== false)?.key || ""); })
|
.then((d) => { setApiKey((d.keys || []).find((k) => k.isActive !== false)?.key || ""); })
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
|
fetch("/api/providers", { cache: "no-store" })
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((d) => { setConnectionCount((d.connections || []).filter((c) => c.provider === providerId && c.isActive !== false).length); })
|
||||||
|
.catch(() => {});
|
||||||
fetch("/api/tunnel/status")
|
fetch("/api/tunnel/status")
|
||||||
.then((r) => r.json())
|
.then((r) => r.json())
|
||||||
.then((d) => { if (d.publicUrl) setTunnelEndpoint(d.publicUrl); })
|
.then((d) => { if (d.publicUrl) setTunnelEndpoint(d.publicUrl); })
|
||||||
|
|
@ -111,6 +119,10 @@ export function TtsExampleCard({ providerId }) {
|
||||||
if (voices.length) {
|
if (voices.length) {
|
||||||
setSelectedVoice(voices[0].id);
|
setSelectedVoice(voices[0].id);
|
||||||
setSelectedVoiceName(voices[0].name || voices[0].id);
|
setSelectedVoiceName(voices[0].name || voices[0].id);
|
||||||
|
} else {
|
||||||
|
// Model has no preset voices (voicedesign/voiceclone) — drop stale voice
|
||||||
|
setSelectedVoice("");
|
||||||
|
setSelectedVoiceName("");
|
||||||
}
|
}
|
||||||
}, [selectedModel]);
|
}, [selectedModel]);
|
||||||
|
|
||||||
|
|
@ -184,6 +196,7 @@ export function TtsExampleCard({ providerId }) {
|
||||||
const ttsBody = (() => {
|
const ttsBody = (() => {
|
||||||
const b = { model: modelFull, input };
|
const b = { model: modelFull, input };
|
||||||
if (config.hasLanguageHint && languageHint) b.language = languageHint;
|
if (config.hasLanguageHint && languageHint) b.language = languageHint;
|
||||||
|
if (config.hasStyleInput && style.trim()) b.style = style.trim();
|
||||||
return b;
|
return b;
|
||||||
})();
|
})();
|
||||||
const curlSnippet = `curl -X POST ${endpoint}/v1/audio/speech${responseFormat === "json" ? "?response_format=json" : ""} \\
|
const curlSnippet = `curl -X POST ${endpoint}/v1/audio/speech${responseFormat === "json" ? "?response_format=json" : ""} \\
|
||||||
|
|
@ -218,7 +231,8 @@ export function TtsExampleCard({ providerId }) {
|
||||||
if (responseFormat === "json") {
|
if (responseFormat === "json") {
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
setJsonResponse(data); // Store full JSON response
|
setJsonResponse(data); // Store full JSON response
|
||||||
const audioBlob = await fetch(`data:audio/mp3;base64,${data.audio}`).then(r => r.blob());
|
const format = data.format || "mp3";
|
||||||
|
const audioBlob = await fetch(`data:audio/${format};base64,${data.audio}`).then(r => r.blob());
|
||||||
setAudioUrl(URL.createObjectURL(audioBlob));
|
setAudioUrl(URL.createObjectURL(audioBlob));
|
||||||
} else {
|
} else {
|
||||||
const blob = await res.blob();
|
const blob = await res.blob();
|
||||||
|
|
@ -259,7 +273,11 @@ export function TtsExampleCard({ providerId }) {
|
||||||
</Row>
|
</Row>
|
||||||
<Row label="API Key">
|
<Row label="API Key">
|
||||||
<span className="px-3 py-1.5 text-sm font-mono text-text-main bg-sidebar rounded-lg truncate block">
|
<span className="px-3 py-1.5 text-sm font-mono text-text-main bg-sidebar rounded-lg truncate block">
|
||||||
{apiKey ? `${apiKey.slice(0, 8)}${"•".repeat(Math.min(20, apiKey.length - 8))}` : <span className="text-text-muted italic">No key configured</span>}
|
{apiKey
|
||||||
|
? `${apiKey.slice(0, 8)}${"•".repeat(Math.min(20, apiKey.length - 8))}`
|
||||||
|
: connectionCount > 0
|
||||||
|
? <span className="text-text-muted italic">Using stored key(s) · {connectionCount} connection{connectionCount > 1 ? "s" : ""}</span>
|
||||||
|
: <span className="text-text-muted italic">No key configured</span>}
|
||||||
</span>
|
</span>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
|
@ -281,7 +299,7 @@ export function TtsExampleCard({ providerId }) {
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Language hint dropdown (Gemini) — sends body.language to guide pronunciation */}
|
{/* Language hint dropdown (Gemini, Xiaomi MiMo) — sends body.language to guide pronunciation */}
|
||||||
{config.hasLanguageHint && (
|
{config.hasLanguageHint && (
|
||||||
<Row label="Language">
|
<Row label="Language">
|
||||||
<select
|
<select
|
||||||
|
|
@ -290,9 +308,11 @@ export function TtsExampleCard({ providerId }) {
|
||||||
className="w-full px-3 py-1.5 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"
|
className="w-full px-3 py-1.5 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary"
|
||||||
>
|
>
|
||||||
<option value="">Auto-detect</option>
|
<option value="">Auto-detect</option>
|
||||||
{GOOGLE_TTS_LANGUAGES.map((l) => (
|
{(config.languageOptions || GOOGLE_TTS_LANGUAGES).map((l) =>
|
||||||
<option key={l.id} value={l.name}>{l.name}</option>
|
typeof l === "string"
|
||||||
))}
|
? <option key={l} value={l}>{l}</option>
|
||||||
|
: <option key={l.id} value={l.name}>{l.name}</option>
|
||||||
|
)}
|
||||||
</select>
|
</select>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
@ -320,7 +340,7 @@ export function TtsExampleCard({ providerId }) {
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Voice chips — shown after language picked (edge-tts, local-device) or always (OpenAI/ElevenLabs) */}
|
{/* Voice chips — shown after language picked (edge-tts, local-device) or always (OpenAI/ElevenLabs/MiMo) */}
|
||||||
{countryVoices.length > 0 && (
|
{countryVoices.length > 0 && (
|
||||||
<Row label="Voice">
|
<Row label="Voice">
|
||||||
<div className="flex flex-wrap gap-1.5">
|
<div className="flex flex-wrap gap-1.5">
|
||||||
|
|
@ -338,7 +358,9 @@ export function TtsExampleCard({ providerId }) {
|
||||||
: "border-border text-text-muted hover:text-primary hover:border-primary/40"
|
: "border-border text-text-muted hover:text-primary hover:border-primary/40"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{v.name}{v.gender ? ` · ${v.gender[0].toUpperCase()}` : ""}
|
{v.name}
|
||||||
|
{v.language ? ` · ${v.language}` : ""}
|
||||||
|
{v.gender ? ` · ${v.gender[0].toUpperCase()}` : ""}
|
||||||
{v.free_users_allowed === true && (
|
{v.free_users_allowed === true && (
|
||||||
<span className="ml-1.5 px-1 py-0.5 text-[9px] font-semibold rounded bg-green-500/15 text-green-600 border border-green-500/20">Free</span>
|
<span className="ml-1.5 px-1 py-0.5 text-[9px] font-semibold rounded bg-green-500/15 text-green-600 border border-green-500/20">Free</span>
|
||||||
)}
|
)}
|
||||||
|
|
@ -418,6 +440,30 @@ export function TtsExampleCard({ providerId }) {
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
{/* Style / voice instructions (Xiaomi MiMo) */}
|
||||||
|
{config.hasStyleInput && (
|
||||||
|
<Row label={translate("Style")}>
|
||||||
|
<div className="relative">
|
||||||
|
<textarea
|
||||||
|
value={style}
|
||||||
|
onChange={(e) => setStyle(e.target.value)}
|
||||||
|
placeholder={translate("e.g. a warm, gentle voice, speaking slowly with a British accent")}
|
||||||
|
rows={2}
|
||||||
|
className="w-full px-3 py-1.5 pr-7 text-sm border border-border rounded-lg bg-background focus:outline-none focus:border-primary resize-none"
|
||||||
|
/>
|
||||||
|
{style && (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setStyle("")}
|
||||||
|
className="absolute right-2 top-1/2 -translate-y-1/2 text-text-muted hover:text-primary transition-colors"
|
||||||
|
>
|
||||||
|
<span className="material-symbols-outlined text-[14px]">close</span>
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Row>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Output Format */}
|
{/* Output Format */}
|
||||||
<Row label="Output Format">
|
<Row label="Output Format">
|
||||||
<select
|
<select
|
||||||
|
|
|
||||||
|
|
@ -135,4 +135,16 @@ export const TTS_PROVIDER_CONFIG = {
|
||||||
voiceKey: "gemini-tts-voices",
|
voiceKey: "gemini-tts-voices",
|
||||||
voicesPerModel: true,
|
voicesPerModel: true,
|
||||||
},
|
},
|
||||||
|
"xiaomi-mimo": {
|
||||||
|
hasLanguageDropdown: false,
|
||||||
|
hasModelSelector: true,
|
||||||
|
hasBrowseButton: false,
|
||||||
|
hasVoiceIdInput: false,
|
||||||
|
hasStyleInput: true, // style/voice instructions (role: user)
|
||||||
|
hasLanguageHint: true, // language dropdown (Auto-detect default); voices are language-independent
|
||||||
|
languageOptions: ["Chinese", "English"],
|
||||||
|
voiceSource: "hardcoded",
|
||||||
|
modelKey: "xiaomi-mimo-tts-models",
|
||||||
|
voicesPerModel: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ export async function handleTts(request) {
|
||||||
const modelStr = body.model;
|
const modelStr = body.model;
|
||||||
const responseFormat = url.searchParams.get("response_format") || "mp3"; // mp3 (default) | json
|
const responseFormat = url.searchParams.get("response_format") || "mp3"; // mp3 (default) | json
|
||||||
const language = body.language || ""; // Optional language hint (currently used by Gemini)
|
const language = body.language || ""; // Optional language hint (currently used by Gemini)
|
||||||
|
const style = body.style || ""; // Optional style/voice instructions (e.g. Xiaomi MiMo)
|
||||||
log.request("POST", `${url.pathname} | ${modelStr} | format=${responseFormat}${language ? ` | lang=${language}` : ""}`);
|
log.request("POST", `${url.pathname} | ${modelStr} | format=${responseFormat}${language ? ` | lang=${language}` : ""}`);
|
||||||
|
|
||||||
const settings = await getSettings();
|
const settings = await getSettings();
|
||||||
|
|
@ -53,7 +54,7 @@ export async function handleTts(request) {
|
||||||
return handleComboChat({
|
return handleComboChat({
|
||||||
body,
|
body,
|
||||||
models: comboModels,
|
models: comboModels,
|
||||||
handleSingleModel: (b, m) => handleSingleModelTts(b, m, responseFormat, language),
|
handleSingleModel: (b, m) => handleSingleModelTts(b, m, responseFormat, language, style),
|
||||||
log,
|
log,
|
||||||
comboName: modelStr,
|
comboName: modelStr,
|
||||||
comboStrategy,
|
comboStrategy,
|
||||||
|
|
@ -61,10 +62,10 @@ export async function handleTts(request) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleSingleModelTts(body, modelStr, responseFormat, language);
|
return handleSingleModelTts(body, modelStr, responseFormat, language, style);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSingleModelTts(body, modelStr, responseFormat, language) {
|
async function handleSingleModelTts(body, modelStr, responseFormat, language, style) {
|
||||||
const modelInfo = await getModelInfo(modelStr);
|
const modelInfo = await getModelInfo(modelStr);
|
||||||
if (!modelInfo.provider) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid model format");
|
if (!modelInfo.provider) return errorResponse(HTTP_STATUS.BAD_REQUEST, "Invalid model format");
|
||||||
|
|
||||||
|
|
@ -73,7 +74,7 @@ async function handleSingleModelTts(body, modelStr, responseFormat, language) {
|
||||||
|
|
||||||
// noAuth providers — no credential needed
|
// noAuth providers — no credential needed
|
||||||
if (!CREDENTIALED_PROVIDERS.has(provider)) {
|
if (!CREDENTIALED_PROVIDERS.has(provider)) {
|
||||||
const result = await handleTtsCore({ provider, model, input: body.input, responseFormat, language });
|
const result = await handleTtsCore({ provider, model, input: body.input, responseFormat, language, style });
|
||||||
if (result.success) return result.response;
|
if (result.success) return result.response;
|
||||||
return errorResponse(result.status || HTTP_STATUS.BAD_GATEWAY, result.error || "TTS failed");
|
return errorResponse(result.status || HTTP_STATUS.BAD_GATEWAY, result.error || "TTS failed");
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +99,7 @@ async function handleSingleModelTts(body, modelStr, responseFormat, language) {
|
||||||
|
|
||||||
log.info("AUTH", `\x1b[32mUsing ${provider} account: ${credentials.connectionName}\x1b[0m`);
|
log.info("AUTH", `\x1b[32mUsing ${provider} account: ${credentials.connectionName}\x1b[0m`);
|
||||||
|
|
||||||
const result = await handleTtsCore({ provider, model, input: body.input, credentials, responseFormat, language });
|
const result = await handleTtsCore({ provider, model, input: body.input, credentials, responseFormat, language, style });
|
||||||
|
|
||||||
if (result.success) return result.response;
|
if (result.success) return result.response;
|
||||||
|
|
||||||
|
|
|
||||||
150
tests/unit/xiaomi-mimo-tts.test.js
Normal file
150
tests/unit/xiaomi-mimo-tts.test.js
Normal file
|
|
@ -0,0 +1,150 @@
|
||||||
|
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||||
|
import { handleTtsCore } from "../../open-sse/handlers/ttsCore.js";
|
||||||
|
import { buildTtsProviderModels, getTtsVoicesForModel } from "../../open-sse/config/ttsModels.js";
|
||||||
|
import { AI_PROVIDERS } from "../../src/shared/constants/providers.js";
|
||||||
|
import { getTtsAdapter } from "../../open-sse/handlers/ttsProviders/index.js";
|
||||||
|
import { PROVIDER_MODELS } from "../../open-sse/config/providerModels.js";
|
||||||
|
import { TTS_PROVIDER_CONFIG } from "../../src/shared/constants/ttsProviders.js";
|
||||||
|
|
||||||
|
const originalFetch = global.fetch;
|
||||||
|
|
||||||
|
function mockMiMoAudioResponse() {
|
||||||
|
global.fetch.mockResolvedValueOnce(
|
||||||
|
new Response(
|
||||||
|
JSON.stringify({
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
message: {
|
||||||
|
role: "assistant",
|
||||||
|
audio: {
|
||||||
|
data: Buffer.from([0, 1, 2, 3]).toString("base64"),
|
||||||
|
format: "wav",
|
||||||
|
transcript: "Hello from MiMo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
{ status: 200, headers: { "Content-Type": "application/json" } }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Xiaomi MiMo TTS", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
global.fetch = vi.fn();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
global.fetch = originalFetch;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("posts to chat completions with text as assistant message and voice in audio.voice", async () => {
|
||||||
|
mockMiMoAudioResponse();
|
||||||
|
|
||||||
|
const result = await handleTtsCore({
|
||||||
|
provider: "xiaomi-mimo",
|
||||||
|
model: "mimo-v2.5-tts/冰糖",
|
||||||
|
input: "Hello from MiMo",
|
||||||
|
credentials: { apiKey: "test-key" },
|
||||||
|
responseFormat: "json",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
expect(global.fetch.mock.calls[0][0]).toBe("https://api.xiaomimimo.com/v1/chat/completions");
|
||||||
|
expect(global.fetch.mock.calls[0][1].headers.Authorization).toBe("Bearer test-key");
|
||||||
|
|
||||||
|
const sent = JSON.parse(global.fetch.mock.calls[0][1].body);
|
||||||
|
expect(sent.model).toBe("mimo-v2.5-tts");
|
||||||
|
expect(sent.stream).toBe(false);
|
||||||
|
expect(sent.audio.format).toBe("wav");
|
||||||
|
expect(sent.audio.voice).toBe("冰糖");
|
||||||
|
const assistant = sent.messages.find((m) => m.role === "assistant");
|
||||||
|
expect(assistant.content).toBe("Hello from MiMo");
|
||||||
|
|
||||||
|
const body = await result.response.json();
|
||||||
|
expect(body.format).toBe("wav");
|
||||||
|
expect(body.audio).toEqual(expect.any(String));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses mimo_default when no voice is provided", async () => {
|
||||||
|
mockMiMoAudioResponse();
|
||||||
|
|
||||||
|
await handleTtsCore({
|
||||||
|
provider: "xiaomi-mimo",
|
||||||
|
model: "mimo-v2.5-tts",
|
||||||
|
input: "Hello from MiMo",
|
||||||
|
credentials: { apiKey: "test-key" },
|
||||||
|
responseFormat: "json",
|
||||||
|
});
|
||||||
|
|
||||||
|
const sent = JSON.parse(global.fetch.mock.calls[0][1].body);
|
||||||
|
expect(sent.model).toBe("mimo-v2.5-tts");
|
||||||
|
expect(sent.audio.voice).toBe("mimo_default");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("threads the style field into the role:user message", async () => {
|
||||||
|
mockMiMoAudioResponse();
|
||||||
|
|
||||||
|
await handleTtsCore({
|
||||||
|
provider: "xiaomi-mimo",
|
||||||
|
model: "mimo-v2.5-tts/Chloe",
|
||||||
|
input: "Hello from MiMo",
|
||||||
|
style: "a calm, warm female voice speaking slowly",
|
||||||
|
credentials: { apiKey: "test-key" },
|
||||||
|
responseFormat: "json",
|
||||||
|
});
|
||||||
|
|
||||||
|
const sent = JSON.parse(global.fetch.mock.calls[0][1].body);
|
||||||
|
const user = sent.messages.find((m) => m.role === "user");
|
||||||
|
expect(user.content).toBe("a calm, warm female voice speaking slowly");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("exposes MiMo TTS models + preset voices in the TTS catalog", () => {
|
||||||
|
const entries = buildTtsProviderModels();
|
||||||
|
|
||||||
|
expect(entries["xiaomi-mimo-tts-models"].map((model) => model.id)).toEqual(["mimo-v2.5-tts"]);
|
||||||
|
|
||||||
|
const voices = getTtsVoicesForModel("xiaomi-mimo", "mimo-v2.5-tts");
|
||||||
|
expect(voices.map((v) => v.id)).toEqual([
|
||||||
|
"mimo_default", "冰糖", "茉莉", "苏打", "白桦", "Mia", "Chloe", "Milo", "Dean",
|
||||||
|
]);
|
||||||
|
expect(voices.find((v) => v.id === "冰糖")).toMatchObject({ name: "冰糖" });
|
||||||
|
expect(voices.find((v) => v.id === "Dean")).toMatchObject({ name: "Dean" });
|
||||||
|
// Voices are language-independent and gender-neutral (no language/gender labels in the UI)
|
||||||
|
expect(voices[0]).not.toHaveProperty("language");
|
||||||
|
expect(voices[0]).not.toHaveProperty("gender");
|
||||||
|
expect(getTtsVoicesForModel("xiaomi-mimo", "mimo-v2.5-tts-voiceclone")).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("threads the language hint into a role:user instruction", async () => {
|
||||||
|
mockMiMoAudioResponse();
|
||||||
|
|
||||||
|
await handleTtsCore({
|
||||||
|
provider: "xiaomi-mimo",
|
||||||
|
model: "mimo-v2.5-tts/冰糖",
|
||||||
|
input: "Hello from MiMo",
|
||||||
|
language: "English",
|
||||||
|
credentials: { apiKey: "test-key" },
|
||||||
|
responseFormat: "json",
|
||||||
|
});
|
||||||
|
|
||||||
|
const sent = JSON.parse(global.fetch.mock.calls[0][1].body);
|
||||||
|
const user = sent.messages.find((m) => m.role === "user");
|
||||||
|
expect(user.content).toBe("Speak in English.");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("wires the provider into media-providers TTS (serviceKind, adapter, UI config)", () => {
|
||||||
|
expect(AI_PROVIDERS["xiaomi-mimo"].serviceKinds).toContain("tts");
|
||||||
|
expect(AI_PROVIDERS["xiaomi-mimo"].ttsConfig.baseUrl).toBe("https://api.xiaomimimo.com/v1/chat/completions");
|
||||||
|
expect(getTtsAdapter("xiaomi-mimo")).toBeTruthy();
|
||||||
|
|
||||||
|
const ttsModels = PROVIDER_MODELS["xiaomi-mimo"].filter((m) => (m.kind || m.type) === "tts").map((m) => m.id);
|
||||||
|
expect(ttsModels).toEqual(["mimo-v2.5-tts"]);
|
||||||
|
|
||||||
|
expect(TTS_PROVIDER_CONFIG["xiaomi-mimo"].hasStyleInput).toBe(true);
|
||||||
|
expect(TTS_PROVIDER_CONFIG["xiaomi-mimo"].hasLanguageHint).toBe(true);
|
||||||
|
expect(TTS_PROVIDER_CONFIG["xiaomi-mimo"].languageOptions).toEqual(["Chinese", "English"]);
|
||||||
|
expect(TTS_PROVIDER_CONFIG["xiaomi-mimo"].hasVoiceIdInput).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue