diff --git a/package-lock.json b/package-lock.json index ee2fff5..aa0bd45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,10 @@ "version": "0.4.24", "hasInstallScript": true, "license": "SEE LICENSE IN LICENSE", + "workspaces": [ + "packages/*", + "plugin-for-vscode" + ], "dependencies": { "patchright": "^1.60.2", "playwright": "^1.60.0" @@ -23,6 +27,14 @@ "node": ">=18" } }, + "node_modules/@ai-free/core": { + "resolved": "packages/core", + "link": true + }, + "node_modules/ai-free-vscode": { + "resolved": "plugin-for-vscode", + "link": true + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -96,6 +108,26 @@ "engines": { "node": ">=18" } + }, + "packages/core": { + "name": "@ai-free/core", + "version": "0.4.24", + "license": "SEE LICENSE IN LICENSE", + "engines": { + "node": ">=18" + } + }, + "plugin-for-vscode": { + "name": "ai-free-vscode", + "version": "0.4.24", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "patchright": "^1.60.2", + "playwright": "^1.60.0" + }, + "engines": { + "vscode": "^1.75.0" + } } } } diff --git a/package.json b/package.json index 50d4d98..9a2ee3f 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,10 @@ "private": true, "license": "SEE LICENSE IN LICENSE", "type": "module", + "workspaces": [ + "packages/*", + "plugin-for-vscode" + ], "repository": { "type": "git", "url": "https://github.com/Staks-sor/ai-free.git" diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..ad1af0e --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,21 @@ +{ + "name": "@ai-free/core", + "version": "0.4.24", + "description": "Shared core abstractions, model catalog, i18n, and pure utilities for AI Free", + "private": true, + "license": "SEE LICENSE IN LICENSE", + "type": "module", + "main": "./src/index.mjs", + "exports": { + ".": "./src/index.mjs", + "./models": "./src/providers/model-catalog.mjs", + "./providers/*": "./src/providers/*.mjs", + "./i18n": "./src/i18n/index.mjs", + "./i18n/*": "./src/i18n/*.mjs", + "./code-agent/*": "./src/code-agent/*.mjs", + "./memory/*": "./src/memory/*.mjs" + }, + "engines": { + "node": ">=18" + } +} diff --git a/packages/core/src/code-agent/parser.mjs b/packages/core/src/code-agent/parser.mjs new file mode 100644 index 0000000..eb8012d --- /dev/null +++ b/packages/core/src/code-agent/parser.mjs @@ -0,0 +1,143 @@ +// Парсер JSON-tool-call'а из ответа LLM. +// Устойчив к markdown-блокам, тексту до/после JSON, нескольким JSON-объектам. +// +// 3 стратегии последовательно: +// 1. Пройтись по всем fenced-блокам ```...``` (любой язык: json, python, tool_calls), +// искать tool в содержимом каждого. +// 2. Вырезать ВСЕ fenced-блоки (они часто содержат пояснения на python и т.п.) +// и искать tool в остатке. Спасает Qwen-кейс: ```python ...``` + текст + +// {"tool":"write_file",...} снаружи блока. +// 3. Fallback — искать в исходном тексте целиком. + +export function parseToolCall(text) { + const trimmed = String(text || "").trim(); + + const xmlResult = findXmlToolCall(trimmed); + if (xmlResult) return xmlResult; + + const fencedBlocks = [ + ...trimmed.matchAll(/```[a-zA-Z0-9]*\n?([\s\S]*?)```/gi), + ]; + for (const match of fencedBlocks) { + const result = findToolCallInText(match[1].trim()); + if (result) return result; + } + + const stripped = trimmed.replace(/```[a-zA-Z0-9]*\n?[\s\S]*?```/gi, " "); + const result2 = findToolCallInText(stripped); + if (result2) return result2; + + return findToolCallInText(trimmed); +} + +function findXmlToolCall(text) { + const match = text.match(/([\s\S]*?)<\/tool_call>/i); + if (!match) return null; + + const tool = match[2]; + const rawBody = match[3].trim(); + if (!rawBody) return { tool }; + + try { + const parsed = JSON.parse(rawBody); + if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { + return { tool, ...parsed }; + } + } catch { + // Fall through to JSON extraction below. + } + + const json = extractFirstJsonObject(rawBody); + if (!json) return { tool }; + try { + const parsed = JSON.parse(json); + if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { + return { tool, ...parsed }; + } + } catch { + // ignore + } + return { tool }; +} + +// Ищет первый JSON-объект с полем "tool" (string) в тексте. +// Если первый {...} не tool-call — пропускает и берёт следующий. +function findToolCallInText(text) { + let offset = 0; + + while (offset < text.length) { + const start = text.indexOf("{", offset); + if (start < 0) return null; + + const candidate = extractFirstJsonObject(text.slice(start)); + if (!candidate) { + return null; + } + + try { + const parsed = normalizeToolCall(JSON.parse(candidate)); + if (parsed) return parsed; + } catch { + // Невалидный JSON — пробуем следующий объект. + } + + offset = start + Math.max(candidate.length, 1); + } + + return null; +} + +function normalizeToolCall(parsed) { + if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null; + if (typeof parsed.tool === "string") return parsed; + + // Some models emit ACP-ish or malformed tool JSON, for example: + // {"":"write_file","path":"x","content":""} + // {"name":"write_file","arguments":{"path":"x","content":""}} + const emptyKeyTool = parsed[""]; + if (typeof emptyKeyTool === "string") { + const { [""]: _ignored, ...rest } = parsed; + return { tool: emptyKeyTool, ...rest }; + } + + if (typeof parsed.name === "string" && parsed.arguments && typeof parsed.arguments === "object") { + return { tool: parsed.name, ...parsed.arguments }; + } + + return null; +} + +// Безопасный экстрактор первого валидного JSON-объекта из текста. +// Уважает строки и эскейпы, не путается на скобках внутри значений. +export function extractFirstJsonObject(text) { + const start = text.indexOf("{"); + if (start < 0) return null; + + let depth = 0; + let inString = false; + let escaped = false; + + for (let index = start; index < text.length; index += 1) { + const char = text[index]; + + if (inString) { + if (escaped) { + escaped = false; + } else if (char === "\\") { + escaped = true; + } else if (char === '"') { + inString = false; + } + continue; + } + + if (char === '"') inString = true; + else if (char === "{") depth += 1; + else if (char === "}") { + depth -= 1; + if (depth === 0) return text.slice(start, index + 1); + } + } + + return null; +} diff --git a/packages/core/src/i18n/index.mjs b/packages/core/src/i18n/index.mjs new file mode 100644 index 0000000..51dd6e9 --- /dev/null +++ b/packages/core/src/i18n/index.mjs @@ -0,0 +1,94 @@ +import { language as ru } from "./languages/ru.mjs"; +import { language as en } from "./languages/en.mjs"; +import { language as es } from "./languages/es.mjs"; +import { language as pt } from "./languages/pt.mjs"; +import { language as fr } from "./languages/fr.mjs"; +import { language as de } from "./languages/de.mjs"; +import { language as zh } from "./languages/zh.mjs"; +import { language as hi } from "./languages/hi.mjs"; +import { language as ar } from "./languages/ar.mjs"; + +export const DEFAULT_LANGUAGE = "ru"; + +export const LANGUAGES = Object.freeze({ + ru, + en, + es, + pt, + fr, + de, + zh, + hi, + ar, +}); + +const ALIASES = Object.freeze({ + "pt-br": "pt", + "pt-pt": "pt", + "zh-cn": "zh", + "zh-hans": "zh", + "zh-tw": "zh", + "zh-hant": "zh", +}); + +export function normalizeLanguage(value) { + const raw = String(value || "") + .trim() + .replace(/\..*$/, "") + .replace(/_/g, "-") + .toLowerCase(); + if (!raw) return DEFAULT_LANGUAGE; + const exact = ALIASES[raw] || raw; + if (LANGUAGES[exact]) return exact; + const short = exact.split("-")[0]; + return LANGUAGES[short] ? short : DEFAULT_LANGUAGE; +} + +export function resolveUserLanguage(explicitLanguage = "") { + return normalizeLanguage( + explicitLanguage + || process.env.AI_FREE_LANG + || process.env.LC_ALL + || process.env.LC_MESSAGES + || process.env.LANG + || DEFAULT_LANGUAGE, + ); +} + +export function getLanguageMeta(languageCode = DEFAULT_LANGUAGE) { + const language = LANGUAGES[normalizeLanguage(languageCode)] || LANGUAGES[DEFAULT_LANGUAGE]; + return { + code: language.code, + name: language.name, + dir: language.dir || "ltr", + }; +} + +export function getMessages(languageCode = DEFAULT_LANGUAGE) { + const code = normalizeLanguage(languageCode); + const base = code === DEFAULT_LANGUAGE + ? LANGUAGES[DEFAULT_LANGUAGE].messages + : LANGUAGES.en.messages; + return { + ...base, + ...(LANGUAGES[code]?.messages || {}), + }; +} + +export function formatMessage(template, vars = {}) { + return String(template || "").replace(/\{([a-zA-Z0-9_]+)\}/g, (match, key) => ( + Object.prototype.hasOwnProperty.call(vars, key) ? String(vars[key]) : match + )); +} + +export function createTranslator(languageCode = DEFAULT_LANGUAGE) { + const language = getLanguageMeta(languageCode); + const messages = getMessages(language.code); + return { + language, + messages, + t(key, vars = {}) { + return formatMessage(messages[key] || key, vars); + }, + }; +} diff --git a/packages/core/src/i18n/languages/ar.mjs b/packages/core/src/i18n/languages/ar.mjs new file mode 100644 index 0000000..6bba4bb --- /dev/null +++ b/packages/core/src/i18n/languages/ar.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "ar", + name: "العربية", + dir: "rtl", + messages: { + "app.workspace": "مساحة العمل", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "تحديث", + "app.newChat": "+ محادثة جديدة", + "app.noChat": "لم يتم اختيار محادثة", + "app.createChatHint": "أنشئ محادثة من اليسار. يمكن أن تكون كل محادثة مشروعا أو سياق عمل منفصلا.", + "app.firstMessage": "اكتب أول رسالة لهذا المشروع.", + "app.close": "إغلاق", + "app.loading": "جار التحميل...", + "app.loadingShort": "جارٍ التحميل...", + "app.error": "خطأ: {message}", + "app.requestFailed": "فشل الطلب", + "app.resizeChats": "تغيير عرض قائمة المحادثات", + "app.resizeComposer": "تغيير ارتفاع منطقة الإدخال", + "newChat.title": "محادثة جديدة", + "newChat.provider": "المزوّد", + "newChat.mode": "الوضع (النموذج)", + "newChat.modeHint": "يتم تثبيت الوضع عند إنشاء المحادثة. للتبديل لاحقًا، أنشئ محادثة جديدة بالوضع المطلوب.", + "newChat.chatTitle": "عنوان المحادثة (اختياري)", + "newChat.chatTitlePlaceholder": "مثال: إعادة تنظيم auth", + "newChat.workspace": "مجلد المشروع", + "newChat.workspacePlaceholder": "/Users/.../project أو ~/Projects/new-thing", + "newChat.browse": "📁 تصفح", + "newChat.up": "↑ للأعلى", + "newChat.home": "🏠 الرئيسية", + "newChat.newFolder": "➕ مجلد جديد", + "newChat.hidden": "مخفي", + "newChat.pickFolder": "اختر هذا المجلد", + "newChat.newFolderPlaceholder": "اسم المجلد الجديد", + "newChat.create": "إنشاء", + "newChat.cancel": "إلغاء", + "newChat.createFolder": "إنشاء المجلد إذا لم يكن موجودًا (فقط داخل $HOME الخاص بك)", + "newChat.submit": "إنشاء محادثة", + "newChat.emptyFolderName": "أدخل اسمًا.", + "newChat.defaultProject": "افتراضي", + "newChat.truncated": "لا تظهر كل المجلدات. فعّل \"المخفية\" أو افتح المجلد الأعلى.", + "newChat.folderCount": "المجلدات: {total}{suffix}", + "newChat.hiddenSuffix": " (مجلدات . مخفية - مربع \"المخفية\")", + "newChat.folderShown": "يتم عرض {shown} من {total} مجلدات", + "newChat.tooManyFolders": "(مجلدات كثيرة جدًا - ضيّق المسار أو فعّل \"المخفية\")", + "newChat.noSubfolders": "(لا توجد مجلدات فرعية - يمكنك اختيار هذا المجلد بزر \"اختيار\")", + "newChat.truncatedInline": "يتم عرض أول {shown} من {total}. ضيّق المسار أو فعّل \"المخفية\".", + "newChat.creating": "جارٍ إنشاء المحادثة...", + "provider.connected": "✓ متصل", + "provider.connectedTitle": "أنت مسجل الدخول. انقر لاستخدام حساب آخر", + "provider.authorize": "🔑 تسجيل الدخول", + "provider.authorizeTitle": "تسجيل الدخول مطلوب. انقر لتسجيل الدخول", + "provider.connectConfirm": "هل تريد توصيل {label}؟\n\nستفتح نافذة متصفح. سجّل الدخول في الموقع؛ ستُغلق النافذة بعد ذلك.", + "provider.chatgptConnectConfirm": "هل تريد توصيل {label}؟\n\nستُفتح نافذة Chrome عادية مرة واحدة لتسجيل دخول موثوق. ستُغلق تلقائياً بعد التحقق من الجلسة النشطة، ثم سيواصل ChatGPT العمل داخل AI Free.", + "provider.chatgptEmbedLogin": "أكمل تسجيل الدخول في نافذة Chrome. لن تُغلق تلقائياً إلا بعد التحقق من الجلسة النشطة.", + "provider.chatgptEmbedLoginTimeout": "انتهت مهلة تسجيل الدخول إلى {label}. اضغط «تسجيل الدخول عبر Chrome» وحاول مرة أخرى.", + "provider.connectedAlert": "تم توصيل {label}.", + "provider.tokenMissing": "اكتمل تسجيل الدخول، لكن لم يتم العثور على token. حاول مرة أخرى أو شغّل: npm run login-{id}", + "provider.connectFailed": "تعذر توصيل {label}: {message}", + "provider.deepseekFast": "محادثة عادية سريعة", + "provider.deepseekExpert": "استدلال / R1", + "provider.deepseekVision": "تعرف على الصور", + "provider.qwenDefault": "اختر النموذج من رأس المحادثة", + "role.assistantDescription": "مساعد عادي", + "role.assistant": "المساعد", + "role.assistant.label": "المساعد", + "role.assistant.description": "مساعد عادي للمحادثة والإجابات السريعة.", + "role.prompt_builder.label": "منشئ المطالبات", + "role.prompt_builder.description": "يوضح المهمة ويحوّلها إلى prompt عملي للخطوات التالية.", + "role.architect.label": "المعماري", + "role.architect.description": "يصمم الحل وحدود الوحدات والبيانات والمخاطر.", + "role.developer.label": "المطور", + "role.developer.description": "يقترح التنفيذ والملفات والخطوات والتفاصيل التقنية.", + "role.tester.label": "المختبر", + "role.tester.description": "يبحث عن الفحوصات والحالات الحدية والانحدارات وسيناريوهات الاختبار.", + "role.reviewer.label": "المراجع", + "role.reviewer.description": "يفحص الخطة/النتيجة نقديًا ويبحث عن نقاط الضعف.", + "role.synthesizer.label": "المُلخّص", + "role.synthesizer.description": "يجمع مخرجات pipeline في ملخص قصير وخطوات تالية.", + "topbar.model": "النموذج", + "topbar.role": "دور هذه المحادثة في pipeline", + "topbar.coderTitle": "تفعيل وضع الوكيل: يمكن للنموذج إنشاء الملفات وتعديلها", + "topbar.coder": "🛠 المبرمج", + "topbar.coderOn": "🛠 المبرمج ON", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ON", + "topbar.pipeline": "التدفق", + "topbar.pipelineOn": "التدفق ON", + "topbar.hardwareTitle": "ESP / firmware للوحات: يفعّل ملف وكيل العتاد", + "topbar.pipelineTitle": "تمرير الرسائل عبر روابط pipeline", + "topbar.flow": "التدفق", + "topbar.flowTitle": "تدفق pipeline", + "topbar.theme": "تغيير السمة", + "topbar.settings": "الإعدادات / الأوامر المسموحة", + "topbar.quit": "خروج — إيقاف التطبيق وإغلاق Chrome", + "pipeline.title": "تدفق pipeline", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "عيّن دورًا لكل محادثة واختر الخطوة التالية.", + "pipeline.empty": "أنشئ عدة محادثات ثم اربطها هنا.", + "pipeline.end": "النهاية", + "pipeline.user": "المستخدم", + "pipeline.model": "النموذج", + "composer.chooseChat": "اختر محادثة من اليسار...", + "composer.message": "رسالة إلى {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ تفكير عميق", + "composer.thinkingTitle": "تفكير عميق: يعرض النموذج سلسلة التفكير", + "composer.thinkingRequired": "التفكير العميق مطلوب لهذا النموذج", + "composer.search": "🌐 بحث ذكي", + "composer.searchTitle": "بحث ذكي: يستخدم النموذج بحث الويب للمعلومات الحديثة", + "composer.attach": "📎 ملف", + "composer.attachTitle": "إرفاق ملف نصي للقراءة", + "composer.voice": "🎙 صوت", + "composer.voiceTitle": "تسجيل الصوت وإدراج التفريغ في الرسالة", + "composer.voiceStop": "■ إيقاف", + "composer.stop": "■", + "composer.stopTitle": "إيقاف التنفيذ", + "composer.voiceInstalling": "جارٍ تثبيت Parakeet V3. قد يستغرق ذلك بضع دقائق...", + "composer.voiceRecording": "جارٍ تسجيل الصوت...", + "composer.voiceTranscribing": "جارٍ تفريغ الصوت...", + "composer.voiceMissing": "مساعد الصوت غير مثبت. ضع ai-free-stt في {path} أو عيّن AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "نافذة المتصفح هذه لا تدعم تسجيل الميكروفون.", + "composer.voiceNoSpeech": "لم يتم التعرف على كلام.", + "composer.defaultImageQuestion": "ماذا يوجد في هذه الصورة؟ صفها بالتفصيل.", + "composer.imageQuestionLabel": "(سؤال عن الصورة)", + "composer.uploadingImage": "جارٍ رفع ومعالجة الصورة{num}: {name}...", + "composer.thinkingStatus": "جارٍ التفكير...", + "composer.writingStatus": "يكتب الرد…", + "composer.backgroundTask": "⚙️ المهمة تعمل في الخلفية؛ يمكنك الانتقال إلى محادثة أخرى", + "file.svgUnsupported": "SVG (\"{name}\") غير مدعوم للتعرف. احفظه كـ PNG أو JPG.", + "file.imageTooLarge": "الصورة \"{name}\" كبيرة جدًا ({mb} MB). الحد: 10 MB.", + "file.largeImageConfirm": "\"{name}\" بحجم {mb} MB. الملفات الكبيرة غالبًا ترجع CONTENT_EMPTY في DeepSeek.\n\nهل تريد الرفع على أي حال؟", + "file.readFailed": "تعذرت قراءة \"{name}\": {message}", + "file.uploadMissingId": "عاد الرفع بدون fileId", + "file.qwenImageUnsupported": "لا يستطيع AI Free حالياً إرسال الصور عبر ناقل Qwen على الويب. اختر DeepSeek V4 Vision أو ChatGPT لمعالجة الصورة بالكامل.", + "file.binaryUnsupported": "الملف \"{name}\" ثنائي ({ext}). المدعوم حاليًا ملفات النص والصور (PNG/JPG/GIF/WEBP).\n\nPDF ومستندات Office لا تعمل بعد وتحتاج مرحلة منفصلة.", + "file.textTooLarge": "الملف \"{name}\" كبير جدًا ({kb} KB). حد النص: {limitKb} KB.", + "file.looksBinary": "الملف \"{name}\" يبدو ثنائيًا. إذا كان نصًا، أعد تسميته إلى .txt.", + "file.remove": "إزالة", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "أرفقت ملف{plural}. اقرأه وخذه في الاعتبار في إجابتك:", + "file.promptHeader": "الملف: {name} ({kb} KB)", + "file.promptQuestion": "سؤالي:", + "chat.delete": "حذف المحادثة", + "chat.running": "مهمة /code قيد التنفيذ", + "chat.messages": "{count} رسالة", + "chat.deleteConfirm": "حذف المحادثة؟", + "chat.history": "السجل: {file}", + "chat.you": "أنت", + "chat.assistant": "المساعد", + "chat.reasoningProcess": "عملية التفكير", + "chat.reasoningThinking": "يفكر…", + "chat.question": "السؤال", + "chat.system": "النظام", + "install.title": "تثبيت أداة", + "install.approve": "تثبيت", + "install.reject": "إلغاء", + "install.running": "التثبيت جارٍ...", + "install.failed": "فشل التثبيت.", + "settings.title": "الإعدادات", + "settings.interface": "الواجهة", + "settings.tabLanguage": "اللغة", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "الأذونات", + "settings.language": "اللغة", + "settings.webSearchDefault": "تفعيل البحث الذكي افتراضيًا", + "settings.voiceTitle": "إدخال صوتي", + "settings.voiceProvider": "النموذج", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "جاهز", + "settings.voiceMissing": "غير مثبت", + "settings.voiceInstallHint": "النموذج وruntime غير مرفقين مع plugin. ثبّت ai-free-stt بشكل منفصل أو عيّن AI_FREE_STT_BIN.", + "settings.languageSaved": "تم حفظ اللغة. جارٍ إعادة تحميل الواجهة...", + "settings.loadFailed": "تعذر تحميل الإعدادات: {message}", + "settings.low": "خطر منخفض", + "settings.medium": "خطر متوسط", + "settings.high": "خطر عال", + "settings.apiTitle": "API متوافقة مع OpenAI", + "settings.baseUrl": "Base URL", + "settings.apiNote": "في عميل متوافق مع OpenAI، استخدم Base URL ومفتاح Bearer API للمزوّد المطلوب. النماذج: {models}", + "settings.anthropicApiTitle": "API متوافقة مع Anthropic", + "settings.anthropicBaseUrl": "Base URL", + "settings.anthropicEndpoint": "Messages endpoint", + "settings.anthropicAuth": "ترويسة المصادقة", + "settings.anthropicNote": "في عميل متوافق مع Anthropic، استخدم Base URL بدون /v1 ونفس مفتاح المزوّد. POST /v1/messages مدعوم. النماذج: {models}", + "settings.noKey": "لم يتم إنشاء المفتاح", + "settings.keyCreated": "تم إنشاء المفتاح", + "settings.createKey": "إنشاء", + "settings.keyReady": "مفتاح API لـ {label} جاهز", + "settings.keyCreateFailed": "تعذر إنشاء مفتاح API لـ {label}: {message}", + "settings.saveFailed": "تعذر الحفظ: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "داكن", + "theme.light": "فاتح", + "theme.contrast": "تباين", + "theme.title": "السمة: {label}", + "shutdown.title": "توقف CLI", + "shutdown.sub": "الخادم لا يستجيب. ستغلق النافذة تلقائيا.", + "shutdown.gracefulTitle": "جارٍ إيقاف ai-free…", + "shutdown.stoppingTasks": "إيقاف المهام في الخلفية…", + "shutdown.closingBrowsers": "إغلاق Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "إيقاف الخادم…", + "shutdown.stopped": "تم الإيقاف", + "shutdown.stoppedSub": "ستغلق النافذة تلقائيا.", + "welcome.title": "مرحبا بك في AI Free", + "welcome.chooseProviders": "اختر مزودي الذكاء الاصطناعي الذين تريد ربطهم.", + "welcome.multi": "اختر واحدًا أو أكثر. يمكنك إضافة المزيد لاحقًا من الإعدادات.", + "welcome.prompt1": "أدخل أرقامًا مفصولة بفواصل (مثل \"1\" أو \"1,2\"),", + "welcome.prompt2": "أو اضغط Enter لاستخدام DeepSeek افتراضيًا:", + "welcome.invalid": "⚠️ تعذر فهم الاختيار. سيتم استخدام DeepSeek افتراضيًا.", + "welcome.connecting": "جارٍ التوصيل: {providers}", + "welcome.loginFailed": "❌ تعذر توصيل {provider}: {message}", + "welcome.retryLater": "يمكنك المحاولة لاحقًا من الإعدادات في نافذة المحادثة.", + "welcome.done": "✅ تم. جار تشغيل نافذة المحادثة...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/de.mjs b/packages/core/src/i18n/languages/de.mjs new file mode 100644 index 0000000..cc4edd7 --- /dev/null +++ b/packages/core/src/i18n/languages/de.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "de", + name: "Deutsch", + dir: "ltr", + messages: { + "app.workspace": "Arbeitsbereich", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "Aktualisieren", + "app.newChat": "+ Neuer Chat", + "app.noChat": "Kein Chat ausgewählt", + "app.createChatHint": "Erstelle links einen Chat. Jeder Chat kann ein eigenes Projekt oder ein eigener Arbeitskontext sein.", + "app.firstMessage": "Schreibe die erste Nachricht für dieses Projekt.", + "app.close": "Schließen", + "app.loading": "Laden...", + "app.loadingShort": "Lade...", + "app.error": "Fehler: {message}", + "app.requestFailed": "Anfrage fehlgeschlagen", + "app.resizeChats": "Chatliste verbreitern/verkleinern", + "app.resizeComposer": "Eingabebereich in der Höhe ändern", + "newChat.title": "Neuer Chat", + "newChat.provider": "Anbieter", + "newChat.mode": "Modus (Modell)", + "newChat.modeHint": "Der Modus wird beim Erstellen des Chats festgelegt. Zum späteren Wechsel einen neuen Chat im gewünschten Modus erstellen.", + "newChat.chatTitle": "Chat-Titel (optional)", + "newChat.chatTitlePlaceholder": "Beispiel: Auth-Refactoring", + "newChat.workspace": "Projektordner", + "newChat.workspacePlaceholder": "/Users/.../project oder ~/Projects/new-thing", + "newChat.browse": "📁 Durchsuchen", + "newChat.up": "↑ Nach oben", + "newChat.home": "🏠 Start", + "newChat.newFolder": "➕ Neuer Ordner", + "newChat.hidden": "Versteckte", + "newChat.pickFolder": "Diesen Ordner auswählen", + "newChat.newFolderPlaceholder": "Name des neuen Ordners", + "newChat.create": "Erstellen", + "newChat.cancel": "Abbrechen", + "newChat.createFolder": "Ordner erstellen, falls er nicht existiert (nur unter Ihrem $HOME)", + "newChat.submit": "Chat erstellen", + "newChat.emptyFolderName": "Geben Sie einen Namen ein.", + "newChat.defaultProject": "Standard", + "newChat.truncated": "Nicht alle Ordner werden angezeigt. Aktivieren Sie \"Versteckt\" oder öffnen Sie den übergeordneten Ordner.", + "newChat.folderCount": "Ordner: {total}{suffix}", + "newChat.hiddenSuffix": " (versteckte .Ordner - Checkbox \"Versteckt\")", + "newChat.folderShown": "Zeige {shown} von {total} Ordnern", + "newChat.tooManyFolders": "(zu viele Ordner - Pfad eingrenzen oder \"Versteckt\" aktivieren)", + "newChat.noSubfolders": "(keine Unterordner - dieser Ordner kann mit \"Auswählen\" gewählt werden)", + "newChat.truncatedInline": "Zeige die ersten {shown} von {total}. Pfad eingrenzen oder \"Versteckt\" aktivieren.", + "newChat.creating": "Chat wird erstellt...", + "provider.connected": "✓ Verbunden", + "provider.connectedTitle": "Sie sind angemeldet. Klicken, um ein anderes Konto zu verwenden", + "provider.authorize": "🔑 Autorisieren", + "provider.authorizeTitle": "Anmeldung erforderlich. Klicken zum Anmelden", + "provider.connectConfirm": "{label} verbinden?\n\nEin Browserfenster wird geöffnet. Melden Sie sich auf der Website an; das Fenster schließt danach.", + "provider.chatgptConnectConfirm": "{label} verbinden?\n\nFür eine zuverlässige Anmeldung wird einmalig ein normales Chrome-Fenster geöffnet. Nach Prüfung der aktiven Sitzung wird es automatisch geschlossen und ChatGPT läuft in AI Free weiter.", + "provider.chatgptEmbedLogin": "Schließen Sie die Anmeldung im Chrome-Fenster ab. Es wird erst nach Prüfung der aktiven Sitzung automatisch geschlossen.", + "provider.chatgptEmbedLoginTimeout": "Zeitüberschreitung bei der Anmeldung bei {label}. Klicken Sie auf „Mit Chrome anmelden“ und versuchen Sie es erneut.", + "provider.connectedAlert": "{label} verbunden.", + "provider.tokenMissing": "Anmeldung abgeschlossen, aber kein Token gefunden. Erneut versuchen oder ausführen: npm run login-{id}", + "provider.connectFailed": "{label} konnte nicht verbunden werden: {message}", + "provider.deepseekFast": "schneller normaler Chat", + "provider.deepseekExpert": "Reasoning / R1", + "provider.deepseekVision": "Bilderkennung", + "provider.qwenDefault": "Modell im Chat-Kopf wählen", + "role.assistantDescription": "Normaler Assistent", + "role.assistant": "Assistent", + "role.assistant.label": "Assistent", + "role.assistant.description": "Normaler Assistent für Chat und schnelle Antworten.", + "role.prompt_builder.label": "Prompt-Ersteller", + "role.prompt_builder.description": "Klärt die Aufgabe und macht daraus einen Arbeits-Prompt für die nächsten Schritte.", + "role.architect.label": "Architekt", + "role.architect.description": "Entwirft Lösung, Modulgrenzen, Daten und Risiken.", + "role.developer.label": "Entwickler", + "role.developer.description": "Schlägt Implementierung, Dateien, Schritte und technische Details vor.", + "role.tester.label": "Tester", + "role.tester.description": "Findet Prüfungen, Grenzfälle, Regressionen und Testszenarien.", + "role.reviewer.label": "Prüfer", + "role.reviewer.description": "Prüft Plan/Ergebnis kritisch und sucht Schwachstellen.", + "role.synthesizer.label": "Synthesizer", + "role.synthesizer.description": "Fasst Pipeline-Ausgaben in eine kurze Zusammenfassung und nächste Schritte zusammen.", + "topbar.model": "Modell", + "topbar.role": "Rolle dieses Chats in der Pipeline", + "topbar.coderTitle": "Agentenmodus aktivieren: Das Modell kann Dateien erstellen und bearbeiten", + "topbar.coder": "🛠 Coder", + "topbar.coderOn": "🛠 Coder EIN", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP EIN", + "topbar.pipeline": "Ablauf", + "topbar.pipelineOn": "Ablauf EIN", + "topbar.hardwareTitle": "ESP / Board-Firmware: aktiviert das Hardware-Agentenprofil", + "topbar.pipelineTitle": "Nachrichten entlang der Pipeline-Verbindungen weitergeben", + "topbar.flow": "Ablauf", + "topbar.flowTitle": "Pipeline-Ablauf", + "topbar.theme": "Theme wechseln", + "topbar.settings": "Einstellungen / erlaubte Befehle", + "topbar.quit": "Beenden — App stoppen und Chrome schließen", + "pipeline.title": "Pipeline-Ablauf", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "Jedem Chat eine Rolle zuweisen und den nächsten Schritt wählen.", + "pipeline.empty": "Erstellen Sie mehrere Chats und verbinden Sie sie hier.", + "pipeline.end": "Ende", + "pipeline.user": "Benutzer", + "pipeline.model": "Modell", + "composer.chooseChat": "Wähle links einen Chat...", + "composer.message": "Nachricht an {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ Tiefes Denken", + "composer.thinkingTitle": "Tiefes Denken: Das Modell zeigt die Gedankenkette", + "composer.thinkingRequired": "Tiefes Denken ist für dieses Modell erforderlich", + "composer.search": "🌐 Intelligente Suche", + "composer.searchTitle": "Intelligente Suche: Das Modell nutzt Websuche für aktuelle Informationen", + "composer.attach": "📎 Datei", + "composer.attachTitle": "Textdatei zum Lesen anhängen", + "composer.voice": "🎙 Sprache", + "composer.voiceTitle": "Sprache aufnehmen und Transkript in die Nachricht einfügen", + "composer.voiceStop": "■ Stopp", + "composer.stop": "■", + "composer.stopTitle": "Ausführung stoppen", + "composer.voiceInstalling": "Parakeet V3 wird installiert. Das kann einige Minuten dauern...", + "composer.voiceRecording": "Sprachaufnahme läuft...", + "composer.voiceTranscribing": "Sprache wird transkribiert...", + "composer.voiceMissing": "Voice-Helper ist nicht installiert. Legen Sie ai-free-stt unter {path} ab oder setzen Sie AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "Dieses Browserfenster unterstützt keine Mikrofonaufnahme.", + "composer.voiceNoSpeech": "Keine Sprache erkannt.", + "composer.defaultImageQuestion": "Was ist auf diesem Bild? Beschreiben Sie es ausführlich.", + "composer.imageQuestionLabel": "(Bildfrage)", + "composer.uploadingImage": "Bild{num} wird hochgeladen und verarbeitet: {name}...", + "composer.thinkingStatus": "Denke...", + "composer.writingStatus": "Schreibt Antwort…", + "composer.backgroundTask": "⚙️ Aufgabe läuft im Hintergrund; Sie können zu einem anderen Chat wechseln", + "file.svgUnsupported": "SVG (\"{name}\") wird für Erkennung nicht unterstützt. Als PNG oder JPG speichern.", + "file.imageTooLarge": "Bild \"{name}\" ist zu groß ({mb} MB). Limit: 10 MB.", + "file.largeImageConfirm": "\"{name}\" ist {mb} MB groß. Große Dateien liefern bei DeepSeek oft CONTENT_EMPTY.\n\nTrotzdem hochladen?", + "file.readFailed": "\"{name}\" konnte nicht gelesen werden: {message}", + "file.uploadMissingId": "Upload kam ohne fileId zurück", + "file.qwenImageUnsupported": "AI Free kann Bilder noch nicht über den Qwen-Webtransport senden. Wählen Sie DeepSeek V4 Vision oder ChatGPT, damit das Bild verarbeitet wird.", + "file.binaryUnsupported": "Datei \"{name}\" ist binär ({ext}). Unterstützt werden derzeit Textdateien und Bilder (PNG/JPG/GIF/WEBP).\n\nPDF- und Office-Dokumente funktionieren noch nicht; dafür ist eine separate Phase nötig.", + "file.textTooLarge": "Datei \"{name}\" ist zu groß ({kb} KB). Textlimit: {limitKb} KB.", + "file.looksBinary": "Datei \"{name}\" sieht binär aus. Wenn sie Text ist, in .txt umbenennen.", + "file.remove": "Entfernen", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "Ich habe Datei{plural} angehängt. Bitte lesen und in der Antwort berücksichtigen:", + "file.promptHeader": "Datei: {name} ({kb} KB)", + "file.promptQuestion": "Meine Frage:", + "chat.delete": "Chat löschen", + "chat.running": "/code-Aufgabe läuft", + "chat.messages": "{count} Nachrichten", + "chat.deleteConfirm": "Chat löschen?", + "chat.history": "Verlauf: {file}", + "chat.you": "Sie", + "chat.assistant": "Assistent", + "chat.reasoningProcess": "Denkprozess", + "chat.reasoningThinking": "Denkt nach…", + "chat.question": "Frage", + "chat.system": "System", + "install.title": "Werkzeug installieren", + "install.approve": "Installieren", + "install.reject": "Abbrechen", + "install.running": "Installation läuft...", + "install.failed": "Installation fehlgeschlagen.", + "settings.title": "Einstellungen", + "settings.interface": "Oberfläche", + "settings.tabLanguage": "Sprache", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "Berechtigungen", + "settings.language": "Sprache", + "settings.webSearchDefault": "Intelligente Suche standardmäßig aktivieren", + "settings.voiceTitle": "Spracheingabe", + "settings.voiceProvider": "Modell", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Bereit", + "settings.voiceMissing": "Nicht installiert", + "settings.voiceInstallHint": "Modell und Runtime sind nicht im Plugin enthalten. Installieren Sie ai-free-stt separat oder setzen Sie AI_FREE_STT_BIN.", + "settings.languageSaved": "Sprache gespeichert. Oberfläche wird neu geladen...", + "settings.loadFailed": "Einstellungen konnten nicht geladen werden: {message}", + "settings.low": "Niedriges Risiko", + "settings.medium": "Mittleres Risiko", + "settings.high": "Hohes Risiko", + "settings.apiTitle": "OpenAI-kompatible API", + "settings.baseUrl": "Basis-URL", + "settings.apiNote": "In einem OpenAI-kompatiblen Client die Basis-URL und den Bearer API-Key des gewünschten Anbieters verwenden. Modelle: {models}", + "settings.anthropicApiTitle": "Anthropic-kompatible API", + "settings.anthropicBaseUrl": "Basis-URL", + "settings.anthropicEndpoint": "Messages-Endpunkt", + "settings.anthropicAuth": "Auth-Header", + "settings.anthropicNote": "In einem Anthropic-kompatiblen Client die Basis-URL ohne /v1 und denselben Anbieter-Key verwenden. POST /v1/messages wird unterstützt. Modelle: {models}", + "settings.noKey": "Schlüssel nicht erstellt", + "settings.keyCreated": "Schlüssel erstellt", + "settings.createKey": "Erstellen", + "settings.keyReady": "{label} API-Key ist bereit", + "settings.keyCreateFailed": "{label} API-Key konnte nicht erstellt werden: {message}", + "settings.saveFailed": "Konnte nicht speichern: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "Dunkel", + "theme.light": "Hell", + "theme.contrast": "Kontrast", + "theme.title": "Theme: {label}", + "shutdown.title": "CLI gestoppt", + "shutdown.sub": "Der Server antwortet nicht mehr. Das Fenster wird automatisch geschlossen.", + "shutdown.gracefulTitle": "ai-free wird beendet…", + "shutdown.stoppingTasks": "Hintergrundaufgaben werden gestoppt…", + "shutdown.closingBrowsers": "Chrome wird geschlossen (ChatGPT / Qwen)…", + "shutdown.closingServer": "Server wird gestoppt…", + "shutdown.stopped": "Gestoppt", + "shutdown.stoppedSub": "Das Fenster wird automatisch geschlossen.", + "welcome.title": "Willkommen bei AI Free", + "welcome.chooseProviders": "Wähle die KI-Anbieter aus, die du verbinden möchtest.", + "welcome.multi": "Wählen Sie einen oder mehrere. Weitere können später in den Einstellungen hinzugefügt werden.", + "welcome.prompt1": "Nummern durch Kommas getrennt eingeben (z. B. \"1\" oder \"1,2\"),", + "welcome.prompt2": "oder Enter für DeepSeek als Standard drücken:", + "welcome.invalid": "⚠️ Auswahl nicht verstanden. DeepSeek wird standardmäßig verwendet.", + "welcome.connecting": "Verbinde: {providers}", + "welcome.loginFailed": "❌ {provider} konnte nicht verbunden werden: {message}", + "welcome.retryLater": "Sie können es später über Einstellungen im Chatfenster erneut versuchen.", + "welcome.done": "✅ Fertig. Chat-Fenster wird gestartet...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/en.mjs b/packages/core/src/i18n/languages/en.mjs new file mode 100644 index 0000000..2e19e77 --- /dev/null +++ b/packages/core/src/i18n/languages/en.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "en", + name: "English", + dir: "ltr", + messages: { + "app.workspace": "Workspace", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "Refresh", + "app.newChat": "+ New chat", + "app.noChat": "No chat selected", + "app.createChatHint": "Create a chat on the left. Each chat can be a separate project or work context.", + "app.firstMessage": "Write the first message for this project.", + "app.close": "Close", + "app.loading": "Loading...", + "app.loadingShort": "Loading...", + "app.error": "Error: {message}", + "app.requestFailed": "Request failed", + "app.resizeChats": "Resize chat list", + "app.resizeComposer": "Resize input area", + "newChat.title": "New chat", + "newChat.provider": "Provider", + "newChat.mode": "Mode (model)", + "newChat.modeHint": "The mode is fixed when the chat is created. To switch later, create a new chat with the mode you need.", + "newChat.chatTitle": "Chat title (optional)", + "newChat.chatTitlePlaceholder": "Example: auth refactor", + "newChat.workspace": "Project folder", + "newChat.workspacePlaceholder": "/Users/.../project or ~/Projects/new-thing", + "newChat.browse": "📁 Browse", + "newChat.up": "↑ Up", + "newChat.home": "🏠 Home", + "newChat.newFolder": "➕ New folder", + "newChat.hidden": "Hidden", + "newChat.pickFolder": "Select this folder", + "newChat.newFolderPlaceholder": "New folder name", + "newChat.create": "Create", + "newChat.cancel": "Cancel", + "newChat.createFolder": "Create the folder if it does not exist (only under your $HOME)", + "newChat.submit": "Create chat", + "newChat.emptyFolderName": "Enter a name.", + "newChat.defaultProject": "default", + "newChat.truncated": "Not all folders are shown. Enable \"Hidden\" or open the parent folder.", + "newChat.folderCount": "Folders: {total}{suffix}", + "newChat.hiddenSuffix": " (hidden .folders - \"Hidden\" checkbox)", + "newChat.folderShown": "Showing {shown} of {total} folders", + "newChat.tooManyFolders": "(too many folders - narrow the path or enable \"Hidden\")", + "newChat.noSubfolders": "(no subfolders - you can select this folder with \"Select\")", + "newChat.truncatedInline": "Showing the first {shown} of {total}. Narrow the path or enable \"Hidden\".", + "newChat.creating": "Creating chat...", + "provider.connected": "✓ Connected", + "provider.connectedTitle": "You are signed in. Click to use another account", + "provider.authorize": "🔑 Sign in", + "provider.authorizeTitle": "Sign-in required. Click to sign in", + "provider.connectConfirm": "Connect {label}?\n\nA browser window will open. Sign in on the site; the window will close after login.", + "provider.chatgptConnectConfirm": "Connect {label}?\n\nA regular Chrome window will open once for reliable sign-in. It closes automatically after the active session is verified, then ChatGPT continues inside AI Free.", + "provider.chatgptEmbedLogin": "Complete sign-in in the Chrome window. It closes automatically only after the active session is verified.", + "provider.chatgptEmbedLoginTimeout": "Sign-in timed out for {label}. Click ‘Sign in with Chrome’ and try again.", + "provider.connectedAlert": "{label} connected.", + "provider.tokenMissing": "Login finished, but no token was found. Try again or run: npm run login-{id}", + "provider.connectFailed": "Could not connect {label}: {message}", + "provider.deepseekFast": "fast regular chat", + "provider.deepseekExpert": "reasoning / R1", + "provider.deepseekVision": "image recognition", + "provider.qwenDefault": "choose the model in the chat header", + "role.assistantDescription": "Regular assistant", + "role.assistant": "Assistant", + "role.assistant.label": "Assistant", + "role.assistant.description": "Regular assistant for chat and quick answers.", + "role.prompt_builder.label": "Prompt Builder", + "role.prompt_builder.description": "Clarifies the task and turns it into a working prompt for the next steps.", + "role.architect.label": "Architect", + "role.architect.description": "Designs the solution, module boundaries, data, and risks.", + "role.developer.label": "Developer", + "role.developer.description": "Proposes implementation, files, steps, and technical details.", + "role.tester.label": "Tester", + "role.tester.description": "Finds checks, edge cases, regressions, and test scenarios.", + "role.reviewer.label": "Reviewer", + "role.reviewer.description": "Critically checks the plan/result and looks for weak spots.", + "role.synthesizer.label": "Synthesizer", + "role.synthesizer.description": "Combines pipeline outputs into a short summary and next steps.", + "topbar.model": "Model", + "topbar.role": "This chat role in the pipeline", + "topbar.coderTitle": "Enable agent mode: the model can create and edit files", + "topbar.coder": "🛠 Coder", + "topbar.coderOn": "🛠 Coder ON", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ON", + "topbar.pipeline": "Pipeline", + "topbar.pipelineOn": "Pipeline ON", + "topbar.hardwareTitle": "ESP / board firmware: enable the hardware agent profile", + "topbar.pipelineTitle": "Pass messages along pipeline links", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "topbar.flow": "Flow", + "topbar.flowTitle": "Pipeline flow", + "topbar.theme": "Change theme", + "topbar.settings": "Settings / allowed commands", + "topbar.quit": "Quit — stop the app and close Chrome", + "pipeline.title": "Pipeline flow", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — separate Chrome.", + "pipeline.sub": "Assign each chat a role and choose the next step.", + "pipeline.empty": "Create several chats, then connect them here.", + "pipeline.end": "End", + "pipeline.user": "User", + "pipeline.model": "model", + "composer.chooseChat": "Select a chat on the left...", + "composer.message": "Message {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ Deep thinking", + "composer.thinkingTitle": "Deep thinking - the model shows chain-of-thought", + "composer.thinkingRequired": "Deep thinking is required for this model", + "composer.search": "🌐 Smart search", + "composer.searchTitle": "Smart search - the model uses web search for current information", + "composer.attach": "📎 File", + "composer.attachTitle": "Attach a text file to read", + "composer.voice": "🎙 Voice", + "composer.voiceTitle": "Record voice and insert the transcript into the message", + "composer.voiceStop": "■ Stop", + "composer.stop": "■", + "composer.stopTitle": "Stop execution", + "composer.voiceInstalling": "Installing Parakeet V3. This can take a few minutes...", + "composer.voiceRecording": "Recording voice...", + "composer.voiceTranscribing": "Transcribing voice...", + "composer.voiceMissing": "Voice helper is not installed. Put ai-free-stt at {path} or set AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "This browser window does not support microphone recording.", + "composer.voiceNoSpeech": "No speech was recognized.", + "composer.defaultImageQuestion": "What is in this image? Describe it in detail.", + "composer.imageQuestionLabel": "(image question)", + "composer.uploadingImage": "Uploading and processing image{num}: {name}...", + "composer.thinkingStatus": "Thinking...", + "composer.writingStatus": "Writing response…", + "composer.backgroundTask": "⚙️ Task is running in the background - you can switch to another chat", + "file.svgUnsupported": "SVG (\"{name}\") is not supported for recognition. Save it as PNG or JPG.", + "file.imageTooLarge": "Image \"{name}\" is too large ({mb} MB). Limit: 10 MB.", + "file.largeImageConfirm": "\"{name}\" is {mb} MB. Large files often return CONTENT_EMPTY on DeepSeek.\n\nUpload anyway?", + "file.readFailed": "Could not read \"{name}\": {message}", + "file.uploadMissingId": "Upload returned without fileId", + "file.qwenImageUnsupported": "AI Free cannot yet pass images through the Qwen web transport. Select DeepSeek V4 Vision or ChatGPT so the image is fully processed.", + "file.binaryUnsupported": "File \"{name}\" is binary ({ext}). Text files and images (PNG/JPG/GIF/WEBP) are currently supported.\n\nPDF and Office documents do not work yet - they need a separate phase.", + "file.textTooLarge": "File \"{name}\" is too large ({kb} KB). Text limit: {limitKb} KB.", + "file.looksBinary": "File \"{name}\" looks binary. If it is text, rename it to .txt.", + "file.remove": "Remove", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "I attached file{plural}. Read and consider it in your answer:", + "file.promptHeader": "File: {name} ({kb} KB)", + "file.promptQuestion": "My question:", + "chat.delete": "Delete chat", + "chat.running": "/code task is running", + "chat.messages": "{count} messages", + "chat.deleteConfirm": "Delete chat?", + "chat.history": "History: {file}", + "chat.you": "You", + "chat.assistant": "Assistant", + "chat.reasoningProcess": "Thought process", + "chat.reasoningThinking": "Thinking…", + "chat.question": "Question", + "chat.system": "System", + "install.title": "Install tool", + "install.approve": "Install", + "install.reject": "Cancel", + "install.running": "Installation is running...", + "install.failed": "Installation failed.", + "settings.title": "Settings", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.interface": "Interface", + "settings.tabLanguage": "Language", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter only the bot token. Chat ID is optional: it will be bound automatically after /start in Telegram.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID (optional)", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "Permissions", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "settings.language": "Language", + "settings.webSearchDefault": "Enable smart search by default", + "settings.voiceTitle": "Voice input", + "settings.voiceProvider": "Model", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Ready", + "settings.voiceMissing": "Not installed", + "settings.voiceInstallHint": "The model and runtime are not bundled with the plugin. Install ai-free-stt separately or set AI_FREE_STT_BIN.", + "settings.languageSaved": "Language saved. Reloading the interface...", + "settings.loadFailed": "Could not load settings: {message}", + "settings.low": "Low risk", + "settings.medium": "Medium risk", + "settings.high": "High risk", + "settings.apiTitle": "OpenAI-compatible API", + "settings.baseUrl": "Base URL", + "settings.apiNote": "In an OpenAI-compatible client, use the Base URL and Bearer API key for the provider you need. Models: {models}", + "settings.anthropicApiTitle": "Anthropic-compatible API", + "settings.anthropicBaseUrl": "Base URL", + "settings.anthropicEndpoint": "Messages endpoint", + "settings.anthropicAuth": "Auth header", + "settings.anthropicNote": "In an Anthropic-compatible client, use the Base URL without /v1 and the same provider API key. POST /v1/messages is supported. Models: {models}", + "settings.noKey": "Key not created", + "settings.keyCreated": "Key created", + "settings.createKey": "Create", + "settings.keyReady": "{label} API key is ready", + "settings.keyCreateFailed": "Could not create {label} API key: {message}", + "settings.saveFailed": "Could not save: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "Dark", + "theme.light": "Light", + "theme.contrast": "Contrast", + "theme.title": "Theme: {label}", + "shutdown.title": "CLI stopped", + "shutdown.sub": "The server is no longer responding. This window will close automatically.", + "shutdown.gracefulTitle": "Stopping ai-free…", + "shutdown.stoppingTasks": "Stopping background tasks…", + "shutdown.closingBrowsers": "Closing Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "Stopping server…", + "shutdown.stopped": "Stopped", + "shutdown.stoppedSub": "This window will close automatically.", + "welcome.title": "Welcome to AI Free", + "welcome.chooseProviders": "Choose the AI providers you want to connect.", + "welcome.multi": "Choose one or several. You can add more later in Settings.", + "welcome.prompt1": "Enter numbers separated by commas (for example \"1\" or \"1,2\"),", + "welcome.prompt2": "or press Enter for DeepSeek by default:", + "welcome.invalid": "⚠️ Could not understand the choice. Using DeepSeek by default.", + "welcome.connecting": "Connecting: {providers}", + "welcome.loginFailed": "❌ Could not connect {provider}: {message}", + "welcome.retryLater": "You can try again later from Settings in the chat window.", + "welcome.done": "✅ Done. Starting the chat window...", + }, +}; diff --git a/packages/core/src/i18n/languages/es.mjs b/packages/core/src/i18n/languages/es.mjs new file mode 100644 index 0000000..7d9cadb --- /dev/null +++ b/packages/core/src/i18n/languages/es.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "es", + name: "Español", + dir: "ltr", + messages: { + "app.workspace": "Área de trabajo", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "Actualizar", + "app.newChat": "+ Nuevo chat", + "app.noChat": "Ningún chat seleccionado", + "app.createChatHint": "Crea un chat a la izquierda. Cada chat puede ser un proyecto o contexto de trabajo independiente.", + "app.firstMessage": "Escribe el primer mensaje para este proyecto.", + "app.close": "Cerrar", + "app.loading": "Cargando...", + "app.loadingShort": "Cargando...", + "app.error": "Error: {message}", + "app.requestFailed": "La solicitud falló", + "app.resizeChats": "Cambiar el ancho de la lista de chats", + "app.resizeComposer": "Cambiar la altura del área de entrada", + "newChat.title": "Nuevo chat", + "newChat.provider": "Proveedor", + "newChat.mode": "Modo (modelo)", + "newChat.modeHint": "El modo queda fijado al crear el chat. Para cambiarlo después, crea un chat nuevo con el modo que necesitas.", + "newChat.chatTitle": "Título del chat (opcional)", + "newChat.chatTitlePlaceholder": "Ejemplo: refactorización de auth", + "newChat.workspace": "Carpeta del proyecto", + "newChat.workspacePlaceholder": "/Users/.../project o ~/Projects/new-thing", + "newChat.browse": "📁 Explorar", + "newChat.up": "↑ Arriba", + "newChat.home": "🏠 Inicio", + "newChat.newFolder": "➕ Nueva carpeta", + "newChat.hidden": "Ocultos", + "newChat.pickFolder": "Seleccionar esta carpeta", + "newChat.newFolderPlaceholder": "Nombre de la nueva carpeta", + "newChat.create": "Crear", + "newChat.cancel": "Cancelar", + "newChat.createFolder": "Crear la carpeta si no existe (solo dentro de tu $HOME)", + "newChat.submit": "Crear chat", + "newChat.emptyFolderName": "Introduce un nombre.", + "newChat.defaultProject": "predeterminado", + "newChat.truncated": "No se muestran todas las carpetas. Activa \"Ocultos\" o abre la carpeta superior.", + "newChat.folderCount": "Carpetas: {total}{suffix}", + "newChat.hiddenSuffix": " (carpetas . ocultas - casilla \"Ocultos\")", + "newChat.folderShown": "Mostrando {shown} de {total} carpetas", + "newChat.tooManyFolders": "(demasiadas carpetas - acota la ruta o activa \"Ocultos\")", + "newChat.noSubfolders": "(no hay subcarpetas - puedes seleccionar esta carpeta con \"Seleccionar\")", + "newChat.truncatedInline": "Se muestran las primeras {shown} de {total}. Acota la ruta o activa \"Ocultos\".", + "newChat.creating": "Creando chat...", + "provider.connected": "✓ Conectado", + "provider.connectedTitle": "Has iniciado sesión. Pulsa para usar otra cuenta", + "provider.authorize": "🔑 Autorizar", + "provider.authorizeTitle": "Se requiere iniciar sesión. Pulsa para entrar", + "provider.connectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana del navegador. Inicia sesión en el sitio; la ventana se cerrará después.", + "provider.chatgptConnectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana normal de Chrome una sola vez para iniciar sesión de forma fiable. Se cerrará automáticamente después de verificar la sesión activa y ChatGPT continuará dentro de AI Free.", + "provider.chatgptEmbedLogin": "Completa el inicio de sesión en la ventana de Chrome. Se cerrará automáticamente solo después de verificar la sesión activa.", + "provider.chatgptEmbedLoginTimeout": "Se agotó el tiempo para iniciar sesión en {label}. Pulsa «Iniciar sesión con Chrome» e inténtalo de nuevo.", + "provider.connectedAlert": "{label} conectado.", + "provider.tokenMissing": "El inicio de sesión terminó, pero no se encontró ningún token. Inténtalo de nuevo o ejecuta: npm run login-{id}", + "provider.connectFailed": "No se pudo conectar {label}: {message}", + "provider.deepseekFast": "chat normal rápido", + "provider.deepseekExpert": "razonamiento / R1", + "provider.deepseekVision": "reconocimiento de imágenes", + "provider.qwenDefault": "elige el modelo en la cabecera del chat", + "role.assistantDescription": "Asistente normal", + "role.assistant": "Asistente", + "role.assistant.label": "Asistente", + "role.assistant.description": "Asistente normal para chat y respuestas rápidas.", + "role.prompt_builder.label": "Constructor de prompts", + "role.prompt_builder.description": "Aclara la tarea y la convierte en un prompt útil para los siguientes pasos.", + "role.architect.label": "Arquitecto", + "role.architect.description": "Diseña la solución, los límites de módulos, los datos y los riesgos.", + "role.developer.label": "Desarrollador", + "role.developer.description": "Propone implementación, archivos, pasos y detalles técnicos.", + "role.tester.label": "Tester", + "role.tester.description": "Busca verificaciones, casos límite, regresiones y escenarios de prueba.", + "role.reviewer.label": "Revisor", + "role.reviewer.description": "Revisa críticamente el plan/resultado y busca puntos débiles.", + "role.synthesizer.label": "Sintetizador", + "role.synthesizer.description": "Combina las salidas del pipeline en un resumen breve y próximos pasos.", + "topbar.model": "Modelo", + "topbar.role": "Rol de este chat en el pipeline", + "topbar.coderTitle": "Activar modo agente: el modelo puede crear y editar archivos", + "topbar.coder": "🛠 Programador", + "topbar.coderOn": "🛠 Programador ACTIVADO", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ACTIVADO", + "topbar.pipeline": "Flujo", + "topbar.pipelineOn": "Flujo ON", + "topbar.hardwareTitle": "ESP / firmware de placas: activa el perfil de agente de hardware", + "topbar.pipelineTitle": "Pasar mensajes por los enlaces del pipeline", + "topbar.flow": "Flujo", + "topbar.flowTitle": "Flujo del pipeline", + "topbar.theme": "Cambiar tema", + "topbar.settings": "Configuración / comandos permitidos", + "topbar.quit": "Salir — detener la app y cerrar Chrome", + "pipeline.title": "Flujo del pipeline", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "Asigna un rol a cada chat y elige el siguiente paso.", + "pipeline.empty": "Crea varios chats y conéctalos aquí.", + "pipeline.end": "Fin", + "pipeline.user": "Usuario", + "pipeline.model": "modelo", + "composer.chooseChat": "Elige un chat a la izquierda...", + "composer.message": "Mensaje para {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ Pensamiento profundo", + "composer.thinkingTitle": "Pensamiento profundo: el modelo muestra la cadena de razonamiento", + "composer.thinkingRequired": "El pensamiento profundo es obligatorio para este modelo", + "composer.search": "🌐 Búsqueda inteligente", + "composer.searchTitle": "Búsqueda inteligente: el modelo usa búsqueda web para información actual", + "composer.attach": "📎 Archivo", + "composer.attachTitle": "Adjuntar un archivo de texto para leer", + "composer.voice": "🎙 Voz", + "composer.voiceTitle": "Grabar voz e insertar la transcripción en el mensaje", + "composer.voiceStop": "■ Parar", + "composer.stop": "■", + "composer.stopTitle": "Detener ejecución", + "composer.voiceInstalling": "Instalando Parakeet V3. Puede tardar unos minutos...", + "composer.voiceRecording": "Grabando voz...", + "composer.voiceTranscribing": "Transcribiendo voz...", + "composer.voiceMissing": "El helper de voz no está instalado. Coloca ai-free-stt en {path} o define AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "Esta ventana del navegador no admite grabación de micrófono.", + "composer.voiceNoSpeech": "No se reconoció voz.", + "composer.defaultImageQuestion": "¿Qué hay en esta imagen? Descríbelo con detalle.", + "composer.imageQuestionLabel": "(pregunta sobre imagen)", + "composer.uploadingImage": "Subiendo y procesando imagen{num}: {name}...", + "composer.thinkingStatus": "Pensando...", + "composer.writingStatus": "Escribiendo respuesta…", + "composer.backgroundTask": "⚙️ La tarea se ejecuta en segundo plano; puedes cambiar a otro chat", + "file.svgUnsupported": "SVG (\"{name}\") no se admite para reconocimiento. Guárdalo como PNG o JPG.", + "file.imageTooLarge": "La imagen \"{name}\" es demasiado grande ({mb} MB). Límite: 10 MB.", + "file.largeImageConfirm": "\"{name}\" pesa {mb} MB. Los archivos grandes suelen devolver CONTENT_EMPTY en DeepSeek.\n\n¿Subir de todos modos?", + "file.readFailed": "No se pudo leer \"{name}\": {message}", + "file.uploadMissingId": "La subida volvió sin fileId", + "file.qwenImageUnsupported": "AI Free todavía no puede enviar imágenes mediante el transporte web de Qwen. Selecciona DeepSeek V4 Vision o ChatGPT para procesar la imagen.", + "file.binaryUnsupported": "El archivo \"{name}\" es binario ({ext}). Ahora se admiten archivos de texto e imágenes (PNG/JPG/GIF/WEBP).\n\nLos PDF y documentos Office aún no funcionan: necesitan una fase separada.", + "file.textTooLarge": "El archivo \"{name}\" es demasiado grande ({kb} KB). Límite de texto: {limitKb} KB.", + "file.looksBinary": "El archivo \"{name}\" parece binario. Si es texto, cámbiale el nombre a .txt.", + "file.remove": "Quitar", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "He adjuntado archivo{plural}. Léelo y tenlo en cuenta en tu respuesta:", + "file.promptHeader": "Archivo: {name} ({kb} KB)", + "file.promptQuestion": "Mi pregunta:", + "chat.delete": "Eliminar chat", + "chat.running": "La tarea /code se está ejecutando", + "chat.messages": "{count} mensajes", + "chat.deleteConfirm": "¿Eliminar chat?", + "chat.history": "Historial: {file}", + "chat.you": "Tú", + "chat.assistant": "Asistente", + "chat.reasoningProcess": "Proceso de razonamiento", + "chat.reasoningThinking": "Pensando…", + "chat.question": "Pregunta", + "chat.system": "Sistema", + "install.title": "Instalar herramienta", + "install.approve": "Instalar", + "install.reject": "Cancelar", + "install.running": "La instalación está en curso...", + "install.failed": "La instalación falló.", + "settings.title": "Configuración", + "settings.interface": "Interfaz", + "settings.tabLanguage": "Idioma", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "Permisos", + "settings.language": "Idioma", + "settings.webSearchDefault": "Activar búsqueda inteligente por defecto", + "settings.voiceTitle": "Entrada de voz", + "settings.voiceProvider": "Modelo", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Listo", + "settings.voiceMissing": "No instalado", + "settings.voiceInstallHint": "El modelo y el runtime no se incluyen con el plugin. Instala ai-free-stt por separado o define AI_FREE_STT_BIN.", + "settings.languageSaved": "Idioma guardado. Recargando la interfaz...", + "settings.loadFailed": "No se pudo cargar la configuración: {message}", + "settings.low": "Riesgo bajo", + "settings.medium": "Riesgo medio", + "settings.high": "Riesgo alto", + "settings.apiTitle": "API compatible con OpenAI", + "settings.baseUrl": "URL base", + "settings.apiNote": "En un cliente compatible con OpenAI, usa la URL base y la clave Bearer del proveedor necesario. Modelos: {models}", + "settings.anthropicApiTitle": "API compatible con Anthropic", + "settings.anthropicBaseUrl": "URL base", + "settings.anthropicEndpoint": "Endpoint de Messages", + "settings.anthropicAuth": "Cabecera de autenticación", + "settings.anthropicNote": "En un cliente compatible con Anthropic, usa la URL base sin /v1 y la misma clave del proveedor. Se admite POST /v1/messages. Modelos: {models}", + "settings.noKey": "Clave no creada", + "settings.keyCreated": "Clave creada", + "settings.createKey": "Crear", + "settings.keyReady": "Clave API de {label} lista", + "settings.keyCreateFailed": "No se pudo crear la clave API de {label}: {message}", + "settings.saveFailed": "No se pudo guardar: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "Oscuro", + "theme.light": "Claro", + "theme.contrast": "Contraste", + "theme.title": "Tema: {label}", + "shutdown.title": "CLI detenido", + "shutdown.sub": "El servidor ya no responde. La ventana se cerrará automáticamente.", + "shutdown.gracefulTitle": "Deteniendo ai-free…", + "shutdown.stoppingTasks": "Deteniendo tareas en segundo plano…", + "shutdown.closingBrowsers": "Cerrando Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "Deteniendo el servidor…", + "shutdown.stopped": "Detenido", + "shutdown.stoppedSub": "La ventana se cerrará automáticamente.", + "welcome.title": "Bienvenido a AI Free", + "welcome.chooseProviders": "Elige los proveedores de IA que quieres conectar.", + "welcome.multi": "Elige uno o varios. Puedes añadir más después en Configuración.", + "welcome.prompt1": "Introduce números separados por comas (por ejemplo \"1\" o \"1,2\"),", + "welcome.prompt2": "o pulsa Enter para usar DeepSeek por defecto:", + "welcome.invalid": "⚠️ No se pudo entender la elección. Usando DeepSeek por defecto.", + "welcome.connecting": "Conectando: {providers}", + "welcome.loginFailed": "❌ No se pudo conectar {provider}: {message}", + "welcome.retryLater": "Puedes intentarlo de nuevo más tarde desde Configuración en la ventana de chat.", + "welcome.done": "✅ Listo. Iniciando la ventana de chat...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/fr.mjs b/packages/core/src/i18n/languages/fr.mjs new file mode 100644 index 0000000..2094ead --- /dev/null +++ b/packages/core/src/i18n/languages/fr.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "fr", + name: "Français", + dir: "ltr", + messages: { + "app.workspace": "Espace de travail", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "Actualiser", + "app.newChat": "+ Nouveau chat", + "app.noChat": "Aucun chat sélectionné", + "app.createChatHint": "Crée un chat à gauche. Chaque chat peut être un projet ou un contexte de travail séparé.", + "app.firstMessage": "Écris le premier message pour ce projet.", + "app.close": "Fermer", + "app.loading": "Chargement...", + "app.loadingShort": "Chargement...", + "app.error": "Erreur : {message}", + "app.requestFailed": "La requête a échoué", + "app.resizeChats": "Redimensionner la liste des chats", + "app.resizeComposer": "Redimensionner la zone de saisie", + "newChat.title": "Nouveau chat", + "newChat.provider": "Fournisseur", + "newChat.mode": "Mode (modèle)", + "newChat.modeHint": "Le mode est fixé à la création du chat. Pour le changer ensuite, créez un nouveau chat avec le mode voulu.", + "newChat.chatTitle": "Titre du chat (facultatif)", + "newChat.chatTitlePlaceholder": "Exemple : refactorisation auth", + "newChat.workspace": "Dossier du projet", + "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", + "newChat.browse": "📁 Parcourir", + "newChat.up": "↑ Haut", + "newChat.home": "🏠 Accueil", + "newChat.newFolder": "➕ Nouveau dossier", + "newChat.hidden": "Masqués", + "newChat.pickFolder": "Sélectionner ce dossier", + "newChat.newFolderPlaceholder": "Nom du nouveau dossier", + "newChat.create": "Créer", + "newChat.cancel": "Annuler", + "newChat.createFolder": "Créer le dossier s’il n’existe pas (uniquement sous votre $HOME)", + "newChat.submit": "Créer le chat", + "newChat.emptyFolderName": "Saisissez un nom.", + "newChat.defaultProject": "par défaut", + "newChat.truncated": "Tous les dossiers ne sont pas affichés. Activez \"Masqués\" ou ouvrez le dossier parent.", + "newChat.folderCount": "Dossiers : {total}{suffix}", + "newChat.hiddenSuffix": " (dossiers . masqués - case \"Masqués\")", + "newChat.folderShown": "Affichage de {shown} sur {total} dossiers", + "newChat.tooManyFolders": "(trop de dossiers - précisez le chemin ou activez \"Masqués\")", + "newChat.noSubfolders": "(aucun sous-dossier - vous pouvez sélectionner ce dossier avec \"Sélectionner\")", + "newChat.truncatedInline": "Affichage des {shown} premiers sur {total}. Précisez le chemin ou activez \"Masqués\".", + "newChat.creating": "Création du chat...", + "provider.connected": "✓ Connecté", + "provider.connectedTitle": "Vous êtes connecté. Cliquez pour utiliser un autre compte", + "provider.authorize": "🔑 Autoriser", + "provider.authorizeTitle": "Connexion requise. Cliquez pour vous connecter", + "provider.connectConfirm": "Connecter {label} ?\n\nUne fenêtre de navigateur va s’ouvrir. Connectez-vous sur le site ; elle se fermera après la connexion.", + "provider.chatgptConnectConfirm": "Connecter {label} ?\n\nUne fenêtre Chrome normale s’ouvrira une seule fois pour une connexion fiable. Elle se fermera automatiquement après vérification de la session active, puis ChatGPT continuera dans AI Free.", + "provider.chatgptEmbedLogin": "Terminez la connexion dans la fenêtre Chrome. Elle se fermera automatiquement uniquement après vérification de la session active.", + "provider.chatgptEmbedLoginTimeout": "Le délai de connexion à {label} a expiré. Cliquez sur « Se connecter avec Chrome » et réessayez.", + "provider.connectedAlert": "{label} connecté.", + "provider.tokenMissing": "Connexion terminée, mais aucun jeton trouvé. Réessayez ou lancez : npm run login-{id}", + "provider.connectFailed": "Impossible de connecter {label} : {message}", + "provider.deepseekFast": "chat normal rapide", + "provider.deepseekExpert": "raisonnement / R1", + "provider.deepseekVision": "reconnaissance d’images", + "provider.qwenDefault": "choisissez le modèle dans l’en-tête du chat", + "role.assistantDescription": "Assistant standard", + "role.assistant": "Assistant", + "role.assistant.label": "Assistant", + "role.assistant.description": "Assistant standard pour le chat et les réponses rapides.", + "role.prompt_builder.label": "Constructeur de prompts", + "role.prompt_builder.description": "Clarifie la tâche et la transforme en prompt exploitable pour les étapes suivantes.", + "role.architect.label": "Architecte", + "role.architect.description": "Conçoit la solution, les limites des modules, les données et les risques.", + "role.developer.label": "Développeur", + "role.developer.description": "Propose l’implémentation, les fichiers, les étapes et les détails techniques.", + "role.tester.label": "Testeur", + "role.tester.description": "Cherche les vérifications, cas limites, régressions et scénarios de test.", + "role.reviewer.label": "Relecteur", + "role.reviewer.description": "Vérifie de façon critique le plan/résultat et cherche les points faibles.", + "role.synthesizer.label": "Synthétiseur", + "role.synthesizer.description": "Combine les sorties du pipeline en un bref résumé et prochaines étapes.", + "topbar.model": "Modèle", + "topbar.role": "Rôle de ce chat dans le pipeline", + "topbar.coderTitle": "Activer le mode agent : le modèle peut créer et modifier des fichiers", + "topbar.coder": "🛠 Codeur", + "topbar.coderOn": "🛠 Codeur ACTIF", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ACTIF", + "topbar.pipeline": "Flux", + "topbar.pipelineOn": "Flux ON", + "topbar.hardwareTitle": "ESP / firmware de cartes : active le profil agent matériel", + "topbar.pipelineTitle": "Transmettre les messages via les liens du pipeline", + "topbar.flow": "Flux", + "topbar.flowTitle": "Flux du pipeline", + "topbar.theme": "Changer le thème", + "topbar.settings": "Paramètres / commandes autorisées", + "topbar.quit": "Quitter — arrêter l'app et fermer Chrome", + "pipeline.title": "Flux du pipeline", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "Attribuez un rôle à chaque chat et choisissez l’étape suivante.", + "pipeline.empty": "Créez plusieurs chats, puis reliez-les ici.", + "pipeline.end": "Fin", + "pipeline.user": "Utilisateur", + "pipeline.model": "modèle", + "composer.chooseChat": "Choisis un chat à gauche...", + "composer.message": "Message pour {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ Raisonnement approfondi", + "composer.thinkingTitle": "Réflexion approfondie : le modèle affiche la chaîne de raisonnement", + "composer.thinkingRequired": "La réflexion approfondie est obligatoire pour ce modèle", + "composer.search": "🌐 Recherche intelligente", + "composer.searchTitle": "Recherche intelligente : le modèle utilise le web pour les informations à jour", + "composer.attach": "📎 Fichier", + "composer.attachTitle": "Joindre un fichier texte à lire", + "composer.voice": "🎙 Voix", + "composer.voiceTitle": "Enregistrer la voix et insérer la transcription dans le message", + "composer.voiceStop": "■ Stop", + "composer.stop": "■", + "composer.stopTitle": "Arrêter l'exécution", + "composer.voiceInstalling": "Installation de Parakeet V3. Cela peut prendre quelques minutes...", + "composer.voiceRecording": "Enregistrement vocal...", + "composer.voiceTranscribing": "Transcription vocale...", + "composer.voiceMissing": "Le helper vocal n’est pas installé. Placez ai-free-stt dans {path} ou définissez AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "Cette fenêtre de navigateur ne prend pas en charge l’enregistrement micro.", + "composer.voiceNoSpeech": "Aucune parole reconnue.", + "composer.defaultImageQuestion": "Que contient cette image ? Décrivez-la en détail.", + "composer.imageQuestionLabel": "(question sur l’image)", + "composer.uploadingImage": "Envoi et traitement de l’image{num} : {name}...", + "composer.thinkingStatus": "Réflexion...", + "composer.writingStatus": "Rédaction de la réponse…", + "composer.backgroundTask": "⚙️ La tâche s’exécute en arrière-plan ; vous pouvez passer à un autre chat", + "file.svgUnsupported": "SVG (\"{name}\") n’est pas pris en charge pour la reconnaissance. Enregistrez en PNG ou JPG.", + "file.imageTooLarge": "L’image \"{name}\" est trop grande ({mb} Mo). Limite : 10 Mo.", + "file.largeImageConfirm": "\"{name}\" fait {mb} Mo. Les gros fichiers renvoient souvent CONTENT_EMPTY sur DeepSeek.\n\nEnvoyer quand même ?", + "file.readFailed": "Impossible de lire \"{name}\" : {message}", + "file.uploadMissingId": "L’envoi est revenu sans fileId", + "file.qwenImageUnsupported": "AI Free ne peut pas encore transmettre les images via le transport web Qwen. Sélectionnez DeepSeek V4 Vision ou ChatGPT pour traiter l’image.", + "file.binaryUnsupported": "Le fichier \"{name}\" est binaire ({ext}). Les fichiers texte et images (PNG/JPG/GIF/WEBP) sont pris en charge.\n\nLes PDF et documents Office ne fonctionnent pas encore : il faut une phase séparée.", + "file.textTooLarge": "Le fichier \"{name}\" est trop grand ({kb} Ko). Limite texte : {limitKb} Ko.", + "file.looksBinary": "Le fichier \"{name}\" semble binaire. Si c’est du texte, renommez-le en .txt.", + "file.remove": "Retirer", + "file.sizeKb": "{kb} Ko", + "file.promptPrefix": "J’ai joint fichier{plural}. Lisez-le et tenez-en compte dans votre réponse :", + "file.promptHeader": "Fichier : {name} ({kb} Ko)", + "file.promptQuestion": "Ma question :", + "chat.delete": "Supprimer le chat", + "chat.running": "La tâche /code est en cours", + "chat.messages": "{count} messages", + "chat.deleteConfirm": "Supprimer le chat ?", + "chat.history": "Historique : {file}", + "chat.you": "Vous", + "chat.assistant": "Assistant", + "chat.reasoningProcess": "Processus de réflexion", + "chat.reasoningThinking": "En train de réfléchir…", + "chat.question": "Question", + "chat.system": "Système", + "install.title": "Installer un outil", + "install.approve": "Installer", + "install.reject": "Annuler", + "install.running": "Installation en cours...", + "install.failed": "L’installation a échoué.", + "settings.title": "Paramètres", + "settings.interface": "Interface", + "settings.tabLanguage": "Langue", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "Autorisations", + "settings.language": "Langue", + "settings.webSearchDefault": "Activer la recherche intelligente par défaut", + "settings.voiceTitle": "Saisie vocale", + "settings.voiceProvider": "Modèle", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Prêt", + "settings.voiceMissing": "Non installé", + "settings.voiceInstallHint": "Le modèle et le runtime ne sont pas inclus dans le plugin. Installez ai-free-stt séparément ou définissez AI_FREE_STT_BIN.", + "settings.languageSaved": "Langue enregistrée. Rechargement de l’interface...", + "settings.loadFailed": "Impossible de charger les paramètres : {message}", + "settings.low": "Risque faible", + "settings.medium": "Risque moyen", + "settings.high": "Risque élevé", + "settings.apiTitle": "API compatible OpenAI", + "settings.baseUrl": "URL de base", + "settings.apiNote": "Dans un client compatible OpenAI, utilisez l’URL de base et la clé Bearer du fournisseur voulu. Modèles : {models}", + "settings.anthropicApiTitle": "API compatible Anthropic", + "settings.anthropicBaseUrl": "URL de base", + "settings.anthropicEndpoint": "Endpoint Messages", + "settings.anthropicAuth": "En-tête d’authentification", + "settings.anthropicNote": "Dans un client compatible Anthropic, utilisez l’URL de base sans /v1 et la même clé fournisseur. POST /v1/messages est pris en charge. Modèles : {models}", + "settings.noKey": "Clé non créée", + "settings.keyCreated": "Clé créée", + "settings.createKey": "Créer", + "settings.keyReady": "Clé API {label} prête", + "settings.keyCreateFailed": "Impossible de créer la clé API {label} : {message}", + "settings.saveFailed": "Impossible d’enregistrer : {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "Sombre", + "theme.light": "Clair", + "theme.contrast": "Contraste", + "theme.title": "Thème : {label}", + "shutdown.title": "CLI arrêté", + "shutdown.sub": "Le serveur ne répond plus. La fenêtre va se fermer automatiquement.", + "shutdown.gracefulTitle": "Arrêt de ai-free…", + "shutdown.stoppingTasks": "Arrêt des tâches en arrière-plan…", + "shutdown.closingBrowsers": "Fermeture de Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "Arrêt du serveur…", + "shutdown.stopped": "Arrêté", + "shutdown.stoppedSub": "La fenêtre va se fermer automatiquement.", + "welcome.title": "Bienvenue dans AI Free", + "welcome.chooseProviders": "Choisis les fournisseurs d'IA à connecter.", + "welcome.multi": "Choisissez-en un ou plusieurs. Vous pourrez en ajouter ensuite dans Paramètres.", + "welcome.prompt1": "Saisissez des numéros séparés par des virgules (par exemple \"1\" ou \"1,2\"),", + "welcome.prompt2": "ou appuyez sur Entrée pour DeepSeek par défaut :", + "welcome.invalid": "⚠️ Choix incompris. DeepSeek sera utilisé par défaut.", + "welcome.connecting": "Connexion : {providers}", + "welcome.loginFailed": "❌ Impossible de connecter {provider} : {message}", + "welcome.retryLater": "Vous pourrez réessayer plus tard depuis Paramètres dans la fenêtre de chat.", + "welcome.done": "✅ Terminé. Lancement de la fenêtre de chat...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/hi.mjs b/packages/core/src/i18n/languages/hi.mjs new file mode 100644 index 0000000..c771b56 --- /dev/null +++ b/packages/core/src/i18n/languages/hi.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "hi", + name: "हिन्दी", + dir: "ltr", + messages: { + "app.workspace": "वर्कस्पेस", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "रीफ्रेश", + "app.newChat": "+ नया चैट", + "app.noChat": "कोई चैट चयनित नहीं", + "app.createChatHint": "बाईं ओर चैट बनाएं। हर चैट अलग प्रोजेक्ट या काम का संदर्भ हो सकती है।", + "app.firstMessage": "इस प्रोजेक्ट के लिए पहला संदेश लिखें।", + "app.close": "बंद करें", + "app.loading": "लोड हो रहा है...", + "app.loadingShort": "लोड हो रहा है...", + "app.error": "त्रुटि: {message}", + "app.requestFailed": "अनुरोध विफल हुआ", + "app.resizeChats": "चैट सूची की चौड़ाई बदलें", + "app.resizeComposer": "इनपुट क्षेत्र की ऊँचाई बदलें", + "newChat.title": "नया चैट", + "newChat.provider": "प्रदाता", + "newChat.mode": "मोड (मॉडल)", + "newChat.modeHint": "चैट बनाते समय मोड तय हो जाता है। बाद में बदलने के लिए ज़रूरी मोड के साथ नया चैट बनाएं।", + "newChat.chatTitle": "चैट शीर्षक (वैकल्पिक)", + "newChat.chatTitlePlaceholder": "उदाहरण: auth refactor", + "newChat.workspace": "प्रोजेक्ट फ़ोल्डर", + "newChat.workspacePlaceholder": "/Users/.../project या ~/Projects/new-thing", + "newChat.browse": "📁 ब्राउज़", + "newChat.up": "↑ ऊपर", + "newChat.home": "🏠 होम", + "newChat.newFolder": "➕ नया फ़ोल्डर", + "newChat.hidden": "छिपे हुए", + "newChat.pickFolder": "यह फ़ोल्डर चुनें", + "newChat.newFolderPlaceholder": "नए फ़ोल्डर का नाम", + "newChat.create": "बनाएं", + "newChat.cancel": "रद्द करें", + "newChat.createFolder": "अगर फ़ोल्डर मौजूद नहीं है तो बनाएं (केवल आपके $HOME के अंदर)", + "newChat.submit": "चैट बनाएं", + "newChat.emptyFolderName": "नाम दर्ज करें।", + "newChat.defaultProject": "डिफ़ॉल्ट", + "newChat.truncated": "सभी फ़ोल्डर नहीं दिखाए गए। \"छिपे हुए\" चालू करें या ऊपर वाला फ़ोल्डर खोलें।", + "newChat.folderCount": "फ़ोल्डर: {total}{suffix}", + "newChat.hiddenSuffix": " (छिपे हुए .फ़ोल्डर - \"छिपे हुए\" चेकबॉक्स)", + "newChat.folderShown": "{total} में से {shown} फ़ोल्डर दिख रहे हैं", + "newChat.tooManyFolders": "(बहुत अधिक फ़ोल्डर - पथ छोटा करें या \"छिपे हुए\" चालू करें)", + "newChat.noSubfolders": "(कोई सबफ़ोल्डर नहीं - इस फ़ोल्डर को \"चुनें\" से चुना जा सकता है)", + "newChat.truncatedInline": "{total} में से पहले {shown} दिख रहे हैं। पथ छोटा करें या \"छिपे हुए\" चालू करें।", + "newChat.creating": "चैट बनाई जा रही है...", + "provider.connected": "✓ कनेक्टेड", + "provider.connectedTitle": "आप साइन इन हैं। दूसरा खाता उपयोग करने के लिए क्लिक करें", + "provider.authorize": "🔑 अधिकृत करें", + "provider.authorizeTitle": "साइन इन आवश्यक है। साइन इन करने के लिए क्लिक करें", + "provider.connectConfirm": "{label} कनेक्ट करें?\n\nब्राउज़र विंडो खुलेगी। साइट पर साइन इन करें; लॉगिन के बाद विंडो बंद हो जाएगी।", + "provider.chatgptConnectConfirm": "{label} को कनेक्ट करें?\n\nविश्वसनीय साइन-इन के लिए सामान्य Chrome विंडो एक बार खुलेगी। सक्रिय सत्र सत्यापित होने के बाद यह अपने आप बंद हो जाएगी और ChatGPT AI Free के अंदर चलता रहेगा।", + "provider.chatgptEmbedLogin": "Chrome विंडो में साइन-इन पूरा करें। सक्रिय सत्र सत्यापित होने के बाद ही यह अपने आप बंद होगी।", + "provider.chatgptEmbedLoginTimeout": "{label} में साइन-इन का समय समाप्त हो गया। «Chrome से साइन इन करें» दबाकर फिर कोशिश करें।", + "provider.connectedAlert": "{label} कनेक्ट हो गया।", + "provider.tokenMissing": "लॉगिन पूरा हुआ, लेकिन token नहीं मिला। फिर कोशिश करें या चलाएँ: npm run login-{id}", + "provider.connectFailed": "{label} कनेक्ट नहीं हो सका: {message}", + "provider.deepseekFast": "तेज़ सामान्य चैट", + "provider.deepseekExpert": "reasoning / R1", + "provider.deepseekVision": "छवि पहचान", + "provider.qwenDefault": "चैट हेडर में मॉडल चुनें", + "role.assistantDescription": "सामान्य सहायक", + "role.assistant": "सहायक", + "role.assistant.label": "सहायक", + "role.assistant.description": "चैट और तेज़ उत्तरों के लिए सामान्य सहायक।", + "role.prompt_builder.label": "प्रॉम्प्ट बिल्डर", + "role.prompt_builder.description": "कार्य स्पष्ट करता है और अगले चरणों के लिए उपयोगी prompt बनाता है।", + "role.architect.label": "आर्किटेक्ट", + "role.architect.description": "समाधान, मॉड्यूल सीमाएँ, डेटा और जोखिम डिज़ाइन करता है।", + "role.developer.label": "डेवलपर", + "role.developer.description": "implementation, files, steps और technical details सुझाता है।", + "role.tester.label": "टेस्टर", + "role.tester.description": "checks, edge cases, regressions और test scenarios खोजता है।", + "role.reviewer.label": "रिव्यूअर", + "role.reviewer.description": "plan/result को आलोचनात्मक रूप से जाँचता है और कमजोरियाँ ढूँढता है।", + "role.synthesizer.label": "सिंथेसाइज़र", + "role.synthesizer.description": "pipeline outputs को छोटे summary और next steps में जोड़ता है।", + "topbar.model": "मॉडल", + "topbar.role": "pipeline में इस चैट की भूमिका", + "topbar.coderTitle": "एजेंट मोड चालू करें: मॉडल फ़ाइलें बना और संपादित कर सकता है", + "topbar.coder": "🛠 कोडर", + "topbar.coderOn": "🛠 कोडर ON", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ON", + "topbar.pipeline": "फ़्लो", + "topbar.pipelineOn": "फ़्लो ON", + "topbar.hardwareTitle": "ESP / बोर्ड firmware: hardware agent profile चालू करता है", + "topbar.pipelineTitle": "pipeline links के जरिए संदेश भेजें", + "topbar.flow": "फ़्लो", + "topbar.flowTitle": "Pipeline फ़्लो", + "topbar.theme": "थीम बदलें", + "topbar.settings": "सेटिंग्स / अनुमत कमांड", + "topbar.quit": "बाहर — ऐप बंद करें और Chrome बंद करें", + "pipeline.title": "Pipeline फ़्लो", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "हर चैट को भूमिका दें और अगला कदम चुनें।", + "pipeline.empty": "कई चैट बनाएं, फिर उन्हें यहाँ जोड़ें।", + "pipeline.end": "अंत", + "pipeline.user": "उपयोगकर्ता", + "pipeline.model": "मॉडल", + "composer.chooseChat": "बाईं ओर चैट चुनें...", + "composer.message": "{label} को संदेश...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ गहरी सोच", + "composer.thinkingTitle": "गहरी सोच: मॉडल chain-of-thought दिखाता है", + "composer.thinkingRequired": "इस मॉडल के लिए गहरी सोच आवश्यक है", + "composer.search": "🌐 स्मार्ट खोज", + "composer.searchTitle": "स्मार्ट खोज: मॉडल ताज़ा जानकारी के लिए वेब खोज उपयोग करता है", + "composer.attach": "📎 फ़ाइल", + "composer.attachTitle": "पढ़ने के लिए टेक्स्ट फ़ाइल जोड़ें", + "composer.voice": "🎙 आवाज़", + "composer.voiceTitle": "आवाज़ रिकॉर्ड करें और transcript को संदेश में डालें", + "composer.voiceStop": "■ रोकें", + "composer.stop": "■", + "composer.stopTitle": "निष्पादन रोकें", + "composer.voiceInstalling": "Parakeet V3 install हो रहा है। इसमें कुछ मिनट लग सकते हैं...", + "composer.voiceRecording": "आवाज़ रिकॉर्ड हो रही है...", + "composer.voiceTranscribing": "आवाज़ transcribe हो रही है...", + "composer.voiceMissing": "Voice helper installed नहीं है। ai-free-stt को {path} में रखें या AI_FREE_STT_BIN set करें।", + "composer.voiceUnsupported": "यह browser window microphone recording support नहीं करती।", + "composer.voiceNoSpeech": "कोई speech पहचानी नहीं गई।", + "composer.defaultImageQuestion": "इस छवि में क्या है? विस्तार से बताएं।", + "composer.imageQuestionLabel": "(छवि प्रश्न)", + "composer.uploadingImage": "छवि{num} अपलोड और प्रोसेस हो रही है: {name}...", + "composer.thinkingStatus": "सोच रहा है...", + "composer.writingStatus": "जवाब लिख रहा है…", + "composer.backgroundTask": "⚙️ कार्य पृष्ठभूमि में चल रहा है; आप दूसरे चैट पर जा सकते हैं", + "file.svgUnsupported": "SVG (\"{name}\") पहचान के लिए समर्थित नहीं है। इसे PNG या JPG के रूप में सहेजें।", + "file.imageTooLarge": "छवि \"{name}\" बहुत बड़ी है ({mb} MB)। सीमा: 10 MB।", + "file.largeImageConfirm": "\"{name}\" {mb} MB है। बड़ी फ़ाइलें DeepSeek पर अक्सर CONTENT_EMPTY लौटाती हैं।\n\nफिर भी अपलोड करें?", + "file.readFailed": "\"{name}\" पढ़ा नहीं जा सका: {message}", + "file.uploadMissingId": "Upload ने fileId नहीं लौटाया", + "file.qwenImageUnsupported": "AI Free अभी Qwen वेब ट्रांसपोर्ट के माध्यम से चित्र नहीं भेज सकता। चित्र को पूरी तरह संसाधित करने के लिए DeepSeek V4 Vision या ChatGPT चुनें।", + "file.binaryUnsupported": "फ़ाइल \"{name}\" binary है ({ext})। अभी text files और images (PNG/JPG/GIF/WEBP) समर्थित हैं।\n\nPDF और Office documents अभी काम नहीं करते - इनके लिए अलग चरण चाहिए।", + "file.textTooLarge": "फ़ाइल \"{name}\" बहुत बड़ी है ({kb} KB)। text सीमा: {limitKb} KB।", + "file.looksBinary": "फ़ाइल \"{name}\" binary लगती है। अगर यह text है, तो इसे .txt नाम दें।", + "file.remove": "हटाएँ", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "मैंने file{plural} जोड़ी है। इसे पढ़ें और उत्तर में ध्यान रखें:", + "file.promptHeader": "फ़ाइल: {name} ({kb} KB)", + "file.promptQuestion": "मेरा प्रश्न:", + "chat.delete": "चैट हटाएं", + "chat.running": "/code कार्य चल रहा है", + "chat.messages": "{count} संदेश", + "chat.deleteConfirm": "चैट हटाएं?", + "chat.history": "इतिहास: {file}", + "chat.you": "आप", + "chat.assistant": "सहायक", + "chat.reasoningProcess": "विचार प्रक्रिया", + "chat.reasoningThinking": "सोच रहा है…", + "chat.question": "प्रश्न", + "chat.system": "सिस्टम", + "install.title": "टूल इंस्टॉल करें", + "install.approve": "इंस्टॉल", + "install.reject": "रद्द करें", + "install.running": "इंस्टॉलेशन चल रहा है...", + "install.failed": "इंस्टॉलेशन विफल हुआ।", + "settings.title": "सेटिंग्स", + "settings.interface": "इंटरफ़ेस", + "settings.tabLanguage": "भाषा", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "अनुमतियाँ", + "settings.language": "भाषा", + "settings.webSearchDefault": "स्मार्ट खोज को डिफ़ॉल्ट रूप से चालू करें", + "settings.voiceTitle": "Voice input", + "settings.voiceProvider": "Model", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "तैयार", + "settings.voiceMissing": "Installed नहीं", + "settings.voiceInstallHint": "Model और runtime plugin में bundled नहीं हैं। ai-free-stt अलग से install करें या AI_FREE_STT_BIN set करें।", + "settings.languageSaved": "भाषा सहेजी गई। इंटरफ़ेस फिर से लोड हो रहा है...", + "settings.loadFailed": "सेटिंग्स लोड नहीं हो सकीं: {message}", + "settings.low": "कम जोखिम", + "settings.medium": "मध्यम जोखिम", + "settings.high": "उच्च जोखिम", + "settings.apiTitle": "OpenAI-compatible API", + "settings.baseUrl": "Base URL", + "settings.apiNote": "OpenAI-compatible client में Base URL और ज़रूरी provider की Bearer API key डालें। Models: {models}", + "settings.anthropicApiTitle": "Anthropic-compatible API", + "settings.anthropicBaseUrl": "Base URL", + "settings.anthropicEndpoint": "Messages endpoint", + "settings.anthropicAuth": "Auth header", + "settings.anthropicNote": "Anthropic-compatible client में /v1 के बिना Base URL और वही provider API key डालें। POST /v1/messages समर्थित है। Models: {models}", + "settings.noKey": "Key नहीं बनी", + "settings.keyCreated": "Key बन गई", + "settings.createKey": "बनाएं", + "settings.keyReady": "{label} API key तैयार है", + "settings.keyCreateFailed": "{label} API key नहीं बन सकी: {message}", + "settings.saveFailed": "सहेजा नहीं जा सका: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "डार्क", + "theme.light": "लाइट", + "theme.contrast": "कॉन्ट्रास्ट", + "theme.title": "थीम: {label}", + "shutdown.title": "CLI बंद हो गया", + "shutdown.sub": "सर्वर जवाब नहीं दे रहा। विंडो अपने आप बंद हो जाएगी।", + "shutdown.gracefulTitle": "ai-free बंद हो रहा है…", + "shutdown.stoppingTasks": "पृष्ठभूमि कार्य रोक रहे हैं…", + "shutdown.closingBrowsers": "Chrome बंद कर रहे हैं (ChatGPT / Qwen)…", + "shutdown.closingServer": "सर्वर बंद कर रहे हैं…", + "shutdown.stopped": "बंद हो गया", + "shutdown.stoppedSub": "विंडो अपने आप बंद हो जाएगी।", + "welcome.title": "AI Free में आपका स्वागत है", + "welcome.chooseProviders": "वे AI प्रदाता चुनें जिन्हें आप कनेक्ट करना चाहते हैं।", + "welcome.multi": "एक या कई चुनें। बाद में Settings में और जोड़ सकते हैं।", + "welcome.prompt1": "कॉमा से अलग नंबर दर्ज करें (जैसे \"1\" या \"1,2\"),", + "welcome.prompt2": "या DeepSeek को डिफ़ॉल्ट रखने के लिए Enter दबाएँ:", + "welcome.invalid": "⚠️ चुनाव समझ नहीं आया। DeepSeek डिफ़ॉल्ट रूप से उपयोग हो रहा है।", + "welcome.connecting": "कनेक्ट हो रहा है: {providers}", + "welcome.loginFailed": "❌ {provider} कनेक्ट नहीं हो सका: {message}", + "welcome.retryLater": "आप बाद में चैट विंडो की Settings से फिर कोशिश कर सकते हैं।", + "welcome.done": "✅ हो गया। चैट विंडो शुरू हो रही है...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/pt.mjs b/packages/core/src/i18n/languages/pt.mjs new file mode 100644 index 0000000..ff9cf0f --- /dev/null +++ b/packages/core/src/i18n/languages/pt.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "pt", + name: "Português", + dir: "ltr", + messages: { + "app.workspace": "Área de trabalho", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "Atualizar", + "app.newChat": "+ Novo chat", + "app.noChat": "Nenhum chat selecionado", + "app.createChatHint": "Crie um chat à esquerda. Cada chat pode ser um projeto ou contexto de trabalho separado.", + "app.firstMessage": "Escreva a primeira mensagem para este projeto.", + "app.close": "Fechar", + "app.loading": "Carregando...", + "app.loadingShort": "Carregando...", + "app.error": "Erro: {message}", + "app.requestFailed": "A solicitação falhou", + "app.resizeChats": "Redimensionar lista de chats", + "app.resizeComposer": "Redimensionar área de entrada", + "newChat.title": "Novo chat", + "newChat.provider": "Provedor", + "newChat.mode": "Modo (modelo)", + "newChat.modeHint": "O modo fica fixo ao criar o chat. Para trocar depois, crie um novo chat com o modo desejado.", + "newChat.chatTitle": "Título do chat (opcional)", + "newChat.chatTitlePlaceholder": "Exemplo: refatoração auth", + "newChat.workspace": "Pasta do projeto", + "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", + "newChat.browse": "📁 Procurar", + "newChat.up": "↑ Acima", + "newChat.home": "🏠 Início", + "newChat.newFolder": "➕ Nova pasta", + "newChat.hidden": "Ocultos", + "newChat.pickFolder": "Selecionar esta pasta", + "newChat.newFolderPlaceholder": "Nome da nova pasta", + "newChat.create": "Criar", + "newChat.cancel": "Cancelar", + "newChat.createFolder": "Criar a pasta se ela não existir (somente dentro do seu $HOME)", + "newChat.submit": "Criar chat", + "newChat.emptyFolderName": "Digite um nome.", + "newChat.defaultProject": "padrão", + "newChat.truncated": "Nem todas as pastas são exibidas. Ative \"Ocultas\" ou abra a pasta superior.", + "newChat.folderCount": "Pastas: {total}{suffix}", + "newChat.hiddenSuffix": " (pastas . ocultas - caixa \"Ocultas\")", + "newChat.folderShown": "Mostrando {shown} de {total} pastas", + "newChat.tooManyFolders": "(pastas demais - refine o caminho ou ative \"Ocultas\")", + "newChat.noSubfolders": "(sem subpastas - você pode selecionar esta pasta com \"Selecionar\")", + "newChat.truncatedInline": "Mostrando as primeiras {shown} de {total}. Refine o caminho ou ative \"Ocultas\".", + "newChat.creating": "Criando chat...", + "provider.connected": "✓ Conectado", + "provider.connectedTitle": "Você está conectado. Clique para usar outra conta", + "provider.authorize": "🔑 Autorizar", + "provider.authorizeTitle": "Login necessário. Clique para entrar", + "provider.connectConfirm": "Conectar {label}?\n\nUma janela do navegador será aberta. Faça login no site; a janela fechará depois.", + "provider.chatgptConnectConfirm": "Conectar {label}?\n\nUma janela normal do Chrome será aberta uma vez para um login confiável. Ela será fechada automaticamente após a verificação da sessão ativa, e o ChatGPT continuará dentro do AI Free.", + "provider.chatgptEmbedLogin": "Conclua o login na janela do Chrome. Ela será fechada automaticamente somente após a verificação da sessão ativa.", + "provider.chatgptEmbedLoginTimeout": "O tempo de login em {label} expirou. Clique em «Entrar com o Chrome» e tente novamente.", + "provider.connectedAlert": "{label} conectado.", + "provider.tokenMissing": "O login terminou, mas nenhum token foi encontrado. Tente novamente ou execute: npm run login-{id}", + "provider.connectFailed": "Não foi possível conectar {label}: {message}", + "provider.deepseekFast": "chat normal rápido", + "provider.deepseekExpert": "raciocínio / R1", + "provider.deepseekVision": "reconhecimento de imagens", + "provider.qwenDefault": "escolha o modelo no cabeçalho do chat", + "role.assistantDescription": "Assistente normal", + "role.assistant": "Assistente", + "role.assistant.label": "Assistente", + "role.assistant.description": "Assistente normal para chat e respostas rápidas.", + "role.prompt_builder.label": "Construtor de prompts", + "role.prompt_builder.description": "Esclarece a tarefa e a transforma em um prompt de trabalho para os próximos passos.", + "role.architect.label": "Arquiteto", + "role.architect.description": "Projeta a solução, limites dos módulos, dados e riscos.", + "role.developer.label": "Desenvolvedor", + "role.developer.description": "Propõe implementação, arquivos, passos e detalhes técnicos.", + "role.tester.label": "Testador", + "role.tester.description": "Encontra verificações, casos extremos, regressões e cenários de teste.", + "role.reviewer.label": "Revisor", + "role.reviewer.description": "Verifica criticamente o plano/resultado e procura pontos fracos.", + "role.synthesizer.label": "Sintetizador", + "role.synthesizer.description": "Combina as saídas do pipeline em um resumo curto e próximos passos.", + "topbar.model": "Modelo", + "topbar.role": "Função deste chat no pipeline", + "topbar.coderTitle": "Ativar modo agente: o modelo pode criar e editar arquivos", + "topbar.coder": "🛠 Programador", + "topbar.coderOn": "🛠 Programador ATIVO", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ATIVO", + "topbar.pipeline": "Fluxo", + "topbar.pipelineOn": "Fluxo ON", + "topbar.hardwareTitle": "ESP / firmware de placas: ativa o perfil de agente de hardware", + "topbar.pipelineTitle": "Passar mensagens pelos links do pipeline", + "topbar.flow": "Fluxo", + "topbar.flowTitle": "Fluxo do pipeline", + "topbar.theme": "Alterar tema", + "topbar.settings": "Configurações / comandos permitidos", + "topbar.quit": "Sair — parar o app e fechar o Chrome", + "pipeline.title": "Fluxo do pipeline", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "Atribua uma função a cada chat e escolha o próximo passo.", + "pipeline.empty": "Crie vários chats e conecte-os aqui.", + "pipeline.end": "Fim", + "pipeline.user": "Usuário", + "pipeline.model": "modelo", + "composer.chooseChat": "Escolha um chat à esquerda...", + "composer.message": "Mensagem para {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ Pensamento profundo", + "composer.thinkingTitle": "Pensamento profundo: o modelo mostra a cadeia de raciocínio", + "composer.thinkingRequired": "Pensamento profundo é obrigatório para este modelo", + "composer.search": "🌐 Busca inteligente", + "composer.searchTitle": "Busca inteligente: o modelo usa busca na web para informações atuais", + "composer.attach": "📎 Arquivo", + "composer.attachTitle": "Anexar um arquivo de texto para leitura", + "composer.voice": "🎙 Voz", + "composer.voiceTitle": "Gravar voz e inserir a transcrição na mensagem", + "composer.voiceStop": "■ Parar", + "composer.stop": "■", + "composer.stopTitle": "Parar execução", + "composer.voiceInstalling": "Instalando Parakeet V3. Isso pode levar alguns minutos...", + "composer.voiceRecording": "Gravando voz...", + "composer.voiceTranscribing": "Transcrevendo voz...", + "composer.voiceMissing": "O helper de voz não está instalado. Coloque ai-free-stt em {path} ou defina AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "Esta janela do navegador não suporta gravação de microfone.", + "composer.voiceNoSpeech": "Nenhuma fala foi reconhecida.", + "composer.defaultImageQuestion": "O que há nesta imagem? Descreva em detalhes.", + "composer.imageQuestionLabel": "(pergunta sobre imagem)", + "composer.uploadingImage": "Enviando e processando imagem{num}: {name}...", + "composer.thinkingStatus": "Pensando...", + "composer.writingStatus": "Escrevendo resposta…", + "composer.backgroundTask": "⚙️ A tarefa está rodando em segundo plano; você pode mudar para outro chat", + "file.svgUnsupported": "SVG (\"{name}\") não é suportado para reconhecimento. Salve como PNG ou JPG.", + "file.imageTooLarge": "A imagem \"{name}\" é grande demais ({mb} MB). Limite: 10 MB.", + "file.largeImageConfirm": "\"{name}\" tem {mb} MB. Arquivos grandes frequentemente retornam CONTENT_EMPTY no DeepSeek.\n\nEnviar mesmo assim?", + "file.readFailed": "Não foi possível ler \"{name}\": {message}", + "file.uploadMissingId": "O upload retornou sem fileId", + "file.qwenImageUnsupported": "O AI Free ainda não pode enviar imagens pelo transporte web do Qwen. Selecione DeepSeek V4 Vision ou ChatGPT para processar a imagem.", + "file.binaryUnsupported": "O arquivo \"{name}\" é binário ({ext}). Atualmente há suporte a arquivos de texto e imagens (PNG/JPG/GIF/WEBP).\n\nPDFs e documentos Office ainda não funcionam: precisam de uma fase separada.", + "file.textTooLarge": "O arquivo \"{name}\" é grande demais ({kb} KB). Limite para texto: {limitKb} KB.", + "file.looksBinary": "O arquivo \"{name}\" parece binário. Se for texto, renomeie para .txt.", + "file.remove": "Remover", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "Anexei arquivo{plural}. Leia e considere na sua resposta:", + "file.promptHeader": "Arquivo: {name} ({kb} KB)", + "file.promptQuestion": "Minha pergunta:", + "chat.delete": "Excluir chat", + "chat.running": "A tarefa /code está em execução", + "chat.messages": "{count} mensagens", + "chat.deleteConfirm": "Excluir chat?", + "chat.history": "Histórico: {file}", + "chat.you": "Você", + "chat.assistant": "Assistente", + "chat.reasoningProcess": "Processo de raciocínio", + "chat.reasoningThinking": "Pensando…", + "chat.question": "Pergunta", + "chat.system": "Sistema", + "install.title": "Instalar ferramenta", + "install.approve": "Instalar", + "install.reject": "Cancelar", + "install.running": "Instalação em andamento...", + "install.failed": "A instalação falhou.", + "settings.title": "Configurações", + "settings.interface": "Interface", + "settings.tabLanguage": "Idioma", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "Permissões", + "settings.language": "Idioma", + "settings.webSearchDefault": "Ativar busca inteligente por padrão", + "settings.voiceTitle": "Entrada de voz", + "settings.voiceProvider": "Modelo", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Pronto", + "settings.voiceMissing": "Não instalado", + "settings.voiceInstallHint": "O modelo e o runtime não vêm no plugin. Instale ai-free-stt separadamente ou defina AI_FREE_STT_BIN.", + "settings.languageSaved": "Idioma salvo. Recarregando a interface...", + "settings.loadFailed": "Não foi possível carregar as configurações: {message}", + "settings.low": "Baixo risco", + "settings.medium": "Risco médio", + "settings.high": "Alto risco", + "settings.apiTitle": "API compatível com OpenAI", + "settings.baseUrl": "URL base", + "settings.apiNote": "Em um cliente compatível com OpenAI, use a URL base e a chave Bearer do provedor necessário. Modelos: {models}", + "settings.anthropicApiTitle": "API compatível com Anthropic", + "settings.anthropicBaseUrl": "URL base", + "settings.anthropicEndpoint": "Endpoint de Messages", + "settings.anthropicAuth": "Cabeçalho de autenticação", + "settings.anthropicNote": "Em um cliente compatível com Anthropic, use a URL base sem /v1 e a mesma chave do provedor. POST /v1/messages é suportado. Modelos: {models}", + "settings.noKey": "Chave não criada", + "settings.keyCreated": "Chave criada", + "settings.createKey": "Criar", + "settings.keyReady": "Chave API de {label} pronta", + "settings.keyCreateFailed": "Não foi possível criar a chave API de {label}: {message}", + "settings.saveFailed": "Não foi possível salvar: {message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "Escuro", + "theme.light": "Claro", + "theme.contrast": "Contraste", + "theme.title": "Tema: {label}", + "shutdown.title": "CLI parado", + "shutdown.sub": "O servidor não responde mais. A janela será fechada automaticamente.", + "shutdown.gracefulTitle": "Parando ai-free…", + "shutdown.stoppingTasks": "Parando tarefas em segundo plano…", + "shutdown.closingBrowsers": "Fechando Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "Parando o servidor…", + "shutdown.stopped": "Parado", + "shutdown.stoppedSub": "A janela será fechada automaticamente.", + "welcome.title": "Bem-vindo ao AI Free", + "welcome.chooseProviders": "Escolha os provedores de IA que deseja conectar.", + "welcome.multi": "Escolha um ou vários. Você pode adicionar mais depois em Configurações.", + "welcome.prompt1": "Digite números separados por vírgulas (por exemplo \"1\" ou \"1,2\"),", + "welcome.prompt2": "ou pressione Enter para usar DeepSeek por padrão:", + "welcome.invalid": "⚠️ Não foi possível entender a escolha. Usando DeepSeek por padrão.", + "welcome.connecting": "Conectando: {providers}", + "welcome.loginFailed": "❌ Não foi possível conectar {provider}: {message}", + "welcome.retryLater": "Você pode tentar novamente mais tarde em Configurações na janela de chat.", + "welcome.done": "✅ Pronto. Iniciando a janela de chat...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/i18n/languages/ru.mjs b/packages/core/src/i18n/languages/ru.mjs new file mode 100644 index 0000000..61346a6 --- /dev/null +++ b/packages/core/src/i18n/languages/ru.mjs @@ -0,0 +1,315 @@ +export const language = { + code: "ru", + name: "Русский", + dir: "ltr", + messages: { + "app.workspace": "Рабочая область", + "sidebar.menu": "Меню", + "sidebar.plugins": "Плагины", + "sidebar.telegram": "Telegram", + "app.refresh": "Обновить", + "app.newChat": "+ Новый чат", + "app.noChat": "Чат не выбран", + "app.createChatHint": "Создай чат слева. Каждый чат можно использовать как отдельный проект или рабочий контекст.", + "app.firstMessage": "Напиши первое сообщение для этого проекта.", + "app.close": "Закрыть", + "app.loading": "Загрузка...", + "app.loadingShort": "Загружаю...", + "app.error": "Ошибка: {message}", + "app.requestFailed": "Запрос не удался", + "app.resizeChats": "Изменить ширину списка чатов", + "app.resizeComposer": "Изменить высоту формы ввода", + "newChat.title": "Новый чат", + "newChat.provider": "Провайдер", + "newChat.mode": "Режим (модель)", + "newChat.modeHint": "Режим зафиксируется при создании чата. Переключить потом нельзя - создавай новый чат в нужном режиме.", + "newChat.chatTitle": "Название чата (опционально)", + "newChat.chatTitlePlaceholder": "Например: рефакторинг auth", + "newChat.workspace": "Папка проекта", + "newChat.workspacePlaceholder": "/Users/.../project или ~/Projects/new-thing", + "newChat.browse": "📁 Обзор", + "newChat.up": "↑ Вверх", + "newChat.home": "🏠 Домой", + "newChat.newFolder": "➕ Новая папка", + "newChat.hidden": "Скрытые", + "newChat.pickFolder": "Выбрать эту папку", + "newChat.newFolderPlaceholder": "Имя новой папки", + "newChat.create": "Создать", + "newChat.cancel": "Отмена", + "newChat.createFolder": "Создать папку, если её ещё нет (только под твоим $HOME)", + "newChat.submit": "Создать чат", + "newChat.emptyFolderName": "Введи имя.", + "newChat.defaultProject": "по умолчанию", + "newChat.truncated": "Показаны не все папки - включи \"Скрытые\" или открой родительскую папку выше.", + "newChat.folderCount": "Папок: {total}{suffix}", + "newChat.hiddenSuffix": " (скрытые .папки - чекбокс \"Скрытые\")", + "newChat.folderShown": "Показано {shown} из {total} папок", + "newChat.tooManyFolders": "(слишком много папок - уточни путь или включи \"Скрытые\")", + "newChat.noSubfolders": "(нет подпапок - можно выбрать эту папку кнопкой \"Выбрать\")", + "newChat.truncatedInline": "Показаны первые {shown} из {total} - сузь путь или включи \"Скрытые\".", + "newChat.creating": "Создаю чат...", + "provider.connected": "✓ Подключено", + "provider.connectedTitle": "Вы авторизованы. Нажмите, если хотите войти под другим аккаунтом", + "provider.authorize": "🔑 Авторизоваться", + "provider.authorizeTitle": "Требуется авторизация. Нажмите, чтобы войти в аккаунт", + "provider.connectConfirm": "Подключить {label}?\n\nОткроется окно браузера - залогинься на сайте. Окно закроется само после входа.", + "provider.chatgptConnectConfirm": "Подключить {label}?\n\nДля надёжного входа один раз откроется обычный Chrome. После проверки активной сессии окно закроется автоматически, а ChatGPT продолжит работать внутри AI Free.", + "provider.chatgptEmbedLogin": "Завершите вход в открывшемся окне Chrome. Оно закроется автоматически только после проверки активной сессии.", + "provider.chatgptEmbedLoginTimeout": "Время ожидания входа в {label} истекло. Нажмите «Войти через Chrome» и повторите вход.", + "provider.connectedAlert": "{label} подключён.", + "provider.tokenMissing": "Логин завершён, но токен не найден. Попробуй ещё раз или: npm run login-{id}", + "provider.connectFailed": "Не удалось подключить {label}: {message}", + "provider.deepseekFast": "быстрый обычный чат", + "provider.deepseekExpert": "reasoning / R1", + "provider.deepseekVision": "распознавание изображений", + "provider.qwenDefault": "выбор модели в шапке чата", + "role.assistantDescription": "Обычный помощник", + "role.assistant": "Ассистент", + "role.assistant.label": "Ассистент", + "role.assistant.description": "Обычный помощник для чата и быстрых ответов.", + "role.prompt_builder.label": "Конструктор промптов", + "role.prompt_builder.description": "Уточняет задачу и превращает её в рабочий промпт для следующих шагов.", + "role.architect.label": "Архитектор", + "role.architect.description": "Проектирует решение, границы модулей, данные и риски.", + "role.developer.label": "Разработчик", + "role.developer.description": "Предлагает реализацию, файлы, шаги и технические детали.", + "role.tester.label": "Тестировщик", + "role.tester.description": "Ищет проверки, edge cases, регрессии и сценарии тестирования.", + "role.reviewer.label": "Ревьюер", + "role.reviewer.description": "Критически проверяет план/результат и ищет слабые места.", + "role.synthesizer.label": "Синтезатор", + "role.synthesizer.description": "Собирает выводы цепочки в короткий итог и следующие шаги.", + "topbar.model": "Модель", + "topbar.role": "Роль этого чата в pipeline", + "topbar.coderTitle": "Включить режим агента - модель сама создаёт/редактирует файлы", + "topbar.coder": "🛠 Кодер", + "topbar.coderOn": "🛠 Кодер ВКЛ", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP ВКЛ", + "topbar.pipeline": "Цепочка", + "topbar.pipelineOn": "Цепочка ВКЛ", + "topbar.hardwareTitle": "ESP / прошивка плат - включает аппаратный профиль агента", + "topbar.pipelineTitle": "Передавать сообщения по связям pipeline", + "topbar.memoryTitle": "Долговременная память агента — прошлые ошибки и решения", + "topbar.memory": "🧠 Память", + "topbar.memoryOn": "🧠 Память ВКЛ", + "topbar.autoSkillTitle": "Автоматически подбирать skill по задаче", + "topbar.autoSkill": "Skill авто", + "topbar.autoSkillOn": "Skill авто ВКЛ", + "topbar.skillTitle": "Skill для code-agent в этом чате", + "topbar.skillNone": "Skill: авто", + "topbar.flow": "Схема", + "topbar.flowTitle": "Схема цепочки", + "topbar.theme": "Сменить тему", + "topbar.settings": "Настройки / разрешённые команды", + "topbar.quit": "Выход — остановить приложение и закрыть Chrome", + "pipeline.title": "Схема цепочки", + "pipeline.makeLeader": "Сделать текущий чат главным", + "pipeline.addAgent": "+ Добавить подчинённого агента", + "pipeline.leaderSet": "Главный агент: {title}", + "pipeline.rolePrompt": "Роль нового агента: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Агент добавлен: {title}", + "agentDrawer.title": "Агент: память и skills", + "agentDrawer.sub": "Режимы, память, skills, браузер workspace", + "agentDrawer.tabAgent": "Агент", + "agentDrawer.tabBrowser": "Браузер", + "agentDrawer.modes": "Режимы", + "agentDrawer.memorySkills": "Память и skills", + "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — отдельный Chrome.", + "pipeline.sub": "Задай роль каждому чату и выбери следующий шаг.", + "pipeline.empty": "Создай несколько чатов, затем свяжи их здесь.", + "pipeline.end": "Конец", + "pipeline.user": "Пользователь", + "pipeline.model": "модель", + "composer.chooseChat": "Выбери чат слева...", + "composer.message": "Сообщение {label}...", + "composer.coderActive": "Режим Coder: опишите задачу для code-agent…", + "composer.thinking": "⚛ Глубокое мышление", + "composer.thinkingTitle": "Глубокое мышление - модель показывает chain-of-thought", + "composer.thinkingRequired": "Глубокое мышление обязательно для этой модели", + "composer.search": "🌐 Умный поиск", + "composer.searchTitle": "Умный поиск - модель использует веб-поиск для актуальной инфы", + "composer.attach": "📎 Файл", + "composer.attachTitle": "Прикрепить текстовый файл для чтения", + "composer.voice": "🎙 Голос", + "composer.voiceTitle": "Записать голос и вставить расшифровку в сообщение", + "composer.voiceStop": "■ Стоп", + "composer.stop": "■", + "composer.stopTitle": "Остановить выполнение", + "composer.voiceInstalling": "Устанавливаю Parakeet V3. Это может занять несколько минут...", + "composer.voiceRecording": "Идёт запись голоса...", + "composer.voiceTranscribing": "Расшифровываю голос...", + "composer.voiceMissing": "Голосовой helper не установлен. Поставь ai-free-stt в {path} или укажи AI_FREE_STT_BIN.", + "composer.voiceUnsupported": "Браузерное окно не поддерживает запись микрофона.", + "composer.voiceNoSpeech": "Не получилось распознать речь.", + "composer.defaultImageQuestion": "Что на этом изображении? Опиши подробно.", + "composer.imageQuestionLabel": "(вопрос по изображению)", + "composer.uploadingImage": "Заливаю и обрабатываю изображение{num}: {name}...", + "composer.thinkingStatus": "Думаю...", + "composer.writingStatus": "Пишет ответ…", + "composer.backgroundTask": "⚙️ Задача выполняется в фоне - можно перейти в другой чат", + "file.svgUnsupported": "SVG (\"{name}\") не поддерживается для распознавания. Сохрани как PNG или JPG.", + "file.imageTooLarge": "Картинка \"{name}\" слишком большая ({mb} МБ). Лимит 10 МБ.", + "file.largeImageConfirm": "\"{name}\" - {mb} МБ. Большие файлы часто получают CONTENT_EMPTY на DeepSeek.\n\nЗагрузить всё равно?", + "file.readFailed": "Не удалось прочитать \"{name}\": {message}", + "file.uploadMissingId": "Загрузка вернулась без fileId", + "file.qwenImageUnsupported": "AI Free пока не может передать изображение в веб-транспорт Qwen. Выберите DeepSeek V4 Vision или ChatGPT — там картинка будет обработана полностью.", + "file.binaryUnsupported": "Файл \"{name}\" - бинарный ({ext}). Сейчас поддерживаются текстовые файлы и изображения (PNG/JPG/GIF/WEBP).\n\nPDF и Office-документы пока не работают - для них нужна отдельная фаза.", + "file.textTooLarge": "Файл \"{name}\" слишком большой ({kb} КБ). Лимит {limitKb} КБ для текстовых.", + "file.looksBinary": "Файл \"{name}\" похож на бинарный. Если уверен, что текстовый - переименуй в .txt.", + "file.remove": "Удалить", + "file.sizeKb": "{kb} КБ", + "file.promptPrefix": "Я прикрепил файл{plural} - прочитай и учитывай при ответе:", + "file.promptHeader": "Файл: {name} ({kb} КБ)", + "file.promptQuestion": "Мой вопрос:", + "chat.delete": "Удалить чат", + "chat.running": "Выполняется /code-задача", + "chat.messages": "{count} сообщений", + "chat.deleteConfirm": "Удалить чат?", + "chat.history": "История: {file}", + "chat.you": "Вы", + "chat.assistant": "Ассистент", + "chat.reasoningProcess": "Процесс размышления", + "chat.reasoningThinking": "Размышляет…", + "chat.question": "Вопрос", + "chat.system": "Система", + "install.title": "Установить инструмент", + "install.approve": "Установить", + "install.reject": "Отмена", + "install.running": "Установка выполняется...", + "install.failed": "Установка завершилась ошибкой.", + "settings.title": "Настройки", + "settings.agentTitle": "Память и skills", + "settings.memoryDefault": "Память включена для новых чатов", + "settings.memoryDefaultDesc": "Агент ищет прошлые ошибки и решения перед /code-задачей.", + "settings.autoSkillDefault": "Auto-skill для новых чатов", + "settings.autoSkillDefaultDesc": "Подбирает skill по ключевым словам (review, fix, bug…).", + "settings.installedSkills": "Установленные skills", + "settings.noSkills": "Skills не найдены. Встроенные: code-review, bug-fix.", + "settings.installedPlugins": "Плагины (Codex / Claude Code)", + "settings.noPlugins": "Плагины не установлены.", + "settings.installPlugin": "Установить", + "settings.installPluginHint": "Поддержка .codex-plugin/plugin.json и .claude-plugin/plugin.json со skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo или URL GitHub", + "settings.pluginInstalled": "Плагин установлен", + "settings.pluginRemoved": "Плагин удалён", + "settings.uninstallPlugin": "Удалить плагин", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Настройки агента сохранены", + "settings.recentMemory": "Недавняя память", + "settings.recentMemoryHint": "Записи агента для текущего workspace. Можно удалить устаревшие.", + "settings.memoryEmpty": "Память пуста для этого проекта.", + "settings.memoryNoWorkspace": "без workspace", + "settings.deleteMemory": "Удалить запись", + "settings.memoryDeleted": "Запись памяти удалена", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS или JSON fallback)", + "agent.memoryUsed": "Память: использовано {count}", + "agent.graphUsed": "граф: {count}", + "agent.memoryPending": "память сохраняется…", + "agent.memorySaved": "сохранено {count}", + "agent.skillUsed": "skill: {skill}", + "settings.interface": "Интерфейс", + "settings.tabLanguage": "Язык", + "settings.tabAgent": "Агент", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Подключение Telegram", + "settings.telegramHint": "Укажите только токен бота. Chat ID можно оставить пустым: он привяжется автоматически после команды /start в Telegram.", + "settings.telegramEnabled": "Включить Telegram", + "settings.telegramEnabledDesc": "Сохранить настройки подключения.", + "settings.telegramBotToken": "Токен бота", + "settings.telegramChatId": "Chat ID (необязательно)", + "settings.telegramSave": "Сохранить", + "settings.telegramSaved": "Настройки Telegram сохранены", + "settings.tabUpdate": "Обновление", + "settings.tabApi": "API", + "settings.tabPermissions": "Разрешения", + "settings.tabStatus": "Статус", + "health.title": "Статус системы", + "health.refresh": "Обновить", + "health.copyReport": "Скопировать отчёт", + "health.ready": "Готов", + "health.needsLogin": "Нужен вход", + "health.copied": "Диагностический отчёт скопирован", + "health.copyManual": "Выделил отчёт, скопируй вручную", + "settings.language": "Язык", + "settings.webSearchDefault": "Включать умный поиск по умолчанию", + "settings.voiceTitle": "Голосовой ввод", + "settings.voiceProvider": "Модель", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "Готово", + "settings.voiceMissing": "Не установлен", + "settings.voiceInstallHint": "Модель и runtime не входят в плагин. Установи ai-free-stt отдельно или укажи AI_FREE_STT_BIN.", + "settings.languageSaved": "Язык сохранён. Перезагружаю интерфейс...", + "settings.loadFailed": "Не удалось загрузить настройки: {message}", + "settings.low": "Низкий риск", + "settings.medium": "Средний риск", + "settings.high": "Высокий риск", + "settings.apiTitle": "API, совместимое с OpenAI", + "settings.baseUrl": "Базовый URL", + "settings.apiNote": "В OpenAI-compatible клиенте укажи Base URL и Bearer API key нужного провайдера. Модели: {models}", + "settings.anthropicApiTitle": "API, совместимое с Anthropic", + "settings.anthropicBaseUrl": "Базовый URL", + "settings.anthropicEndpoint": "Эндпоинт Messages", + "settings.anthropicAuth": "Заголовок авторизации", + "settings.anthropicNote": "В Anthropic-compatible клиенте укажи Base URL без /v1 и API key того же провайдера. Поддерживается POST /v1/messages. Модели: {models}", + "settings.noKey": "Ключ не создан", + "settings.keyCreated": "Ключ создан", + "settings.createKey": "Создать", + "settings.keyReady": "{label} API key готов", + "settings.keyCreateFailed": "Не удалось создать {label} API key: {message}", + "settings.saveFailed": "Не удалось сохранить: {message}", + "settings.agentPermissions": "Разрешения агентов", + "settings.allowPythonModuleAndEval": "Разрешить python -m и python -c", + "settings.allowPythonModuleAndEvalDesc": "Позволяет агенту запускать Python-модули и inline-код. Включай только для доверенных проектов.", + "settings.allowShell": "Разрешить shell-команды (run_shell)", + "settings.allowShellDesc": "Пайпы, &&, перенаправления: grep -r foo . | head, find … | xargs и т.д.", + "permission.title": "Нужно разрешение", + "permission.description": "Агент запросил действие, которое отключено в настройках безопасности.", + "permission.settingsHint": "Можно включить это сейчас или позже в Settings → Разрешения.", + "permission.approve": "Включить", + "permission.reject": "Не включать", + "permission.enabled": "Разрешение включено. Повтори задачу.", + + "update.title": "Обновление десктопной версии", + "update.notChecked": "Проверка ещё не выполнялась.", + "update.check": "Проверить", + "update.install": "Обновить", + "update.checking": "Проверяю GitHub...", + "update.available": "Доступна новая версия.", + "update.upToDate": "Установлена актуальная версия.", + "update.gitRequired": "Новая версия есть, но автообновление доступно только для git-установки.", + "update.checkFailed": "Не удалось проверить обновление: {message}", + "update.installing": "Обновляю через git. Если npm доступен, зависимости установятся автоматически...", + "update.installed": "Обновление установлено. Перезапусти AI Free.", + "update.installFailed": "Не удалось обновить: {message}", + "update.confirm": "Запустить обновление AI Free?\n\nБудет выполнено: git pull --ff-only и npm install. Чаты в ~/.deepseek-cli/state.json не удаляются.", + "update.note": "Обновляется только код приложения в папке проекта. Чаты, настройки и авторизация хранятся отдельно в ~/.deepseek-cli и ~/.qwen-cli.", + "update.currentVersion": "Текущая", + "update.latestVersion": "Последняя", + "update.projectRoot": "Папка", + + "theme.dark": "Тёмная", + "theme.light": "Светлая", + "theme.contrast": "Контраст", + "theme.title": "Тема: {label}", + "shutdown.title": "CLI остановлен", + "shutdown.sub": "Сервер больше не отвечает. Окно закроется автоматически.", + "shutdown.gracefulTitle": "Останавливаем ai-free…", + "shutdown.stoppingTasks": "Останавливаем фоновые задачи…", + "shutdown.closingBrowsers": "Закрываем Chrome (ChatGPT / Qwen)…", + "shutdown.closingServer": "Останавливаем сервер…", + "shutdown.stopped": "Остановлено", + "shutdown.stoppedSub": "Окно закроется автоматически.", + "welcome.title": "Добро пожаловать в AI Free", + "welcome.chooseProviders": "Выбери AI-провайдеров, которых хочешь подключить.", + "welcome.multi": "Можно один, можно несколько - позже добавишь ещё через Settings.", + "welcome.prompt1": "Введи номера через запятую (например \"1\" или \"1,2\"),", + "welcome.prompt2": "или нажми Enter для DeepSeek по умолчанию:", + "welcome.invalid": "⚠️ Не понял выбор. Использую DeepSeek по умолчанию.", + "welcome.connecting": "Подключаю: {providers}", + "welcome.loginFailed": "❌ Не удалось подключить {provider}: {message}", + "welcome.retryLater": "Можно повторить позже через Settings в окне чатов.", + "welcome.done": "✅ Готово. Запускаю окно чатов...", + }, +}; diff --git a/packages/core/src/i18n/languages/zh.mjs b/packages/core/src/i18n/languages/zh.mjs new file mode 100644 index 0000000..adaee8a --- /dev/null +++ b/packages/core/src/i18n/languages/zh.mjs @@ -0,0 +1,313 @@ +export const language = { + code: "zh", + name: "中文", + dir: "ltr", + messages: { + "app.workspace": "工作区", + "sidebar.menu": "Menu", + "sidebar.plugins": "Plugins", + "sidebar.telegram": "Telegram", + "app.refresh": "刷新", + "app.newChat": "+ 新聊天", + "app.noChat": "未选择聊天", + "app.createChatHint": "在左侧创建聊天。每个聊天都可以作为单独的项目或工作上下文。", + "app.firstMessage": "为这个项目写第一条消息。", + "app.close": "关闭", + "app.loading": "加载中...", + "app.loadingShort": "正在加载...", + "app.error": "错误:{message}", + "app.requestFailed": "请求失败", + "app.resizeChats": "调整聊天列表宽度", + "app.resizeComposer": "调整输入区域高度", + "newChat.title": "新聊天", + "newChat.provider": "提供商", + "newChat.mode": "模式(模型)", + "newChat.modeHint": "模式在创建聊天时固定。之后如需切换,请用所需模式创建新聊天。", + "newChat.chatTitle": "聊天标题(可选)", + "newChat.chatTitlePlaceholder": "例如:auth 重构", + "newChat.workspace": "项目文件夹", + "newChat.workspacePlaceholder": "/Users/.../project 或 ~/Projects/new-thing", + "newChat.browse": "📁 浏览", + "newChat.up": "↑ 上级", + "newChat.home": "🏠 主页", + "newChat.newFolder": "➕ 新建文件夹", + "newChat.hidden": "隐藏", + "newChat.pickFolder": "选择此文件夹", + "newChat.newFolderPlaceholder": "新文件夹名称", + "newChat.create": "创建", + "newChat.cancel": "取消", + "newChat.createFolder": "如果文件夹不存在则创建(仅限你的 $HOME 下)", + "newChat.submit": "创建聊天", + "newChat.emptyFolderName": "请输入名称。", + "newChat.defaultProject": "默认", + "newChat.truncated": "未显示所有文件夹。启用“隐藏”或打开上级文件夹。", + "newChat.folderCount": "文件夹:{total}{suffix}", + "newChat.hiddenSuffix": "(隐藏的 .文件夹 - “隐藏”复选框)", + "newChat.folderShown": "显示 {shown} / {total} 个文件夹", + "newChat.tooManyFolders": "(文件夹太多 - 缩小路径或启用“隐藏”)", + "newChat.noSubfolders": "(没有子文件夹 - 可用“选择”按钮选择此文件夹)", + "newChat.truncatedInline": "显示前 {shown} / {total} 个。缩小路径或启用“隐藏”。", + "newChat.creating": "正在创建聊天...", + "provider.connected": "✓ 已连接", + "provider.connectedTitle": "你已登录。点击可使用其他账号", + "provider.authorize": "🔑 授权", + "provider.authorizeTitle": "需要登录。点击登录", + "provider.connectConfirm": "连接 {label}?\n\n将打开浏览器窗口。请在网站登录;登录后窗口会关闭。", + "provider.chatgptConnectConfirm": "连接 {label}?\n\n首次可靠登录会打开普通 Chrome 窗口。验证有效会话后窗口将自动关闭,ChatGPT 随后会继续在 AI Free 内运行。", + "provider.chatgptEmbedLogin": "请在 Chrome 窗口中完成登录。只有验证有效会话后,该窗口才会自动关闭。", + "provider.chatgptEmbedLoginTimeout": "登录 {label} 超时。请点击“使用 Chrome 登录”后重试。", + "provider.connectedAlert": "{label} 已连接。", + "provider.tokenMissing": "登录完成,但未找到令牌。请重试或运行:npm run login-{id}", + "provider.connectFailed": "无法连接 {label}:{message}", + "provider.deepseekFast": "快速普通聊天", + "provider.deepseekExpert": "推理 / R1", + "provider.deepseekVision": "图像识别", + "provider.qwenDefault": "在聊天顶部选择模型", + "role.assistantDescription": "普通助手", + "role.assistant": "助手", + "role.assistant.label": "助手", + "role.assistant.description": "用于聊天和快速回答的普通助手。", + "role.prompt_builder.label": "提示词构建器", + "role.prompt_builder.description": "澄清任务并将其转成后续步骤可执行的提示词。", + "role.architect.label": "架构师", + "role.architect.description": "设计方案、模块边界、数据和风险。", + "role.developer.label": "开发者", + "role.developer.description": "提出实现、文件、步骤和技术细节。", + "role.tester.label": "测试者", + "role.tester.description": "寻找检查项、边界情况、回归风险和测试场景。", + "role.reviewer.label": "审查者", + "role.reviewer.description": "批判性检查计划/结果并寻找薄弱点。", + "role.synthesizer.label": "汇总者", + "role.synthesizer.description": "将 pipeline 输出合并为简短总结和下一步。", + "topbar.model": "模型", + "topbar.role": "此聊天在 pipeline 中的角色", + "topbar.coderTitle": "启用代理模式:模型可创建和编辑文件", + "topbar.coder": "🛠 编码器", + "topbar.coderOn": "🛠 编码器开", + "topbar.hardware": "ESP", + "topbar.hardwareOn": "ESP 开", + "topbar.pipeline": "流程", + "topbar.pipelineOn": "流程开", + "topbar.hardwareTitle": "ESP / 板卡固件:启用硬件代理配置", + "topbar.pipelineTitle": "沿 pipeline 连接传递消息", + "topbar.flow": "流程", + "topbar.flowTitle": "Pipeline 流程", + "topbar.theme": "切换主题", + "topbar.settings": "设置 / 允许的命令", + "topbar.quit": "退出 — 停止应用并关闭 Chrome", + "pipeline.title": "Pipeline 流程", + "pipeline.makeLeader": "Make current chat the leader", + "pipeline.addAgent": "+ Add subordinate agent", + "pipeline.leaderSet": "Team leader: {title}", + "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", + "pipeline.agentAdded": "Agent added: {title}", + "agentDrawer.title": "Agent: memory & skills", + "agentDrawer.sub": "Modes, memory, skills, workspace browser", + "agentDrawer.tabAgent": "Agent", + "agentDrawer.tabBrowser": "Browser", + "agentDrawer.modes": "Modes", + "agentDrawer.memorySkills": "Memory & skills", + "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", + "pipeline.sub": "为每个聊天分配角色并选择下一步。", + "pipeline.empty": "创建多个聊天,然后在这里连接它们。", + "pipeline.end": "结束", + "pipeline.user": "用户", + "pipeline.model": "模型", + "composer.chooseChat": "在左侧选择聊天...", + "composer.message": "发送给 {label}...", + "composer.coderActive": "Coder mode: describe a code-agent task…", + "composer.thinking": "⚛ 深度思考", + "composer.thinkingTitle": "深度思考:模型显示思维链", + "composer.thinkingRequired": "此模型必须启用深度思考", + "composer.search": "🌐 智能搜索", + "composer.searchTitle": "智能搜索:模型使用网页搜索获取最新信息", + "composer.attach": "📎 文件", + "composer.attachTitle": "附加要读取的文本文件", + "composer.voice": "🎙 语音", + "composer.voiceTitle": "录音并把转写插入消息", + "composer.voiceStop": "■ 停止", + "composer.stop": "■", + "composer.stopTitle": "停止执行", + "composer.voiceInstalling": "正在安装 Parakeet V3。这可能需要几分钟...", + "composer.voiceRecording": "正在录音...", + "composer.voiceTranscribing": "正在转写语音...", + "composer.voiceMissing": "未安装语音 helper。请把 ai-free-stt 放到 {path},或设置 AI_FREE_STT_BIN。", + "composer.voiceUnsupported": "此浏览器窗口不支持麦克风录音。", + "composer.voiceNoSpeech": "未识别到语音。", + "composer.defaultImageQuestion": "这张图片里有什么?请详细描述。", + "composer.imageQuestionLabel": "(图片问题)", + "composer.uploadingImage": "正在上传并处理图片{num}:{name}...", + "composer.thinkingStatus": "正在思考...", + "composer.writingStatus": "正在撰写回复…", + "composer.backgroundTask": "⚙️ 任务正在后台运行;你可以切换到其他聊天", + "file.svgUnsupported": "不支持识别 SVG(\"{name}\")。请保存为 PNG 或 JPG。", + "file.imageTooLarge": "图片 \"{name}\" 太大({mb} MB)。限制:10 MB。", + "file.largeImageConfirm": "\"{name}\" 为 {mb} MB。大文件在 DeepSeek 上经常返回 CONTENT_EMPTY。\n\n仍要上传吗?", + "file.readFailed": "无法读取 \"{name}\":{message}", + "file.uploadMissingId": "上传返回时没有 fileId", + "file.qwenImageUnsupported": "AI Free 暂时无法通过 Qwen 网页传输发送图片。请选择 DeepSeek V4 Vision 或 ChatGPT 来完整处理图片。", + "file.binaryUnsupported": "文件 \"{name}\" 是二进制文件({ext})。当前支持文本文件和图片(PNG/JPG/GIF/WEBP)。\n\nPDF 和 Office 文档暂不支持,需要单独阶段。", + "file.textTooLarge": "文件 \"{name}\" 太大({kb} KB)。文本限制:{limitKb} KB。", + "file.looksBinary": "文件 \"{name}\" 看起来像二进制。如果确定是文本,请重命名为 .txt。", + "file.remove": "移除", + "file.sizeKb": "{kb} KB", + "file.promptPrefix": "我附加了文件{plural}。请阅读并在回答中考虑:", + "file.promptHeader": "文件:{name}({kb} KB)", + "file.promptQuestion": "我的问题:", + "chat.delete": "删除聊天", + "chat.running": "/code 任务正在运行", + "chat.messages": "{count} 条消息", + "chat.deleteConfirm": "删除聊天?", + "chat.history": "历史:{file}", + "chat.you": "你", + "chat.assistant": "助手", + "chat.reasoningProcess": "思考过程", + "chat.reasoningThinking": "思考中…", + "chat.question": "问题", + "chat.system": "系统", + "install.title": "安装工具", + "install.approve": "安装", + "install.reject": "取消", + "install.running": "正在安装...", + "install.failed": "安装失败。", + "settings.title": "设置", + "settings.interface": "界面", + "settings.tabLanguage": "语言", + "settings.tabUpdate": "Update", + "settings.tabApi": "API", + "settings.tabPermissions": "权限", + "settings.language": "语言", + "settings.webSearchDefault": "默认启用智能搜索", + "settings.voiceTitle": "语音输入", + "settings.voiceProvider": "模型", + "settings.voiceRuntime": "Runtime", + "settings.voiceReady": "已就绪", + "settings.voiceMissing": "未安装", + "settings.voiceInstallHint": "模型和 runtime 不随插件打包。请单独安装 ai-free-stt,或设置 AI_FREE_STT_BIN。", + "settings.languageSaved": "语言已保存。正在重新加载界面...", + "settings.loadFailed": "无法加载设置:{message}", + "settings.low": "低风险", + "settings.medium": "中等风险", + "settings.high": "高风险", + "settings.apiTitle": "OpenAI 兼容 API", + "settings.baseUrl": "Base URL", + "settings.apiNote": "在 OpenAI 兼容客户端中,填写 Base URL 和对应提供商的 Bearer API key。模型:{models}", + "settings.anthropicApiTitle": "Anthropic 兼容 API", + "settings.anthropicBaseUrl": "Base URL", + "settings.anthropicEndpoint": "Messages endpoint", + "settings.anthropicAuth": "认证 header", + "settings.anthropicNote": "在 Anthropic 兼容客户端中,使用不带 /v1 的 Base URL 和同一个提供商 API key。支持 POST /v1/messages。模型:{models}", + "settings.noKey": "尚未创建密钥", + "settings.keyCreated": "密钥已创建", + "settings.createKey": "创建", + "settings.keyReady": "{label} API key 已就绪", + "settings.keyCreateFailed": "无法创建 {label} API key:{message}", + "settings.saveFailed": "保存失败:{message}", + "settings.agentPermissions": "Agent permissions", + "settings.allowPythonModuleAndEval": "Allow python -m and python -c", + "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", + "settings.allowShell": "Allow shell commands (run_shell)", + "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", + "permission.title": "Permission required", + "permission.description": "The agent requested an action that is disabled by security settings.", + "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", + "permission.approve": "Enable", + "permission.reject": "Do not enable", + "permission.enabled": "Permission enabled. Repeat the task.", + "settings.tabStatus": "Status", + "health.title": "System status", + "health.refresh": "Refresh", + "health.copyReport": "Copy report", + "health.ready": "Ready", + "health.needsLogin": "Needs login", + "health.copied": "Diagnostic report copied", + "health.copyManual": "Report selected, copy it manually", + "update.title": "Desktop version update", + "update.notChecked": "No update check has run yet.", + "update.check": "Check", + "update.install": "Update", + "update.checking": "Checking GitHub...", + "update.available": "A new version is available.", + "update.upToDate": "You are on the latest version.", + "update.gitRequired": "A new version is available, but auto-update requires a git installation.", + "update.checkFailed": "Could not check for updates: {message}", + "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", + "update.installed": "Update installed. Restart AI Free.", + "update.installFailed": "Could not update: {message}", + "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", + "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", + "update.currentVersion": "Current", + "update.latestVersion": "Latest", + "update.projectRoot": "Folder", + "theme.dark": "深色", + "theme.light": "浅色", + "theme.contrast": "高对比", + "theme.title": "主题:{label}", + "shutdown.title": "CLI 已停止", + "shutdown.sub": "服务器不再响应。窗口将自动关闭。", + "shutdown.gracefulTitle": "正在停止 ai-free…", + "shutdown.stoppingTasks": "正在停止后台任务…", + "shutdown.closingBrowsers": "正在关闭 Chrome(ChatGPT / Qwen)…", + "shutdown.closingServer": "正在停止服务器…", + "shutdown.stopped": "已停止", + "shutdown.stoppedSub": "窗口将自动关闭。", + "welcome.title": "欢迎使用 AI Free", + "welcome.chooseProviders": "选择要连接的 AI 提供商。", + "welcome.multi": "可选择一个或多个。之后可在设置中继续添加。", + "welcome.prompt1": "输入用逗号分隔的编号(例如 \"1\" 或 \"1,2\"),", + "welcome.prompt2": "或按 Enter 默认使用 DeepSeek:", + "welcome.invalid": "⚠️ 无法理解选择。默认使用 DeepSeek。", + "welcome.connecting": "正在连接:{providers}", + "welcome.loginFailed": "❌ 无法连接 {provider}:{message}", + "welcome.retryLater": "你可以稍后在聊天窗口的设置中重试。", + "welcome.done": "✅ 完成。正在启动聊天窗口...", + "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", + "topbar.memory": "🧠 Memory", + "topbar.memoryOn": "🧠 Memory ON", + "topbar.autoSkillTitle": "Auto-pick a skill from the task text", + "topbar.autoSkill": "Auto skill", + "topbar.autoSkillOn": "Auto skill ON", + "topbar.skillTitle": "Skill for the code agent in this chat", + "topbar.skillNone": "Skill: auto", + "settings.tabAgent": "Agent", + "settings.tabTelegram": "Telegram", + "settings.telegramTitle": "Telegram connection", + "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", + "settings.telegramEnabled": "Enable Telegram", + "settings.telegramEnabledDesc": "Save connection settings.", + "settings.telegramBotToken": "Bot token", + "settings.telegramChatId": "Chat ID", + "settings.telegramSave": "Save", + "settings.telegramSaved": "Telegram settings saved", + "settings.agentTitle": "Memory and skills", + "settings.memoryDefault": "Memory enabled for new chats", + "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", + "settings.autoSkillDefault": "Auto-skill for new chats", + "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", + "settings.installedSkills": "Installed skills", + "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", + "settings.installedPlugins": "Plugins (Codex / Claude Code)", + "settings.noPlugins": "No plugins installed yet.", + "settings.installPlugin": "Install", + "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", + "settings.pluginInstallGithub": "user/repo or GitHub URL", + "settings.pluginInstalled": "Plugin installed", + "settings.pluginRemoved": "Plugin removed", + "settings.uninstallPlugin": "Remove plugin", + "settings.pluginSkillCount": "{count} skill(s)", + "settings.skillCommands": "Tools: {commands}", + "settings.agentSaved": "Agent settings saved", + "settings.recentMemory": "Recent memory", + "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", + "settings.memoryEmpty": "No memory entries for this project.", + "settings.memoryNoWorkspace": "no workspace", + "settings.deleteMemory": "Delete entry", + "settings.memoryDeleted": "Memory entry deleted", + "agent.memoryUsed": "Memory used: {count}", + "agent.graphUsed": "graph: {count}", + "agent.memoryPending": "memory saving…", + "agent.memorySaved": "saved {count}", + "agent.skillUsed": "skill: {skill}", + "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", + }, +}; diff --git a/packages/core/src/index.mjs b/packages/core/src/index.mjs new file mode 100644 index 0000000..445dfa6 --- /dev/null +++ b/packages/core/src/index.mjs @@ -0,0 +1,7 @@ +// @ai-free/core — основная точка входа общего ядра AI Free +export * from "./providers/model-catalog.mjs"; +export * from "./i18n/index.mjs"; +export * from "./code-agent/parser.mjs"; +export * from "./memory/paths.mjs"; +export * from "./memory/markdown.mjs"; +export * from "./memory/search/fts-query.mjs"; diff --git a/packages/core/src/memory/markdown.mjs b/packages/core/src/memory/markdown.mjs new file mode 100644 index 0000000..f634d40 --- /dev/null +++ b/packages/core/src/memory/markdown.mjs @@ -0,0 +1,95 @@ +// Markdown vault — человекочитаемые заметки с YAML frontmatter. + +import fs from "node:fs"; +import path from "node:path"; +import { MEMORY_VAULT } from "./paths.mjs"; + +export function serializeFrontmatter(fields = {}) { + const lines = []; + for (const [key, value] of Object.entries(fields)) { + if (value === undefined || value === null) continue; + if (Array.isArray(value)) { + lines.push(`${key}: [${value.map((v) => JSON.stringify(String(v))).join(", ")}]`); + continue; + } + if (typeof value === "object") { + lines.push(`${key}: ${JSON.stringify(value)}`); + continue; + } + lines.push(`${key}: ${String(value)}`); + } + return `${lines.join("\n")}\n`; +} + +export function parseFrontmatter(text) { + const raw = String(text || ""); + const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/); + if (!match) { + return { meta: {}, content: raw.trim() }; + } + + const meta = {}; + for (const line of match[1].split("\n")) { + const idx = line.indexOf(":"); + if (idx <= 0) continue; + const key = line.slice(0, idx).trim(); + let value = line.slice(idx + 1).trim(); + if (value.startsWith("[") && value.endsWith("]")) { + try { + meta[key] = JSON.parse(value.replace(/'/g, '"')); + } catch { + meta[key] = value.slice(1, -1).split(",").map((v) => v.trim().replace(/^"|"$/g, "")); + } + continue; + } + if ((value.startsWith("{") && value.endsWith("}")) || (value.startsWith("[") && value.endsWith("]"))) { + try { meta[key] = JSON.parse(value); continue; } catch {} + } + meta[key] = value; + } + + return { meta, content: match[2].trim() }; +} + +export function writeMemoryMarkdown(item) { + if (!item?.id) return null; + fs.mkdirSync(MEMORY_VAULT, { recursive: true }); + const filePath = path.join(MEMORY_VAULT, `${item.id}.md`); + const frontmatter = serializeFrontmatter({ + id: item.id, + type: item.type, + tags: item.tags || [], + workspace: item.workspace || "", + createdAt: item.createdAt, + updatedAt: item.updatedAt, + }); + fs.writeFileSync(filePath, `---\n${frontmatter}---\n\n${item.content || ""}\n`, "utf8"); + return filePath; +} + +export function readMemoryMarkdown(id) { + const filePath = path.join(MEMORY_VAULT, `${id}.md`); + if (!fs.existsSync(filePath)) return null; + const parsed = parseFrontmatter(fs.readFileSync(filePath, "utf8")); + return normalizeVaultItem(parsed.meta, parsed.content); +} + +export function deleteMemoryMarkdown(id) { + const filePath = path.join(MEMORY_VAULT, `${id}.md`); + if (!fs.existsSync(filePath)) return false; + fs.unlinkSync(filePath); + return true; +} + +function normalizeVaultItem(meta, content) { + return { + id: String(meta.id || ""), + type: String(meta.type || "note"), + content: String(content || ""), + tags: Array.isArray(meta.tags) ? meta.tags : [], + workspace: String(meta.workspace || ""), + meta: {}, + createdAt: String(meta.createdAt || new Date().toISOString()), + updatedAt: String(meta.updatedAt || meta.createdAt || new Date().toISOString()), + }; +} diff --git a/packages/core/src/memory/paths.mjs b/packages/core/src/memory/paths.mjs new file mode 100644 index 0000000..4f93e16 --- /dev/null +++ b/packages/core/src/memory/paths.mjs @@ -0,0 +1,19 @@ +// Пути хранилища памяти (~/.ai-free/memory/). + +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +export const MEMORY_BASE = process.env.AI_FREE_MEMORY_DIR + ? path.resolve(process.env.AI_FREE_MEMORY_DIR) + : path.join(os.homedir(), ".ai-free", "memory"); + +export const MEMORY_DB = path.join(MEMORY_BASE, "memory.db"); +export const MEMORY_VAULT = path.join(MEMORY_BASE, "vault"); +export const LEGACY_INDEX = path.join(MEMORY_BASE, "index.json"); +export const MIGRATION_FLAG = path.join(MEMORY_BASE, ".migrated-v2.json"); + +export function ensureMemoryDirs() { + fs.mkdirSync(MEMORY_BASE, { recursive: true }); + fs.mkdirSync(MEMORY_VAULT, { recursive: true }); +} diff --git a/packages/core/src/memory/search/fts-query.mjs b/packages/core/src/memory/search/fts-query.mjs new file mode 100644 index 0000000..79307db --- /dev/null +++ b/packages/core/src/memory/search/fts-query.mjs @@ -0,0 +1,33 @@ +// FTS query builder для SQLite FTS5. + +export function buildFtsMatchQuery(query = "") { + const tokens = String(query || "") + .trim() + .split(/\s+/) + .filter(Boolean) + .map((token) => token.replace(/["*]/g, "").trim()) + .filter(Boolean); + + if (!tokens.length) return ""; + + return tokens.map((token) => `"${token.replace(/"/g, '""')}"`).join(" OR "); +} + +export function rankFtsResults(rows, query = "") { + const q = String(query || "").toLowerCase(); + if (!q) return rows; + + return [...rows].sort((a, b) => scoreItem(b, q) - scoreItem(a, q)); +} + +function scoreItem(item, query) { + const content = String(item.content || "").toLowerCase(); + let score = 0; + if (content.includes(query)) score += 4; + for (const token of query.split(/\s+/).filter(Boolean)) { + if (content.includes(token)) score += 1; + if (item.type?.toLowerCase() === token) score += 2; + if (item.tags?.some((tag) => String(tag).toLowerCase() === token)) score += 2; + } + return score; +} diff --git a/packages/core/src/providers/model-catalog.mjs b/packages/core/src/providers/model-catalog.mjs new file mode 100644 index 0000000..d2d4d53 --- /dev/null +++ b/packages/core/src/providers/model-catalog.mjs @@ -0,0 +1,189 @@ +// Единый каталог моделей для desktop и расширения VS Code. +// Здесь храним и OpenAI-compatible id, и UI-метаданные, чтобы API, ACP и webview +// не расходились между собой после очередного обновления списка моделей. + +export const PROVIDER_CATALOG = { + deepseek: { + id: "deepseek", + label: "DeepSeek", + icon: "DS", + sub: "chat.deepseek.com", + defaultMode: "fast", + defaultModel: "deepseek-v4-flash", + modes: [ + { + id: "fast", + title: "DeepSeek v4 Flash", + sub: "быстрый обычный чат", + model: "deepseek-v4-flash", + }, + { + id: "expert", + title: "DeepSeek v4 Pro", + sub: "reasoning / R1", + model: "deepseek-v4-pro", + reasoning: true, + }, + { + id: "vision", + title: "DeepSeek v4 Vision", + sub: "распознавание изображений", + model: "deepseek-v4-vision", + vision: true, + }, + ], + models: [ + { id: "deepseek-v4-flash", label: "DeepSeek v4 Flash", apiModel: null }, + { id: "deepseek-v4-pro", label: "DeepSeek v4 Pro", apiModel: "expert", reasoning: true }, + { id: "deepseek-v4-vision", label: "DeepSeek v4 Vision", apiModel: "vision", vision: true }, + { id: "deepseek-chat", label: "DeepSeek Chat", apiModel: null, legacy: true }, + { id: "deepseek-reasoner", label: "DeepSeek Reasoner", apiModel: "expert", reasoning: true, legacy: true }, + ], + }, + qwen: { + id: "qwen", + label: "Qwen", + icon: "QW", + sub: "chat.qwen.ai", + defaultMode: "default", + defaultModel: "qwen3.7-plus", + modes: [ + { + id: "default", + title: "Qwen Chat", + sub: "выбор модели в шапке чата", + model: "qwen3.7-plus", + }, + ], + models: [ + { id: "qwen3.8-max", label: "Qwen3.8 Max", sub: "актуальная флагманская модель", reasoning: true, vision: true, search: true }, + { id: "qwen3.7-plus", label: "Qwen3.7 Plus", sub: "default, актуальный web-default" }, + { id: "qwen3.7-max", label: "Qwen3.7 MAX", sub: "мощнее, может требовать доступ" }, + { id: "qwen-latest-series-invite-beta-v24", label: "Qwen3.7 Max Preview", sub: "актуальный preview max" }, + { id: "qwen-latest-series-invite-beta-v16", label: "Qwen3.7 Plus Preview", sub: "актуальный preview plus" }, + { id: "qwen3.6-plus", label: "Qwen3.6 Plus", sub: "стабильный быстрый чат" }, + { id: "qwen3.6-max-preview", label: "Qwen3.6 Max Preview", sub: "предыдущий preview max" }, + { id: "qwen3.6-27b", label: "Qwen3.6 27B", sub: "быстрая средняя модель" }, + { id: "qwen3.6-35b-a3b", label: "Qwen3.6 35B A3B", sub: "MoE-модель" }, + { id: "qwen3.5-plus", label: "Qwen3.5 Plus", sub: "стабильный fallback" }, + { id: "qwen3.5-27b", label: "Qwen3.5 27B", sub: "стабильный fallback" }, + { id: "qwen3.5-35b-a3b", label: "Qwen3.5 35B A3B", sub: "стабильный fallback MoE" }, + { id: "qwen3-max-2026-01-23", label: "Qwen3 Max", sub: "актуальный Qwen3 Max" }, + { id: "qwen3-coder-plus", label: "Qwen3 Coder", sub: "coding model" }, + ], + }, + chatgpt: { + id: "chatgpt", + label: "ChatGPT", + icon: "GP", + sub: "chatgpt.com", + defaultMode: "default", + defaultModel: "gpt-5.5-instant", + modes: [ + { + id: "default", + title: "ChatGPT Web", + sub: "модели chatgpt.com сессии", + model: "gpt-5.5-instant", + }, + ], + models: [ + { id: "gpt-5.5-instant", label: "GPT-5.5 Instant", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "Мгновенный", "ChatGPT", "Auto", "Авто", "Default", "GPT-4o", "GPT-4o mini"] }, + { id: "gpt-5.6-sol-medium", label: "GPT-5.6 Sol · Medium", apiModel: "gpt-5.6-sol-medium", webLabels: ["Medium", "Средний", "Thinking", "Reasoning", "Рассуждения"], reasoning: true }, + { id: "gpt-5.6-sol-high", label: "GPT-5.6 Sol · High", apiModel: "gpt-5.6-sol-high", webLabels: ["High", "Высокий"], reasoning: true }, + { id: "gpt-5.6-sol-extra-high", label: "GPT-5.6 Sol · Extra High", apiModel: "gpt-5.6-sol-extra-high", webLabels: ["Extra High", "Очень высокий"], reasoning: true }, + { id: "gpt-5.6-sol-pro-standard", label: "GPT-5.6 Sol Pro · Standard", apiModel: "gpt-5.6-sol-pro-standard", webLabels: ["Pro Standard", "Pro стандартный", "Pro"], reasoning: true }, + { id: "gpt-5.6-sol-pro-extended", label: "GPT-5.6 Sol Pro · Extended", apiModel: "gpt-5.6-sol-pro-extended", webLabels: ["Pro Extended", "Pro расширенный"], reasoning: true }, + { id: "gpt-5.5", label: "GPT-5.5", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "ChatGPT", "GPT-4o", "Default"], legacy: true }, + { id: "gpt-4o", label: "GPT-4o", apiModel: "gpt-4o", webLabels: ["GPT-4o", "4o", "ChatGPT"], legacy: true }, + { id: "gpt-4o-mini", label: "GPT-4o mini", apiModel: "gpt-4o-mini", webLabels: ["GPT-4o mini", "4o mini", "ChatGPT"], legacy: true }, + { id: "o1-mini", label: "o1 mini", apiModel: "o1-mini", webLabels: ["o1-mini", "o1 mini", "o1"], reasoning: true, legacy: true }, + { id: "o3-mini", label: "o3 mini", apiModel: "o3-mini", webLabels: ["o3-mini", "o3 mini", "o3"], reasoning: true, legacy: true }, + ], + }, +}; + +export const OPENAI_COMPAT_MODELS = Object.values(PROVIDER_CATALOG).flatMap((provider) => + provider.models.map((model) => ({ + name: model.id, + provider: provider.id, + model: model.apiModel === undefined ? model.id : model.apiModel, + label: model.label, + reasoning: model.reasoning === true, + vision: model.vision === true, + legacy: model.legacy === true, + })), +); + +export function getProviderCatalog(providerId) { + return PROVIDER_CATALOG[providerId] || null; +} + +export function getProviderIds() { + return Object.keys(PROVIDER_CATALOG); +} + +export function getProviderDefaultModel(providerId, modeId = null) { + const provider = getProviderCatalog(providerId); + if (!provider) return null; + if (modeId) { + const mode = provider.modes.find((item) => item.id === modeId); + if (mode?.model) return mode.model; + } + return provider.defaultModel || provider.models[0]?.id || null; +} + +export function findProviderModel(providerId, modelId) { + const provider = getProviderCatalog(providerId); + if (!provider) return null; + return provider.models.find((model) => model.id === modelId) || null; +} + +export function findModel(name) { + return OPENAI_COMPAT_MODELS.find((model) => model.name === name); +} + +export function modelsList(overrides = {}) { + const models = Object.entries(PROVIDER_CATALOG).flatMap(([providerId, provider]) => { + const providerModels = overrides[providerId]?.models || provider.models; + return providerModels.map((model) => ({ + name: model.id, + provider: providerId, + })); + }); + return { + object: "list", + data: models.map((model) => ({ + id: model.name, + object: "model", + created: 1700000000, + owned_by: model.provider, + })), + }; +} + +export function uiModelCatalog(overrides = {}) { + return { + providers: Object.fromEntries( + Object.entries(PROVIDER_CATALOG).map(([providerId, provider]) => [ + providerId, + (() => { + const override = overrides[providerId] || {}; + const modes = override.modes || provider.modes; + const models = override.models || provider.models; + return { + label: provider.label, + icon: provider.icon, + sub: provider.sub, + defaultMode: provider.defaultMode, + defaultModel: override.defaultModel || provider.defaultModel, + modes: modes.map((mode) => ({ ...mode })), + models: models + .filter((model) => model.legacy !== true) + .map((model) => ({ ...model })), + }; + })(), + ]), + ), + }; +} diff --git a/plugin-for-vscode/src/code-agent/parser.mjs b/plugin-for-vscode/src/code-agent/parser.mjs index eb8012d..c97b8ce 100644 --- a/plugin-for-vscode/src/code-agent/parser.mjs +++ b/plugin-for-vscode/src/code-agent/parser.mjs @@ -1,143 +1,2 @@ -// Парсер JSON-tool-call'а из ответа LLM. -// Устойчив к markdown-блокам, тексту до/после JSON, нескольким JSON-объектам. -// -// 3 стратегии последовательно: -// 1. Пройтись по всем fenced-блокам ```...``` (любой язык: json, python, tool_calls), -// искать tool в содержимом каждого. -// 2. Вырезать ВСЕ fenced-блоки (они часто содержат пояснения на python и т.п.) -// и искать tool в остатке. Спасает Qwen-кейс: ```python ...``` + текст + -// {"tool":"write_file",...} снаружи блока. -// 3. Fallback — искать в исходном тексте целиком. - -export function parseToolCall(text) { - const trimmed = String(text || "").trim(); - - const xmlResult = findXmlToolCall(trimmed); - if (xmlResult) return xmlResult; - - const fencedBlocks = [ - ...trimmed.matchAll(/```[a-zA-Z0-9]*\n?([\s\S]*?)```/gi), - ]; - for (const match of fencedBlocks) { - const result = findToolCallInText(match[1].trim()); - if (result) return result; - } - - const stripped = trimmed.replace(/```[a-zA-Z0-9]*\n?[\s\S]*?```/gi, " "); - const result2 = findToolCallInText(stripped); - if (result2) return result2; - - return findToolCallInText(trimmed); -} - -function findXmlToolCall(text) { - const match = text.match(/([\s\S]*?)<\/tool_call>/i); - if (!match) return null; - - const tool = match[2]; - const rawBody = match[3].trim(); - if (!rawBody) return { tool }; - - try { - const parsed = JSON.parse(rawBody); - if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { - return { tool, ...parsed }; - } - } catch { - // Fall through to JSON extraction below. - } - - const json = extractFirstJsonObject(rawBody); - if (!json) return { tool }; - try { - const parsed = JSON.parse(json); - if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { - return { tool, ...parsed }; - } - } catch { - // ignore - } - return { tool }; -} - -// Ищет первый JSON-объект с полем "tool" (string) в тексте. -// Если первый {...} не tool-call — пропускает и берёт следующий. -function findToolCallInText(text) { - let offset = 0; - - while (offset < text.length) { - const start = text.indexOf("{", offset); - if (start < 0) return null; - - const candidate = extractFirstJsonObject(text.slice(start)); - if (!candidate) { - return null; - } - - try { - const parsed = normalizeToolCall(JSON.parse(candidate)); - if (parsed) return parsed; - } catch { - // Невалидный JSON — пробуем следующий объект. - } - - offset = start + Math.max(candidate.length, 1); - } - - return null; -} - -function normalizeToolCall(parsed) { - if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null; - if (typeof parsed.tool === "string") return parsed; - - // Some models emit ACP-ish or malformed tool JSON, for example: - // {"":"write_file","path":"x","content":""} - // {"name":"write_file","arguments":{"path":"x","content":""}} - const emptyKeyTool = parsed[""]; - if (typeof emptyKeyTool === "string") { - const { [""]: _ignored, ...rest } = parsed; - return { tool: emptyKeyTool, ...rest }; - } - - if (typeof parsed.name === "string" && parsed.arguments && typeof parsed.arguments === "object") { - return { tool: parsed.name, ...parsed.arguments }; - } - - return null; -} - -// Безопасный экстрактор первого валидного JSON-объекта из текста. -// Уважает строки и эскейпы, не путается на скобках внутри значений. -export function extractFirstJsonObject(text) { - const start = text.indexOf("{"); - if (start < 0) return null; - - let depth = 0; - let inString = false; - let escaped = false; - - for (let index = start; index < text.length; index += 1) { - const char = text[index]; - - if (inString) { - if (escaped) { - escaped = false; - } else if (char === "\\") { - escaped = true; - } else if (char === '"') { - inString = false; - } - continue; - } - - if (char === '"') inString = true; - else if (char === "{") depth += 1; - else if (char === "}") { - depth -= 1; - if (depth === 0) return text.slice(start, index + 1); - } - } - - return null; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/code-agent/parser.mjs"; diff --git a/plugin-for-vscode/src/i18n/index.mjs b/plugin-for-vscode/src/i18n/index.mjs index 51dd6e9..7230136 100644 --- a/plugin-for-vscode/src/i18n/index.mjs +++ b/plugin-for-vscode/src/i18n/index.mjs @@ -1,94 +1,2 @@ -import { language as ru } from "./languages/ru.mjs"; -import { language as en } from "./languages/en.mjs"; -import { language as es } from "./languages/es.mjs"; -import { language as pt } from "./languages/pt.mjs"; -import { language as fr } from "./languages/fr.mjs"; -import { language as de } from "./languages/de.mjs"; -import { language as zh } from "./languages/zh.mjs"; -import { language as hi } from "./languages/hi.mjs"; -import { language as ar } from "./languages/ar.mjs"; - -export const DEFAULT_LANGUAGE = "ru"; - -export const LANGUAGES = Object.freeze({ - ru, - en, - es, - pt, - fr, - de, - zh, - hi, - ar, -}); - -const ALIASES = Object.freeze({ - "pt-br": "pt", - "pt-pt": "pt", - "zh-cn": "zh", - "zh-hans": "zh", - "zh-tw": "zh", - "zh-hant": "zh", -}); - -export function normalizeLanguage(value) { - const raw = String(value || "") - .trim() - .replace(/\..*$/, "") - .replace(/_/g, "-") - .toLowerCase(); - if (!raw) return DEFAULT_LANGUAGE; - const exact = ALIASES[raw] || raw; - if (LANGUAGES[exact]) return exact; - const short = exact.split("-")[0]; - return LANGUAGES[short] ? short : DEFAULT_LANGUAGE; -} - -export function resolveUserLanguage(explicitLanguage = "") { - return normalizeLanguage( - explicitLanguage - || process.env.AI_FREE_LANG - || process.env.LC_ALL - || process.env.LC_MESSAGES - || process.env.LANG - || DEFAULT_LANGUAGE, - ); -} - -export function getLanguageMeta(languageCode = DEFAULT_LANGUAGE) { - const language = LANGUAGES[normalizeLanguage(languageCode)] || LANGUAGES[DEFAULT_LANGUAGE]; - return { - code: language.code, - name: language.name, - dir: language.dir || "ltr", - }; -} - -export function getMessages(languageCode = DEFAULT_LANGUAGE) { - const code = normalizeLanguage(languageCode); - const base = code === DEFAULT_LANGUAGE - ? LANGUAGES[DEFAULT_LANGUAGE].messages - : LANGUAGES.en.messages; - return { - ...base, - ...(LANGUAGES[code]?.messages || {}), - }; -} - -export function formatMessage(template, vars = {}) { - return String(template || "").replace(/\{([a-zA-Z0-9_]+)\}/g, (match, key) => ( - Object.prototype.hasOwnProperty.call(vars, key) ? String(vars[key]) : match - )); -} - -export function createTranslator(languageCode = DEFAULT_LANGUAGE) { - const language = getLanguageMeta(languageCode); - const messages = getMessages(language.code); - return { - language, - messages, - t(key, vars = {}) { - return formatMessage(messages[key] || key, vars); - }, - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/index.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/ar.mjs b/plugin-for-vscode/src/i18n/languages/ar.mjs index 6bba4bb..79eb79d 100644 --- a/plugin-for-vscode/src/i18n/languages/ar.mjs +++ b/plugin-for-vscode/src/i18n/languages/ar.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "ar", - name: "العربية", - dir: "rtl", - messages: { - "app.workspace": "مساحة العمل", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "تحديث", - "app.newChat": "+ محادثة جديدة", - "app.noChat": "لم يتم اختيار محادثة", - "app.createChatHint": "أنشئ محادثة من اليسار. يمكن أن تكون كل محادثة مشروعا أو سياق عمل منفصلا.", - "app.firstMessage": "اكتب أول رسالة لهذا المشروع.", - "app.close": "إغلاق", - "app.loading": "جار التحميل...", - "app.loadingShort": "جارٍ التحميل...", - "app.error": "خطأ: {message}", - "app.requestFailed": "فشل الطلب", - "app.resizeChats": "تغيير عرض قائمة المحادثات", - "app.resizeComposer": "تغيير ارتفاع منطقة الإدخال", - "newChat.title": "محادثة جديدة", - "newChat.provider": "المزوّد", - "newChat.mode": "الوضع (النموذج)", - "newChat.modeHint": "يتم تثبيت الوضع عند إنشاء المحادثة. للتبديل لاحقًا، أنشئ محادثة جديدة بالوضع المطلوب.", - "newChat.chatTitle": "عنوان المحادثة (اختياري)", - "newChat.chatTitlePlaceholder": "مثال: إعادة تنظيم auth", - "newChat.workspace": "مجلد المشروع", - "newChat.workspacePlaceholder": "/Users/.../project أو ~/Projects/new-thing", - "newChat.browse": "📁 تصفح", - "newChat.up": "↑ للأعلى", - "newChat.home": "🏠 الرئيسية", - "newChat.newFolder": "➕ مجلد جديد", - "newChat.hidden": "مخفي", - "newChat.pickFolder": "اختر هذا المجلد", - "newChat.newFolderPlaceholder": "اسم المجلد الجديد", - "newChat.create": "إنشاء", - "newChat.cancel": "إلغاء", - "newChat.createFolder": "إنشاء المجلد إذا لم يكن موجودًا (فقط داخل $HOME الخاص بك)", - "newChat.submit": "إنشاء محادثة", - "newChat.emptyFolderName": "أدخل اسمًا.", - "newChat.defaultProject": "افتراضي", - "newChat.truncated": "لا تظهر كل المجلدات. فعّل \"المخفية\" أو افتح المجلد الأعلى.", - "newChat.folderCount": "المجلدات: {total}{suffix}", - "newChat.hiddenSuffix": " (مجلدات . مخفية - مربع \"المخفية\")", - "newChat.folderShown": "يتم عرض {shown} من {total} مجلدات", - "newChat.tooManyFolders": "(مجلدات كثيرة جدًا - ضيّق المسار أو فعّل \"المخفية\")", - "newChat.noSubfolders": "(لا توجد مجلدات فرعية - يمكنك اختيار هذا المجلد بزر \"اختيار\")", - "newChat.truncatedInline": "يتم عرض أول {shown} من {total}. ضيّق المسار أو فعّل \"المخفية\".", - "newChat.creating": "جارٍ إنشاء المحادثة...", - "provider.connected": "✓ متصل", - "provider.connectedTitle": "أنت مسجل الدخول. انقر لاستخدام حساب آخر", - "provider.authorize": "🔑 تسجيل الدخول", - "provider.authorizeTitle": "تسجيل الدخول مطلوب. انقر لتسجيل الدخول", - "provider.connectConfirm": "هل تريد توصيل {label}؟\n\nستفتح نافذة متصفح. سجّل الدخول في الموقع؛ ستُغلق النافذة بعد ذلك.", - "provider.chatgptConnectConfirm": "هل تريد توصيل {label}؟\n\nستُفتح نافذة Chrome عادية مرة واحدة لتسجيل دخول موثوق. ستُغلق تلقائياً بعد التحقق من الجلسة النشطة، ثم سيواصل ChatGPT العمل داخل AI Free.", - "provider.chatgptEmbedLogin": "أكمل تسجيل الدخول في نافذة Chrome. لن تُغلق تلقائياً إلا بعد التحقق من الجلسة النشطة.", - "provider.chatgptEmbedLoginTimeout": "انتهت مهلة تسجيل الدخول إلى {label}. اضغط «تسجيل الدخول عبر Chrome» وحاول مرة أخرى.", - "provider.connectedAlert": "تم توصيل {label}.", - "provider.tokenMissing": "اكتمل تسجيل الدخول، لكن لم يتم العثور على token. حاول مرة أخرى أو شغّل: npm run login-{id}", - "provider.connectFailed": "تعذر توصيل {label}: {message}", - "provider.deepseekFast": "محادثة عادية سريعة", - "provider.deepseekExpert": "استدلال / R1", - "provider.deepseekVision": "تعرف على الصور", - "provider.qwenDefault": "اختر النموذج من رأس المحادثة", - "role.assistantDescription": "مساعد عادي", - "role.assistant": "المساعد", - "role.assistant.label": "المساعد", - "role.assistant.description": "مساعد عادي للمحادثة والإجابات السريعة.", - "role.prompt_builder.label": "منشئ المطالبات", - "role.prompt_builder.description": "يوضح المهمة ويحوّلها إلى prompt عملي للخطوات التالية.", - "role.architect.label": "المعماري", - "role.architect.description": "يصمم الحل وحدود الوحدات والبيانات والمخاطر.", - "role.developer.label": "المطور", - "role.developer.description": "يقترح التنفيذ والملفات والخطوات والتفاصيل التقنية.", - "role.tester.label": "المختبر", - "role.tester.description": "يبحث عن الفحوصات والحالات الحدية والانحدارات وسيناريوهات الاختبار.", - "role.reviewer.label": "المراجع", - "role.reviewer.description": "يفحص الخطة/النتيجة نقديًا ويبحث عن نقاط الضعف.", - "role.synthesizer.label": "المُلخّص", - "role.synthesizer.description": "يجمع مخرجات pipeline في ملخص قصير وخطوات تالية.", - "topbar.model": "النموذج", - "topbar.role": "دور هذه المحادثة في pipeline", - "topbar.coderTitle": "تفعيل وضع الوكيل: يمكن للنموذج إنشاء الملفات وتعديلها", - "topbar.coder": "🛠 المبرمج", - "topbar.coderOn": "🛠 المبرمج ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "التدفق", - "topbar.pipelineOn": "التدفق ON", - "topbar.hardwareTitle": "ESP / firmware للوحات: يفعّل ملف وكيل العتاد", - "topbar.pipelineTitle": "تمرير الرسائل عبر روابط pipeline", - "topbar.flow": "التدفق", - "topbar.flowTitle": "تدفق pipeline", - "topbar.theme": "تغيير السمة", - "topbar.settings": "الإعدادات / الأوامر المسموحة", - "topbar.quit": "خروج — إيقاف التطبيق وإغلاق Chrome", - "pipeline.title": "تدفق pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "عيّن دورًا لكل محادثة واختر الخطوة التالية.", - "pipeline.empty": "أنشئ عدة محادثات ثم اربطها هنا.", - "pipeline.end": "النهاية", - "pipeline.user": "المستخدم", - "pipeline.model": "النموذج", - "composer.chooseChat": "اختر محادثة من اليسار...", - "composer.message": "رسالة إلى {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ تفكير عميق", - "composer.thinkingTitle": "تفكير عميق: يعرض النموذج سلسلة التفكير", - "composer.thinkingRequired": "التفكير العميق مطلوب لهذا النموذج", - "composer.search": "🌐 بحث ذكي", - "composer.searchTitle": "بحث ذكي: يستخدم النموذج بحث الويب للمعلومات الحديثة", - "composer.attach": "📎 ملف", - "composer.attachTitle": "إرفاق ملف نصي للقراءة", - "composer.voice": "🎙 صوت", - "composer.voiceTitle": "تسجيل الصوت وإدراج التفريغ في الرسالة", - "composer.voiceStop": "■ إيقاف", - "composer.stop": "■", - "composer.stopTitle": "إيقاف التنفيذ", - "composer.voiceInstalling": "جارٍ تثبيت Parakeet V3. قد يستغرق ذلك بضع دقائق...", - "composer.voiceRecording": "جارٍ تسجيل الصوت...", - "composer.voiceTranscribing": "جارٍ تفريغ الصوت...", - "composer.voiceMissing": "مساعد الصوت غير مثبت. ضع ai-free-stt في {path} أو عيّن AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "نافذة المتصفح هذه لا تدعم تسجيل الميكروفون.", - "composer.voiceNoSpeech": "لم يتم التعرف على كلام.", - "composer.defaultImageQuestion": "ماذا يوجد في هذه الصورة؟ صفها بالتفصيل.", - "composer.imageQuestionLabel": "(سؤال عن الصورة)", - "composer.uploadingImage": "جارٍ رفع ومعالجة الصورة{num}: {name}...", - "composer.thinkingStatus": "جارٍ التفكير...", - "composer.writingStatus": "يكتب الرد…", - "composer.backgroundTask": "⚙️ المهمة تعمل في الخلفية؛ يمكنك الانتقال إلى محادثة أخرى", - "file.svgUnsupported": "SVG (\"{name}\") غير مدعوم للتعرف. احفظه كـ PNG أو JPG.", - "file.imageTooLarge": "الصورة \"{name}\" كبيرة جدًا ({mb} MB). الحد: 10 MB.", - "file.largeImageConfirm": "\"{name}\" بحجم {mb} MB. الملفات الكبيرة غالبًا ترجع CONTENT_EMPTY في DeepSeek.\n\nهل تريد الرفع على أي حال؟", - "file.readFailed": "تعذرت قراءة \"{name}\": {message}", - "file.uploadMissingId": "عاد الرفع بدون fileId", - "file.qwenImageUnsupported": "لا يستطيع AI Free حالياً إرسال الصور عبر ناقل Qwen على الويب. اختر DeepSeek V4 Vision أو ChatGPT لمعالجة الصورة بالكامل.", - "file.binaryUnsupported": "الملف \"{name}\" ثنائي ({ext}). المدعوم حاليًا ملفات النص والصور (PNG/JPG/GIF/WEBP).\n\nPDF ومستندات Office لا تعمل بعد وتحتاج مرحلة منفصلة.", - "file.textTooLarge": "الملف \"{name}\" كبير جدًا ({kb} KB). حد النص: {limitKb} KB.", - "file.looksBinary": "الملف \"{name}\" يبدو ثنائيًا. إذا كان نصًا، أعد تسميته إلى .txt.", - "file.remove": "إزالة", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "أرفقت ملف{plural}. اقرأه وخذه في الاعتبار في إجابتك:", - "file.promptHeader": "الملف: {name} ({kb} KB)", - "file.promptQuestion": "سؤالي:", - "chat.delete": "حذف المحادثة", - "chat.running": "مهمة /code قيد التنفيذ", - "chat.messages": "{count} رسالة", - "chat.deleteConfirm": "حذف المحادثة؟", - "chat.history": "السجل: {file}", - "chat.you": "أنت", - "chat.assistant": "المساعد", - "chat.reasoningProcess": "عملية التفكير", - "chat.reasoningThinking": "يفكر…", - "chat.question": "السؤال", - "chat.system": "النظام", - "install.title": "تثبيت أداة", - "install.approve": "تثبيت", - "install.reject": "إلغاء", - "install.running": "التثبيت جارٍ...", - "install.failed": "فشل التثبيت.", - "settings.title": "الإعدادات", - "settings.interface": "الواجهة", - "settings.tabLanguage": "اللغة", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "الأذونات", - "settings.language": "اللغة", - "settings.webSearchDefault": "تفعيل البحث الذكي افتراضيًا", - "settings.voiceTitle": "إدخال صوتي", - "settings.voiceProvider": "النموذج", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "جاهز", - "settings.voiceMissing": "غير مثبت", - "settings.voiceInstallHint": "النموذج وruntime غير مرفقين مع plugin. ثبّت ai-free-stt بشكل منفصل أو عيّن AI_FREE_STT_BIN.", - "settings.languageSaved": "تم حفظ اللغة. جارٍ إعادة تحميل الواجهة...", - "settings.loadFailed": "تعذر تحميل الإعدادات: {message}", - "settings.low": "خطر منخفض", - "settings.medium": "خطر متوسط", - "settings.high": "خطر عال", - "settings.apiTitle": "API متوافقة مع OpenAI", - "settings.baseUrl": "Base URL", - "settings.apiNote": "في عميل متوافق مع OpenAI، استخدم Base URL ومفتاح Bearer API للمزوّد المطلوب. النماذج: {models}", - "settings.anthropicApiTitle": "API متوافقة مع Anthropic", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "ترويسة المصادقة", - "settings.anthropicNote": "في عميل متوافق مع Anthropic، استخدم Base URL بدون /v1 ونفس مفتاح المزوّد. POST /v1/messages مدعوم. النماذج: {models}", - "settings.noKey": "لم يتم إنشاء المفتاح", - "settings.keyCreated": "تم إنشاء المفتاح", - "settings.createKey": "إنشاء", - "settings.keyReady": "مفتاح API لـ {label} جاهز", - "settings.keyCreateFailed": "تعذر إنشاء مفتاح API لـ {label}: {message}", - "settings.saveFailed": "تعذر الحفظ: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "داكن", - "theme.light": "فاتح", - "theme.contrast": "تباين", - "theme.title": "السمة: {label}", - "shutdown.title": "توقف CLI", - "shutdown.sub": "الخادم لا يستجيب. ستغلق النافذة تلقائيا.", - "shutdown.gracefulTitle": "جارٍ إيقاف ai-free…", - "shutdown.stoppingTasks": "إيقاف المهام في الخلفية…", - "shutdown.closingBrowsers": "إغلاق Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "إيقاف الخادم…", - "shutdown.stopped": "تم الإيقاف", - "shutdown.stoppedSub": "ستغلق النافذة تلقائيا.", - "welcome.title": "مرحبا بك في AI Free", - "welcome.chooseProviders": "اختر مزودي الذكاء الاصطناعي الذين تريد ربطهم.", - "welcome.multi": "اختر واحدًا أو أكثر. يمكنك إضافة المزيد لاحقًا من الإعدادات.", - "welcome.prompt1": "أدخل أرقامًا مفصولة بفواصل (مثل \"1\" أو \"1,2\"),", - "welcome.prompt2": "أو اضغط Enter لاستخدام DeepSeek افتراضيًا:", - "welcome.invalid": "⚠️ تعذر فهم الاختيار. سيتم استخدام DeepSeek افتراضيًا.", - "welcome.connecting": "جارٍ التوصيل: {providers}", - "welcome.loginFailed": "❌ تعذر توصيل {provider}: {message}", - "welcome.retryLater": "يمكنك المحاولة لاحقًا من الإعدادات في نافذة المحادثة.", - "welcome.done": "✅ تم. جار تشغيل نافذة المحادثة...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/ar.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/de.mjs b/plugin-for-vscode/src/i18n/languages/de.mjs index cc4edd7..44d1716 100644 --- a/plugin-for-vscode/src/i18n/languages/de.mjs +++ b/plugin-for-vscode/src/i18n/languages/de.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "de", - name: "Deutsch", - dir: "ltr", - messages: { - "app.workspace": "Arbeitsbereich", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Aktualisieren", - "app.newChat": "+ Neuer Chat", - "app.noChat": "Kein Chat ausgewählt", - "app.createChatHint": "Erstelle links einen Chat. Jeder Chat kann ein eigenes Projekt oder ein eigener Arbeitskontext sein.", - "app.firstMessage": "Schreibe die erste Nachricht für dieses Projekt.", - "app.close": "Schließen", - "app.loading": "Laden...", - "app.loadingShort": "Lade...", - "app.error": "Fehler: {message}", - "app.requestFailed": "Anfrage fehlgeschlagen", - "app.resizeChats": "Chatliste verbreitern/verkleinern", - "app.resizeComposer": "Eingabebereich in der Höhe ändern", - "newChat.title": "Neuer Chat", - "newChat.provider": "Anbieter", - "newChat.mode": "Modus (Modell)", - "newChat.modeHint": "Der Modus wird beim Erstellen des Chats festgelegt. Zum späteren Wechsel einen neuen Chat im gewünschten Modus erstellen.", - "newChat.chatTitle": "Chat-Titel (optional)", - "newChat.chatTitlePlaceholder": "Beispiel: Auth-Refactoring", - "newChat.workspace": "Projektordner", - "newChat.workspacePlaceholder": "/Users/.../project oder ~/Projects/new-thing", - "newChat.browse": "📁 Durchsuchen", - "newChat.up": "↑ Nach oben", - "newChat.home": "🏠 Start", - "newChat.newFolder": "➕ Neuer Ordner", - "newChat.hidden": "Versteckte", - "newChat.pickFolder": "Diesen Ordner auswählen", - "newChat.newFolderPlaceholder": "Name des neuen Ordners", - "newChat.create": "Erstellen", - "newChat.cancel": "Abbrechen", - "newChat.createFolder": "Ordner erstellen, falls er nicht existiert (nur unter Ihrem $HOME)", - "newChat.submit": "Chat erstellen", - "newChat.emptyFolderName": "Geben Sie einen Namen ein.", - "newChat.defaultProject": "Standard", - "newChat.truncated": "Nicht alle Ordner werden angezeigt. Aktivieren Sie \"Versteckt\" oder öffnen Sie den übergeordneten Ordner.", - "newChat.folderCount": "Ordner: {total}{suffix}", - "newChat.hiddenSuffix": " (versteckte .Ordner - Checkbox \"Versteckt\")", - "newChat.folderShown": "Zeige {shown} von {total} Ordnern", - "newChat.tooManyFolders": "(zu viele Ordner - Pfad eingrenzen oder \"Versteckt\" aktivieren)", - "newChat.noSubfolders": "(keine Unterordner - dieser Ordner kann mit \"Auswählen\" gewählt werden)", - "newChat.truncatedInline": "Zeige die ersten {shown} von {total}. Pfad eingrenzen oder \"Versteckt\" aktivieren.", - "newChat.creating": "Chat wird erstellt...", - "provider.connected": "✓ Verbunden", - "provider.connectedTitle": "Sie sind angemeldet. Klicken, um ein anderes Konto zu verwenden", - "provider.authorize": "🔑 Autorisieren", - "provider.authorizeTitle": "Anmeldung erforderlich. Klicken zum Anmelden", - "provider.connectConfirm": "{label} verbinden?\n\nEin Browserfenster wird geöffnet. Melden Sie sich auf der Website an; das Fenster schließt danach.", - "provider.chatgptConnectConfirm": "{label} verbinden?\n\nFür eine zuverlässige Anmeldung wird einmalig ein normales Chrome-Fenster geöffnet. Nach Prüfung der aktiven Sitzung wird es automatisch geschlossen und ChatGPT läuft in AI Free weiter.", - "provider.chatgptEmbedLogin": "Schließen Sie die Anmeldung im Chrome-Fenster ab. Es wird erst nach Prüfung der aktiven Sitzung automatisch geschlossen.", - "provider.chatgptEmbedLoginTimeout": "Zeitüberschreitung bei der Anmeldung bei {label}. Klicken Sie auf „Mit Chrome anmelden“ und versuchen Sie es erneut.", - "provider.connectedAlert": "{label} verbunden.", - "provider.tokenMissing": "Anmeldung abgeschlossen, aber kein Token gefunden. Erneut versuchen oder ausführen: npm run login-{id}", - "provider.connectFailed": "{label} konnte nicht verbunden werden: {message}", - "provider.deepseekFast": "schneller normaler Chat", - "provider.deepseekExpert": "Reasoning / R1", - "provider.deepseekVision": "Bilderkennung", - "provider.qwenDefault": "Modell im Chat-Kopf wählen", - "role.assistantDescription": "Normaler Assistent", - "role.assistant": "Assistent", - "role.assistant.label": "Assistent", - "role.assistant.description": "Normaler Assistent für Chat und schnelle Antworten.", - "role.prompt_builder.label": "Prompt-Ersteller", - "role.prompt_builder.description": "Klärt die Aufgabe und macht daraus einen Arbeits-Prompt für die nächsten Schritte.", - "role.architect.label": "Architekt", - "role.architect.description": "Entwirft Lösung, Modulgrenzen, Daten und Risiken.", - "role.developer.label": "Entwickler", - "role.developer.description": "Schlägt Implementierung, Dateien, Schritte und technische Details vor.", - "role.tester.label": "Tester", - "role.tester.description": "Findet Prüfungen, Grenzfälle, Regressionen und Testszenarien.", - "role.reviewer.label": "Prüfer", - "role.reviewer.description": "Prüft Plan/Ergebnis kritisch und sucht Schwachstellen.", - "role.synthesizer.label": "Synthesizer", - "role.synthesizer.description": "Fasst Pipeline-Ausgaben in eine kurze Zusammenfassung und nächste Schritte zusammen.", - "topbar.model": "Modell", - "topbar.role": "Rolle dieses Chats in der Pipeline", - "topbar.coderTitle": "Agentenmodus aktivieren: Das Modell kann Dateien erstellen und bearbeiten", - "topbar.coder": "🛠 Coder", - "topbar.coderOn": "🛠 Coder EIN", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP EIN", - "topbar.pipeline": "Ablauf", - "topbar.pipelineOn": "Ablauf EIN", - "topbar.hardwareTitle": "ESP / Board-Firmware: aktiviert das Hardware-Agentenprofil", - "topbar.pipelineTitle": "Nachrichten entlang der Pipeline-Verbindungen weitergeben", - "topbar.flow": "Ablauf", - "topbar.flowTitle": "Pipeline-Ablauf", - "topbar.theme": "Theme wechseln", - "topbar.settings": "Einstellungen / erlaubte Befehle", - "topbar.quit": "Beenden — App stoppen und Chrome schließen", - "pipeline.title": "Pipeline-Ablauf", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Jedem Chat eine Rolle zuweisen und den nächsten Schritt wählen.", - "pipeline.empty": "Erstellen Sie mehrere Chats und verbinden Sie sie hier.", - "pipeline.end": "Ende", - "pipeline.user": "Benutzer", - "pipeline.model": "Modell", - "composer.chooseChat": "Wähle links einen Chat...", - "composer.message": "Nachricht an {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Tiefes Denken", - "composer.thinkingTitle": "Tiefes Denken: Das Modell zeigt die Gedankenkette", - "composer.thinkingRequired": "Tiefes Denken ist für dieses Modell erforderlich", - "composer.search": "🌐 Intelligente Suche", - "composer.searchTitle": "Intelligente Suche: Das Modell nutzt Websuche für aktuelle Informationen", - "composer.attach": "📎 Datei", - "composer.attachTitle": "Textdatei zum Lesen anhängen", - "composer.voice": "🎙 Sprache", - "composer.voiceTitle": "Sprache aufnehmen und Transkript in die Nachricht einfügen", - "composer.voiceStop": "■ Stopp", - "composer.stop": "■", - "composer.stopTitle": "Ausführung stoppen", - "composer.voiceInstalling": "Parakeet V3 wird installiert. Das kann einige Minuten dauern...", - "composer.voiceRecording": "Sprachaufnahme läuft...", - "composer.voiceTranscribing": "Sprache wird transkribiert...", - "composer.voiceMissing": "Voice-Helper ist nicht installiert. Legen Sie ai-free-stt unter {path} ab oder setzen Sie AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Dieses Browserfenster unterstützt keine Mikrofonaufnahme.", - "composer.voiceNoSpeech": "Keine Sprache erkannt.", - "composer.defaultImageQuestion": "Was ist auf diesem Bild? Beschreiben Sie es ausführlich.", - "composer.imageQuestionLabel": "(Bildfrage)", - "composer.uploadingImage": "Bild{num} wird hochgeladen und verarbeitet: {name}...", - "composer.thinkingStatus": "Denke...", - "composer.writingStatus": "Schreibt Antwort…", - "composer.backgroundTask": "⚙️ Aufgabe läuft im Hintergrund; Sie können zu einem anderen Chat wechseln", - "file.svgUnsupported": "SVG (\"{name}\") wird für Erkennung nicht unterstützt. Als PNG oder JPG speichern.", - "file.imageTooLarge": "Bild \"{name}\" ist zu groß ({mb} MB). Limit: 10 MB.", - "file.largeImageConfirm": "\"{name}\" ist {mb} MB groß. Große Dateien liefern bei DeepSeek oft CONTENT_EMPTY.\n\nTrotzdem hochladen?", - "file.readFailed": "\"{name}\" konnte nicht gelesen werden: {message}", - "file.uploadMissingId": "Upload kam ohne fileId zurück", - "file.qwenImageUnsupported": "AI Free kann Bilder noch nicht über den Qwen-Webtransport senden. Wählen Sie DeepSeek V4 Vision oder ChatGPT, damit das Bild verarbeitet wird.", - "file.binaryUnsupported": "Datei \"{name}\" ist binär ({ext}). Unterstützt werden derzeit Textdateien und Bilder (PNG/JPG/GIF/WEBP).\n\nPDF- und Office-Dokumente funktionieren noch nicht; dafür ist eine separate Phase nötig.", - "file.textTooLarge": "Datei \"{name}\" ist zu groß ({kb} KB). Textlimit: {limitKb} KB.", - "file.looksBinary": "Datei \"{name}\" sieht binär aus. Wenn sie Text ist, in .txt umbenennen.", - "file.remove": "Entfernen", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "Ich habe Datei{plural} angehängt. Bitte lesen und in der Antwort berücksichtigen:", - "file.promptHeader": "Datei: {name} ({kb} KB)", - "file.promptQuestion": "Meine Frage:", - "chat.delete": "Chat löschen", - "chat.running": "/code-Aufgabe läuft", - "chat.messages": "{count} Nachrichten", - "chat.deleteConfirm": "Chat löschen?", - "chat.history": "Verlauf: {file}", - "chat.you": "Sie", - "chat.assistant": "Assistent", - "chat.reasoningProcess": "Denkprozess", - "chat.reasoningThinking": "Denkt nach…", - "chat.question": "Frage", - "chat.system": "System", - "install.title": "Werkzeug installieren", - "install.approve": "Installieren", - "install.reject": "Abbrechen", - "install.running": "Installation läuft...", - "install.failed": "Installation fehlgeschlagen.", - "settings.title": "Einstellungen", - "settings.interface": "Oberfläche", - "settings.tabLanguage": "Sprache", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Berechtigungen", - "settings.language": "Sprache", - "settings.webSearchDefault": "Intelligente Suche standardmäßig aktivieren", - "settings.voiceTitle": "Spracheingabe", - "settings.voiceProvider": "Modell", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Bereit", - "settings.voiceMissing": "Nicht installiert", - "settings.voiceInstallHint": "Modell und Runtime sind nicht im Plugin enthalten. Installieren Sie ai-free-stt separat oder setzen Sie AI_FREE_STT_BIN.", - "settings.languageSaved": "Sprache gespeichert. Oberfläche wird neu geladen...", - "settings.loadFailed": "Einstellungen konnten nicht geladen werden: {message}", - "settings.low": "Niedriges Risiko", - "settings.medium": "Mittleres Risiko", - "settings.high": "Hohes Risiko", - "settings.apiTitle": "OpenAI-kompatible API", - "settings.baseUrl": "Basis-URL", - "settings.apiNote": "In einem OpenAI-kompatiblen Client die Basis-URL und den Bearer API-Key des gewünschten Anbieters verwenden. Modelle: {models}", - "settings.anthropicApiTitle": "Anthropic-kompatible API", - "settings.anthropicBaseUrl": "Basis-URL", - "settings.anthropicEndpoint": "Messages-Endpunkt", - "settings.anthropicAuth": "Auth-Header", - "settings.anthropicNote": "In einem Anthropic-kompatiblen Client die Basis-URL ohne /v1 und denselben Anbieter-Key verwenden. POST /v1/messages wird unterstützt. Modelle: {models}", - "settings.noKey": "Schlüssel nicht erstellt", - "settings.keyCreated": "Schlüssel erstellt", - "settings.createKey": "Erstellen", - "settings.keyReady": "{label} API-Key ist bereit", - "settings.keyCreateFailed": "{label} API-Key konnte nicht erstellt werden: {message}", - "settings.saveFailed": "Konnte nicht speichern: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Dunkel", - "theme.light": "Hell", - "theme.contrast": "Kontrast", - "theme.title": "Theme: {label}", - "shutdown.title": "CLI gestoppt", - "shutdown.sub": "Der Server antwortet nicht mehr. Das Fenster wird automatisch geschlossen.", - "shutdown.gracefulTitle": "ai-free wird beendet…", - "shutdown.stoppingTasks": "Hintergrundaufgaben werden gestoppt…", - "shutdown.closingBrowsers": "Chrome wird geschlossen (ChatGPT / Qwen)…", - "shutdown.closingServer": "Server wird gestoppt…", - "shutdown.stopped": "Gestoppt", - "shutdown.stoppedSub": "Das Fenster wird automatisch geschlossen.", - "welcome.title": "Willkommen bei AI Free", - "welcome.chooseProviders": "Wähle die KI-Anbieter aus, die du verbinden möchtest.", - "welcome.multi": "Wählen Sie einen oder mehrere. Weitere können später in den Einstellungen hinzugefügt werden.", - "welcome.prompt1": "Nummern durch Kommas getrennt eingeben (z. B. \"1\" oder \"1,2\"),", - "welcome.prompt2": "oder Enter für DeepSeek als Standard drücken:", - "welcome.invalid": "⚠️ Auswahl nicht verstanden. DeepSeek wird standardmäßig verwendet.", - "welcome.connecting": "Verbinde: {providers}", - "welcome.loginFailed": "❌ {provider} konnte nicht verbunden werden: {message}", - "welcome.retryLater": "Sie können es später über Einstellungen im Chatfenster erneut versuchen.", - "welcome.done": "✅ Fertig. Chat-Fenster wird gestartet...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/de.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/en.mjs b/plugin-for-vscode/src/i18n/languages/en.mjs index 2e19e77..95b1cd1 100644 --- a/plugin-for-vscode/src/i18n/languages/en.mjs +++ b/plugin-for-vscode/src/i18n/languages/en.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "en", - name: "English", - dir: "ltr", - messages: { - "app.workspace": "Workspace", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Refresh", - "app.newChat": "+ New chat", - "app.noChat": "No chat selected", - "app.createChatHint": "Create a chat on the left. Each chat can be a separate project or work context.", - "app.firstMessage": "Write the first message for this project.", - "app.close": "Close", - "app.loading": "Loading...", - "app.loadingShort": "Loading...", - "app.error": "Error: {message}", - "app.requestFailed": "Request failed", - "app.resizeChats": "Resize chat list", - "app.resizeComposer": "Resize input area", - "newChat.title": "New chat", - "newChat.provider": "Provider", - "newChat.mode": "Mode (model)", - "newChat.modeHint": "The mode is fixed when the chat is created. To switch later, create a new chat with the mode you need.", - "newChat.chatTitle": "Chat title (optional)", - "newChat.chatTitlePlaceholder": "Example: auth refactor", - "newChat.workspace": "Project folder", - "newChat.workspacePlaceholder": "/Users/.../project or ~/Projects/new-thing", - "newChat.browse": "📁 Browse", - "newChat.up": "↑ Up", - "newChat.home": "🏠 Home", - "newChat.newFolder": "➕ New folder", - "newChat.hidden": "Hidden", - "newChat.pickFolder": "Select this folder", - "newChat.newFolderPlaceholder": "New folder name", - "newChat.create": "Create", - "newChat.cancel": "Cancel", - "newChat.createFolder": "Create the folder if it does not exist (only under your $HOME)", - "newChat.submit": "Create chat", - "newChat.emptyFolderName": "Enter a name.", - "newChat.defaultProject": "default", - "newChat.truncated": "Not all folders are shown. Enable \"Hidden\" or open the parent folder.", - "newChat.folderCount": "Folders: {total}{suffix}", - "newChat.hiddenSuffix": " (hidden .folders - \"Hidden\" checkbox)", - "newChat.folderShown": "Showing {shown} of {total} folders", - "newChat.tooManyFolders": "(too many folders - narrow the path or enable \"Hidden\")", - "newChat.noSubfolders": "(no subfolders - you can select this folder with \"Select\")", - "newChat.truncatedInline": "Showing the first {shown} of {total}. Narrow the path or enable \"Hidden\".", - "newChat.creating": "Creating chat...", - "provider.connected": "✓ Connected", - "provider.connectedTitle": "You are signed in. Click to use another account", - "provider.authorize": "🔑 Sign in", - "provider.authorizeTitle": "Sign-in required. Click to sign in", - "provider.connectConfirm": "Connect {label}?\n\nA browser window will open. Sign in on the site; the window will close after login.", - "provider.chatgptConnectConfirm": "Connect {label}?\n\nA regular Chrome window will open once for reliable sign-in. It closes automatically after the active session is verified, then ChatGPT continues inside AI Free.", - "provider.chatgptEmbedLogin": "Complete sign-in in the Chrome window. It closes automatically only after the active session is verified.", - "provider.chatgptEmbedLoginTimeout": "Sign-in timed out for {label}. Click ‘Sign in with Chrome’ and try again.", - "provider.connectedAlert": "{label} connected.", - "provider.tokenMissing": "Login finished, but no token was found. Try again or run: npm run login-{id}", - "provider.connectFailed": "Could not connect {label}: {message}", - "provider.deepseekFast": "fast regular chat", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "image recognition", - "provider.qwenDefault": "choose the model in the chat header", - "role.assistantDescription": "Regular assistant", - "role.assistant": "Assistant", - "role.assistant.label": "Assistant", - "role.assistant.description": "Regular assistant for chat and quick answers.", - "role.prompt_builder.label": "Prompt Builder", - "role.prompt_builder.description": "Clarifies the task and turns it into a working prompt for the next steps.", - "role.architect.label": "Architect", - "role.architect.description": "Designs the solution, module boundaries, data, and risks.", - "role.developer.label": "Developer", - "role.developer.description": "Proposes implementation, files, steps, and technical details.", - "role.tester.label": "Tester", - "role.tester.description": "Finds checks, edge cases, regressions, and test scenarios.", - "role.reviewer.label": "Reviewer", - "role.reviewer.description": "Critically checks the plan/result and looks for weak spots.", - "role.synthesizer.label": "Synthesizer", - "role.synthesizer.description": "Combines pipeline outputs into a short summary and next steps.", - "topbar.model": "Model", - "topbar.role": "This chat role in the pipeline", - "topbar.coderTitle": "Enable agent mode: the model can create and edit files", - "topbar.coder": "🛠 Coder", - "topbar.coderOn": "🛠 Coder ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "Pipeline", - "topbar.pipelineOn": "Pipeline ON", - "topbar.hardwareTitle": "ESP / board firmware: enable the hardware agent profile", - "topbar.pipelineTitle": "Pass messages along pipeline links", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "topbar.flow": "Flow", - "topbar.flowTitle": "Pipeline flow", - "topbar.theme": "Change theme", - "topbar.settings": "Settings / allowed commands", - "topbar.quit": "Quit — stop the app and close Chrome", - "pipeline.title": "Pipeline flow", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — separate Chrome.", - "pipeline.sub": "Assign each chat a role and choose the next step.", - "pipeline.empty": "Create several chats, then connect them here.", - "pipeline.end": "End", - "pipeline.user": "User", - "pipeline.model": "model", - "composer.chooseChat": "Select a chat on the left...", - "composer.message": "Message {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Deep thinking", - "composer.thinkingTitle": "Deep thinking - the model shows chain-of-thought", - "composer.thinkingRequired": "Deep thinking is required for this model", - "composer.search": "🌐 Smart search", - "composer.searchTitle": "Smart search - the model uses web search for current information", - "composer.attach": "📎 File", - "composer.attachTitle": "Attach a text file to read", - "composer.voice": "🎙 Voice", - "composer.voiceTitle": "Record voice and insert the transcript into the message", - "composer.voiceStop": "■ Stop", - "composer.stop": "■", - "composer.stopTitle": "Stop execution", - "composer.voiceInstalling": "Installing Parakeet V3. This can take a few minutes...", - "composer.voiceRecording": "Recording voice...", - "composer.voiceTranscribing": "Transcribing voice...", - "composer.voiceMissing": "Voice helper is not installed. Put ai-free-stt at {path} or set AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "This browser window does not support microphone recording.", - "composer.voiceNoSpeech": "No speech was recognized.", - "composer.defaultImageQuestion": "What is in this image? Describe it in detail.", - "composer.imageQuestionLabel": "(image question)", - "composer.uploadingImage": "Uploading and processing image{num}: {name}...", - "composer.thinkingStatus": "Thinking...", - "composer.writingStatus": "Writing response…", - "composer.backgroundTask": "⚙️ Task is running in the background - you can switch to another chat", - "file.svgUnsupported": "SVG (\"{name}\") is not supported for recognition. Save it as PNG or JPG.", - "file.imageTooLarge": "Image \"{name}\" is too large ({mb} MB). Limit: 10 MB.", - "file.largeImageConfirm": "\"{name}\" is {mb} MB. Large files often return CONTENT_EMPTY on DeepSeek.\n\nUpload anyway?", - "file.readFailed": "Could not read \"{name}\": {message}", - "file.uploadMissingId": "Upload returned without fileId", - "file.qwenImageUnsupported": "AI Free cannot yet pass images through the Qwen web transport. Select DeepSeek V4 Vision or ChatGPT so the image is fully processed.", - "file.binaryUnsupported": "File \"{name}\" is binary ({ext}). Text files and images (PNG/JPG/GIF/WEBP) are currently supported.\n\nPDF and Office documents do not work yet - they need a separate phase.", - "file.textTooLarge": "File \"{name}\" is too large ({kb} KB). Text limit: {limitKb} KB.", - "file.looksBinary": "File \"{name}\" looks binary. If it is text, rename it to .txt.", - "file.remove": "Remove", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "I attached file{plural}. Read and consider it in your answer:", - "file.promptHeader": "File: {name} ({kb} KB)", - "file.promptQuestion": "My question:", - "chat.delete": "Delete chat", - "chat.running": "/code task is running", - "chat.messages": "{count} messages", - "chat.deleteConfirm": "Delete chat?", - "chat.history": "History: {file}", - "chat.you": "You", - "chat.assistant": "Assistant", - "chat.reasoningProcess": "Thought process", - "chat.reasoningThinking": "Thinking…", - "chat.question": "Question", - "chat.system": "System", - "install.title": "Install tool", - "install.approve": "Install", - "install.reject": "Cancel", - "install.running": "Installation is running...", - "install.failed": "Installation failed.", - "settings.title": "Settings", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.interface": "Interface", - "settings.tabLanguage": "Language", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter only the bot token. Chat ID is optional: it will be bound automatically after /start in Telegram.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID (optional)", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permissions", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "settings.language": "Language", - "settings.webSearchDefault": "Enable smart search by default", - "settings.voiceTitle": "Voice input", - "settings.voiceProvider": "Model", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Ready", - "settings.voiceMissing": "Not installed", - "settings.voiceInstallHint": "The model and runtime are not bundled with the plugin. Install ai-free-stt separately or set AI_FREE_STT_BIN.", - "settings.languageSaved": "Language saved. Reloading the interface...", - "settings.loadFailed": "Could not load settings: {message}", - "settings.low": "Low risk", - "settings.medium": "Medium risk", - "settings.high": "High risk", - "settings.apiTitle": "OpenAI-compatible API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "In an OpenAI-compatible client, use the Base URL and Bearer API key for the provider you need. Models: {models}", - "settings.anthropicApiTitle": "Anthropic-compatible API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "Auth header", - "settings.anthropicNote": "In an Anthropic-compatible client, use the Base URL without /v1 and the same provider API key. POST /v1/messages is supported. Models: {models}", - "settings.noKey": "Key not created", - "settings.keyCreated": "Key created", - "settings.createKey": "Create", - "settings.keyReady": "{label} API key is ready", - "settings.keyCreateFailed": "Could not create {label} API key: {message}", - "settings.saveFailed": "Could not save: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Dark", - "theme.light": "Light", - "theme.contrast": "Contrast", - "theme.title": "Theme: {label}", - "shutdown.title": "CLI stopped", - "shutdown.sub": "The server is no longer responding. This window will close automatically.", - "shutdown.gracefulTitle": "Stopping ai-free…", - "shutdown.stoppingTasks": "Stopping background tasks…", - "shutdown.closingBrowsers": "Closing Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Stopping server…", - "shutdown.stopped": "Stopped", - "shutdown.stoppedSub": "This window will close automatically.", - "welcome.title": "Welcome to AI Free", - "welcome.chooseProviders": "Choose the AI providers you want to connect.", - "welcome.multi": "Choose one or several. You can add more later in Settings.", - "welcome.prompt1": "Enter numbers separated by commas (for example \"1\" or \"1,2\"),", - "welcome.prompt2": "or press Enter for DeepSeek by default:", - "welcome.invalid": "⚠️ Could not understand the choice. Using DeepSeek by default.", - "welcome.connecting": "Connecting: {providers}", - "welcome.loginFailed": "❌ Could not connect {provider}: {message}", - "welcome.retryLater": "You can try again later from Settings in the chat window.", - "welcome.done": "✅ Done. Starting the chat window...", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/en.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/es.mjs b/plugin-for-vscode/src/i18n/languages/es.mjs index 7d9cadb..4c1add0 100644 --- a/plugin-for-vscode/src/i18n/languages/es.mjs +++ b/plugin-for-vscode/src/i18n/languages/es.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "es", - name: "Español", - dir: "ltr", - messages: { - "app.workspace": "Área de trabajo", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Actualizar", - "app.newChat": "+ Nuevo chat", - "app.noChat": "Ningún chat seleccionado", - "app.createChatHint": "Crea un chat a la izquierda. Cada chat puede ser un proyecto o contexto de trabajo independiente.", - "app.firstMessage": "Escribe el primer mensaje para este proyecto.", - "app.close": "Cerrar", - "app.loading": "Cargando...", - "app.loadingShort": "Cargando...", - "app.error": "Error: {message}", - "app.requestFailed": "La solicitud falló", - "app.resizeChats": "Cambiar el ancho de la lista de chats", - "app.resizeComposer": "Cambiar la altura del área de entrada", - "newChat.title": "Nuevo chat", - "newChat.provider": "Proveedor", - "newChat.mode": "Modo (modelo)", - "newChat.modeHint": "El modo queda fijado al crear el chat. Para cambiarlo después, crea un chat nuevo con el modo que necesitas.", - "newChat.chatTitle": "Título del chat (opcional)", - "newChat.chatTitlePlaceholder": "Ejemplo: refactorización de auth", - "newChat.workspace": "Carpeta del proyecto", - "newChat.workspacePlaceholder": "/Users/.../project o ~/Projects/new-thing", - "newChat.browse": "📁 Explorar", - "newChat.up": "↑ Arriba", - "newChat.home": "🏠 Inicio", - "newChat.newFolder": "➕ Nueva carpeta", - "newChat.hidden": "Ocultos", - "newChat.pickFolder": "Seleccionar esta carpeta", - "newChat.newFolderPlaceholder": "Nombre de la nueva carpeta", - "newChat.create": "Crear", - "newChat.cancel": "Cancelar", - "newChat.createFolder": "Crear la carpeta si no existe (solo dentro de tu $HOME)", - "newChat.submit": "Crear chat", - "newChat.emptyFolderName": "Introduce un nombre.", - "newChat.defaultProject": "predeterminado", - "newChat.truncated": "No se muestran todas las carpetas. Activa \"Ocultos\" o abre la carpeta superior.", - "newChat.folderCount": "Carpetas: {total}{suffix}", - "newChat.hiddenSuffix": " (carpetas . ocultas - casilla \"Ocultos\")", - "newChat.folderShown": "Mostrando {shown} de {total} carpetas", - "newChat.tooManyFolders": "(demasiadas carpetas - acota la ruta o activa \"Ocultos\")", - "newChat.noSubfolders": "(no hay subcarpetas - puedes seleccionar esta carpeta con \"Seleccionar\")", - "newChat.truncatedInline": "Se muestran las primeras {shown} de {total}. Acota la ruta o activa \"Ocultos\".", - "newChat.creating": "Creando chat...", - "provider.connected": "✓ Conectado", - "provider.connectedTitle": "Has iniciado sesión. Pulsa para usar otra cuenta", - "provider.authorize": "🔑 Autorizar", - "provider.authorizeTitle": "Se requiere iniciar sesión. Pulsa para entrar", - "provider.connectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana del navegador. Inicia sesión en el sitio; la ventana se cerrará después.", - "provider.chatgptConnectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana normal de Chrome una sola vez para iniciar sesión de forma fiable. Se cerrará automáticamente después de verificar la sesión activa y ChatGPT continuará dentro de AI Free.", - "provider.chatgptEmbedLogin": "Completa el inicio de sesión en la ventana de Chrome. Se cerrará automáticamente solo después de verificar la sesión activa.", - "provider.chatgptEmbedLoginTimeout": "Se agotó el tiempo para iniciar sesión en {label}. Pulsa «Iniciar sesión con Chrome» e inténtalo de nuevo.", - "provider.connectedAlert": "{label} conectado.", - "provider.tokenMissing": "El inicio de sesión terminó, pero no se encontró ningún token. Inténtalo de nuevo o ejecuta: npm run login-{id}", - "provider.connectFailed": "No se pudo conectar {label}: {message}", - "provider.deepseekFast": "chat normal rápido", - "provider.deepseekExpert": "razonamiento / R1", - "provider.deepseekVision": "reconocimiento de imágenes", - "provider.qwenDefault": "elige el modelo en la cabecera del chat", - "role.assistantDescription": "Asistente normal", - "role.assistant": "Asistente", - "role.assistant.label": "Asistente", - "role.assistant.description": "Asistente normal para chat y respuestas rápidas.", - "role.prompt_builder.label": "Constructor de prompts", - "role.prompt_builder.description": "Aclara la tarea y la convierte en un prompt útil para los siguientes pasos.", - "role.architect.label": "Arquitecto", - "role.architect.description": "Diseña la solución, los límites de módulos, los datos y los riesgos.", - "role.developer.label": "Desarrollador", - "role.developer.description": "Propone implementación, archivos, pasos y detalles técnicos.", - "role.tester.label": "Tester", - "role.tester.description": "Busca verificaciones, casos límite, regresiones y escenarios de prueba.", - "role.reviewer.label": "Revisor", - "role.reviewer.description": "Revisa críticamente el plan/resultado y busca puntos débiles.", - "role.synthesizer.label": "Sintetizador", - "role.synthesizer.description": "Combina las salidas del pipeline en un resumen breve y próximos pasos.", - "topbar.model": "Modelo", - "topbar.role": "Rol de este chat en el pipeline", - "topbar.coderTitle": "Activar modo agente: el modelo puede crear y editar archivos", - "topbar.coder": "🛠 Programador", - "topbar.coderOn": "🛠 Programador ACTIVADO", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ACTIVADO", - "topbar.pipeline": "Flujo", - "topbar.pipelineOn": "Flujo ON", - "topbar.hardwareTitle": "ESP / firmware de placas: activa el perfil de agente de hardware", - "topbar.pipelineTitle": "Pasar mensajes por los enlaces del pipeline", - "topbar.flow": "Flujo", - "topbar.flowTitle": "Flujo del pipeline", - "topbar.theme": "Cambiar tema", - "topbar.settings": "Configuración / comandos permitidos", - "topbar.quit": "Salir — detener la app y cerrar Chrome", - "pipeline.title": "Flujo del pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Asigna un rol a cada chat y elige el siguiente paso.", - "pipeline.empty": "Crea varios chats y conéctalos aquí.", - "pipeline.end": "Fin", - "pipeline.user": "Usuario", - "pipeline.model": "modelo", - "composer.chooseChat": "Elige un chat a la izquierda...", - "composer.message": "Mensaje para {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Pensamiento profundo", - "composer.thinkingTitle": "Pensamiento profundo: el modelo muestra la cadena de razonamiento", - "composer.thinkingRequired": "El pensamiento profundo es obligatorio para este modelo", - "composer.search": "🌐 Búsqueda inteligente", - "composer.searchTitle": "Búsqueda inteligente: el modelo usa búsqueda web para información actual", - "composer.attach": "📎 Archivo", - "composer.attachTitle": "Adjuntar un archivo de texto para leer", - "composer.voice": "🎙 Voz", - "composer.voiceTitle": "Grabar voz e insertar la transcripción en el mensaje", - "composer.voiceStop": "■ Parar", - "composer.stop": "■", - "composer.stopTitle": "Detener ejecución", - "composer.voiceInstalling": "Instalando Parakeet V3. Puede tardar unos minutos...", - "composer.voiceRecording": "Grabando voz...", - "composer.voiceTranscribing": "Transcribiendo voz...", - "composer.voiceMissing": "El helper de voz no está instalado. Coloca ai-free-stt en {path} o define AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Esta ventana del navegador no admite grabación de micrófono.", - "composer.voiceNoSpeech": "No se reconoció voz.", - "composer.defaultImageQuestion": "¿Qué hay en esta imagen? Descríbelo con detalle.", - "composer.imageQuestionLabel": "(pregunta sobre imagen)", - "composer.uploadingImage": "Subiendo y procesando imagen{num}: {name}...", - "composer.thinkingStatus": "Pensando...", - "composer.writingStatus": "Escribiendo respuesta…", - "composer.backgroundTask": "⚙️ La tarea se ejecuta en segundo plano; puedes cambiar a otro chat", - "file.svgUnsupported": "SVG (\"{name}\") no se admite para reconocimiento. Guárdalo como PNG o JPG.", - "file.imageTooLarge": "La imagen \"{name}\" es demasiado grande ({mb} MB). Límite: 10 MB.", - "file.largeImageConfirm": "\"{name}\" pesa {mb} MB. Los archivos grandes suelen devolver CONTENT_EMPTY en DeepSeek.\n\n¿Subir de todos modos?", - "file.readFailed": "No se pudo leer \"{name}\": {message}", - "file.uploadMissingId": "La subida volvió sin fileId", - "file.qwenImageUnsupported": "AI Free todavía no puede enviar imágenes mediante el transporte web de Qwen. Selecciona DeepSeek V4 Vision o ChatGPT para procesar la imagen.", - "file.binaryUnsupported": "El archivo \"{name}\" es binario ({ext}). Ahora se admiten archivos de texto e imágenes (PNG/JPG/GIF/WEBP).\n\nLos PDF y documentos Office aún no funcionan: necesitan una fase separada.", - "file.textTooLarge": "El archivo \"{name}\" es demasiado grande ({kb} KB). Límite de texto: {limitKb} KB.", - "file.looksBinary": "El archivo \"{name}\" parece binario. Si es texto, cámbiale el nombre a .txt.", - "file.remove": "Quitar", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "He adjuntado archivo{plural}. Léelo y tenlo en cuenta en tu respuesta:", - "file.promptHeader": "Archivo: {name} ({kb} KB)", - "file.promptQuestion": "Mi pregunta:", - "chat.delete": "Eliminar chat", - "chat.running": "La tarea /code se está ejecutando", - "chat.messages": "{count} mensajes", - "chat.deleteConfirm": "¿Eliminar chat?", - "chat.history": "Historial: {file}", - "chat.you": "Tú", - "chat.assistant": "Asistente", - "chat.reasoningProcess": "Proceso de razonamiento", - "chat.reasoningThinking": "Pensando…", - "chat.question": "Pregunta", - "chat.system": "Sistema", - "install.title": "Instalar herramienta", - "install.approve": "Instalar", - "install.reject": "Cancelar", - "install.running": "La instalación está en curso...", - "install.failed": "La instalación falló.", - "settings.title": "Configuración", - "settings.interface": "Interfaz", - "settings.tabLanguage": "Idioma", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permisos", - "settings.language": "Idioma", - "settings.webSearchDefault": "Activar búsqueda inteligente por defecto", - "settings.voiceTitle": "Entrada de voz", - "settings.voiceProvider": "Modelo", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Listo", - "settings.voiceMissing": "No instalado", - "settings.voiceInstallHint": "El modelo y el runtime no se incluyen con el plugin. Instala ai-free-stt por separado o define AI_FREE_STT_BIN.", - "settings.languageSaved": "Idioma guardado. Recargando la interfaz...", - "settings.loadFailed": "No se pudo cargar la configuración: {message}", - "settings.low": "Riesgo bajo", - "settings.medium": "Riesgo medio", - "settings.high": "Riesgo alto", - "settings.apiTitle": "API compatible con OpenAI", - "settings.baseUrl": "URL base", - "settings.apiNote": "En un cliente compatible con OpenAI, usa la URL base y la clave Bearer del proveedor necesario. Modelos: {models}", - "settings.anthropicApiTitle": "API compatible con Anthropic", - "settings.anthropicBaseUrl": "URL base", - "settings.anthropicEndpoint": "Endpoint de Messages", - "settings.anthropicAuth": "Cabecera de autenticación", - "settings.anthropicNote": "En un cliente compatible con Anthropic, usa la URL base sin /v1 y la misma clave del proveedor. Se admite POST /v1/messages. Modelos: {models}", - "settings.noKey": "Clave no creada", - "settings.keyCreated": "Clave creada", - "settings.createKey": "Crear", - "settings.keyReady": "Clave API de {label} lista", - "settings.keyCreateFailed": "No se pudo crear la clave API de {label}: {message}", - "settings.saveFailed": "No se pudo guardar: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Oscuro", - "theme.light": "Claro", - "theme.contrast": "Contraste", - "theme.title": "Tema: {label}", - "shutdown.title": "CLI detenido", - "shutdown.sub": "El servidor ya no responde. La ventana se cerrará automáticamente.", - "shutdown.gracefulTitle": "Deteniendo ai-free…", - "shutdown.stoppingTasks": "Deteniendo tareas en segundo plano…", - "shutdown.closingBrowsers": "Cerrando Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Deteniendo el servidor…", - "shutdown.stopped": "Detenido", - "shutdown.stoppedSub": "La ventana se cerrará automáticamente.", - "welcome.title": "Bienvenido a AI Free", - "welcome.chooseProviders": "Elige los proveedores de IA que quieres conectar.", - "welcome.multi": "Elige uno o varios. Puedes añadir más después en Configuración.", - "welcome.prompt1": "Introduce números separados por comas (por ejemplo \"1\" o \"1,2\"),", - "welcome.prompt2": "o pulsa Enter para usar DeepSeek por defecto:", - "welcome.invalid": "⚠️ No se pudo entender la elección. Usando DeepSeek por defecto.", - "welcome.connecting": "Conectando: {providers}", - "welcome.loginFailed": "❌ No se pudo conectar {provider}: {message}", - "welcome.retryLater": "Puedes intentarlo de nuevo más tarde desde Configuración en la ventana de chat.", - "welcome.done": "✅ Listo. Iniciando la ventana de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/es.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/fr.mjs b/plugin-for-vscode/src/i18n/languages/fr.mjs index 2094ead..7c613ad 100644 --- a/plugin-for-vscode/src/i18n/languages/fr.mjs +++ b/plugin-for-vscode/src/i18n/languages/fr.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "fr", - name: "Français", - dir: "ltr", - messages: { - "app.workspace": "Espace de travail", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Actualiser", - "app.newChat": "+ Nouveau chat", - "app.noChat": "Aucun chat sélectionné", - "app.createChatHint": "Crée un chat à gauche. Chaque chat peut être un projet ou un contexte de travail séparé.", - "app.firstMessage": "Écris le premier message pour ce projet.", - "app.close": "Fermer", - "app.loading": "Chargement...", - "app.loadingShort": "Chargement...", - "app.error": "Erreur : {message}", - "app.requestFailed": "La requête a échoué", - "app.resizeChats": "Redimensionner la liste des chats", - "app.resizeComposer": "Redimensionner la zone de saisie", - "newChat.title": "Nouveau chat", - "newChat.provider": "Fournisseur", - "newChat.mode": "Mode (modèle)", - "newChat.modeHint": "Le mode est fixé à la création du chat. Pour le changer ensuite, créez un nouveau chat avec le mode voulu.", - "newChat.chatTitle": "Titre du chat (facultatif)", - "newChat.chatTitlePlaceholder": "Exemple : refactorisation auth", - "newChat.workspace": "Dossier du projet", - "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", - "newChat.browse": "📁 Parcourir", - "newChat.up": "↑ Haut", - "newChat.home": "🏠 Accueil", - "newChat.newFolder": "➕ Nouveau dossier", - "newChat.hidden": "Masqués", - "newChat.pickFolder": "Sélectionner ce dossier", - "newChat.newFolderPlaceholder": "Nom du nouveau dossier", - "newChat.create": "Créer", - "newChat.cancel": "Annuler", - "newChat.createFolder": "Créer le dossier s’il n’existe pas (uniquement sous votre $HOME)", - "newChat.submit": "Créer le chat", - "newChat.emptyFolderName": "Saisissez un nom.", - "newChat.defaultProject": "par défaut", - "newChat.truncated": "Tous les dossiers ne sont pas affichés. Activez \"Masqués\" ou ouvrez le dossier parent.", - "newChat.folderCount": "Dossiers : {total}{suffix}", - "newChat.hiddenSuffix": " (dossiers . masqués - case \"Masqués\")", - "newChat.folderShown": "Affichage de {shown} sur {total} dossiers", - "newChat.tooManyFolders": "(trop de dossiers - précisez le chemin ou activez \"Masqués\")", - "newChat.noSubfolders": "(aucun sous-dossier - vous pouvez sélectionner ce dossier avec \"Sélectionner\")", - "newChat.truncatedInline": "Affichage des {shown} premiers sur {total}. Précisez le chemin ou activez \"Masqués\".", - "newChat.creating": "Création du chat...", - "provider.connected": "✓ Connecté", - "provider.connectedTitle": "Vous êtes connecté. Cliquez pour utiliser un autre compte", - "provider.authorize": "🔑 Autoriser", - "provider.authorizeTitle": "Connexion requise. Cliquez pour vous connecter", - "provider.connectConfirm": "Connecter {label} ?\n\nUne fenêtre de navigateur va s’ouvrir. Connectez-vous sur le site ; elle se fermera après la connexion.", - "provider.chatgptConnectConfirm": "Connecter {label} ?\n\nUne fenêtre Chrome normale s’ouvrira une seule fois pour une connexion fiable. Elle se fermera automatiquement après vérification de la session active, puis ChatGPT continuera dans AI Free.", - "provider.chatgptEmbedLogin": "Terminez la connexion dans la fenêtre Chrome. Elle se fermera automatiquement uniquement après vérification de la session active.", - "provider.chatgptEmbedLoginTimeout": "Le délai de connexion à {label} a expiré. Cliquez sur « Se connecter avec Chrome » et réessayez.", - "provider.connectedAlert": "{label} connecté.", - "provider.tokenMissing": "Connexion terminée, mais aucun jeton trouvé. Réessayez ou lancez : npm run login-{id}", - "provider.connectFailed": "Impossible de connecter {label} : {message}", - "provider.deepseekFast": "chat normal rapide", - "provider.deepseekExpert": "raisonnement / R1", - "provider.deepseekVision": "reconnaissance d’images", - "provider.qwenDefault": "choisissez le modèle dans l’en-tête du chat", - "role.assistantDescription": "Assistant standard", - "role.assistant": "Assistant", - "role.assistant.label": "Assistant", - "role.assistant.description": "Assistant standard pour le chat et les réponses rapides.", - "role.prompt_builder.label": "Constructeur de prompts", - "role.prompt_builder.description": "Clarifie la tâche et la transforme en prompt exploitable pour les étapes suivantes.", - "role.architect.label": "Architecte", - "role.architect.description": "Conçoit la solution, les limites des modules, les données et les risques.", - "role.developer.label": "Développeur", - "role.developer.description": "Propose l’implémentation, les fichiers, les étapes et les détails techniques.", - "role.tester.label": "Testeur", - "role.tester.description": "Cherche les vérifications, cas limites, régressions et scénarios de test.", - "role.reviewer.label": "Relecteur", - "role.reviewer.description": "Vérifie de façon critique le plan/résultat et cherche les points faibles.", - "role.synthesizer.label": "Synthétiseur", - "role.synthesizer.description": "Combine les sorties du pipeline en un bref résumé et prochaines étapes.", - "topbar.model": "Modèle", - "topbar.role": "Rôle de ce chat dans le pipeline", - "topbar.coderTitle": "Activer le mode agent : le modèle peut créer et modifier des fichiers", - "topbar.coder": "🛠 Codeur", - "topbar.coderOn": "🛠 Codeur ACTIF", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ACTIF", - "topbar.pipeline": "Flux", - "topbar.pipelineOn": "Flux ON", - "topbar.hardwareTitle": "ESP / firmware de cartes : active le profil agent matériel", - "topbar.pipelineTitle": "Transmettre les messages via les liens du pipeline", - "topbar.flow": "Flux", - "topbar.flowTitle": "Flux du pipeline", - "topbar.theme": "Changer le thème", - "topbar.settings": "Paramètres / commandes autorisées", - "topbar.quit": "Quitter — arrêter l'app et fermer Chrome", - "pipeline.title": "Flux du pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Attribuez un rôle à chaque chat et choisissez l’étape suivante.", - "pipeline.empty": "Créez plusieurs chats, puis reliez-les ici.", - "pipeline.end": "Fin", - "pipeline.user": "Utilisateur", - "pipeline.model": "modèle", - "composer.chooseChat": "Choisis un chat à gauche...", - "composer.message": "Message pour {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Raisonnement approfondi", - "composer.thinkingTitle": "Réflexion approfondie : le modèle affiche la chaîne de raisonnement", - "composer.thinkingRequired": "La réflexion approfondie est obligatoire pour ce modèle", - "composer.search": "🌐 Recherche intelligente", - "composer.searchTitle": "Recherche intelligente : le modèle utilise le web pour les informations à jour", - "composer.attach": "📎 Fichier", - "composer.attachTitle": "Joindre un fichier texte à lire", - "composer.voice": "🎙 Voix", - "composer.voiceTitle": "Enregistrer la voix et insérer la transcription dans le message", - "composer.voiceStop": "■ Stop", - "composer.stop": "■", - "composer.stopTitle": "Arrêter l'exécution", - "composer.voiceInstalling": "Installation de Parakeet V3. Cela peut prendre quelques minutes...", - "composer.voiceRecording": "Enregistrement vocal...", - "composer.voiceTranscribing": "Transcription vocale...", - "composer.voiceMissing": "Le helper vocal n’est pas installé. Placez ai-free-stt dans {path} ou définissez AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Cette fenêtre de navigateur ne prend pas en charge l’enregistrement micro.", - "composer.voiceNoSpeech": "Aucune parole reconnue.", - "composer.defaultImageQuestion": "Que contient cette image ? Décrivez-la en détail.", - "composer.imageQuestionLabel": "(question sur l’image)", - "composer.uploadingImage": "Envoi et traitement de l’image{num} : {name}...", - "composer.thinkingStatus": "Réflexion...", - "composer.writingStatus": "Rédaction de la réponse…", - "composer.backgroundTask": "⚙️ La tâche s’exécute en arrière-plan ; vous pouvez passer à un autre chat", - "file.svgUnsupported": "SVG (\"{name}\") n’est pas pris en charge pour la reconnaissance. Enregistrez en PNG ou JPG.", - "file.imageTooLarge": "L’image \"{name}\" est trop grande ({mb} Mo). Limite : 10 Mo.", - "file.largeImageConfirm": "\"{name}\" fait {mb} Mo. Les gros fichiers renvoient souvent CONTENT_EMPTY sur DeepSeek.\n\nEnvoyer quand même ?", - "file.readFailed": "Impossible de lire \"{name}\" : {message}", - "file.uploadMissingId": "L’envoi est revenu sans fileId", - "file.qwenImageUnsupported": "AI Free ne peut pas encore transmettre les images via le transport web Qwen. Sélectionnez DeepSeek V4 Vision ou ChatGPT pour traiter l’image.", - "file.binaryUnsupported": "Le fichier \"{name}\" est binaire ({ext}). Les fichiers texte et images (PNG/JPG/GIF/WEBP) sont pris en charge.\n\nLes PDF et documents Office ne fonctionnent pas encore : il faut une phase séparée.", - "file.textTooLarge": "Le fichier \"{name}\" est trop grand ({kb} Ko). Limite texte : {limitKb} Ko.", - "file.looksBinary": "Le fichier \"{name}\" semble binaire. Si c’est du texte, renommez-le en .txt.", - "file.remove": "Retirer", - "file.sizeKb": "{kb} Ko", - "file.promptPrefix": "J’ai joint fichier{plural}. Lisez-le et tenez-en compte dans votre réponse :", - "file.promptHeader": "Fichier : {name} ({kb} Ko)", - "file.promptQuestion": "Ma question :", - "chat.delete": "Supprimer le chat", - "chat.running": "La tâche /code est en cours", - "chat.messages": "{count} messages", - "chat.deleteConfirm": "Supprimer le chat ?", - "chat.history": "Historique : {file}", - "chat.you": "Vous", - "chat.assistant": "Assistant", - "chat.reasoningProcess": "Processus de réflexion", - "chat.reasoningThinking": "En train de réfléchir…", - "chat.question": "Question", - "chat.system": "Système", - "install.title": "Installer un outil", - "install.approve": "Installer", - "install.reject": "Annuler", - "install.running": "Installation en cours...", - "install.failed": "L’installation a échoué.", - "settings.title": "Paramètres", - "settings.interface": "Interface", - "settings.tabLanguage": "Langue", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Autorisations", - "settings.language": "Langue", - "settings.webSearchDefault": "Activer la recherche intelligente par défaut", - "settings.voiceTitle": "Saisie vocale", - "settings.voiceProvider": "Modèle", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Prêt", - "settings.voiceMissing": "Non installé", - "settings.voiceInstallHint": "Le modèle et le runtime ne sont pas inclus dans le plugin. Installez ai-free-stt séparément ou définissez AI_FREE_STT_BIN.", - "settings.languageSaved": "Langue enregistrée. Rechargement de l’interface...", - "settings.loadFailed": "Impossible de charger les paramètres : {message}", - "settings.low": "Risque faible", - "settings.medium": "Risque moyen", - "settings.high": "Risque élevé", - "settings.apiTitle": "API compatible OpenAI", - "settings.baseUrl": "URL de base", - "settings.apiNote": "Dans un client compatible OpenAI, utilisez l’URL de base et la clé Bearer du fournisseur voulu. Modèles : {models}", - "settings.anthropicApiTitle": "API compatible Anthropic", - "settings.anthropicBaseUrl": "URL de base", - "settings.anthropicEndpoint": "Endpoint Messages", - "settings.anthropicAuth": "En-tête d’authentification", - "settings.anthropicNote": "Dans un client compatible Anthropic, utilisez l’URL de base sans /v1 et la même clé fournisseur. POST /v1/messages est pris en charge. Modèles : {models}", - "settings.noKey": "Clé non créée", - "settings.keyCreated": "Clé créée", - "settings.createKey": "Créer", - "settings.keyReady": "Clé API {label} prête", - "settings.keyCreateFailed": "Impossible de créer la clé API {label} : {message}", - "settings.saveFailed": "Impossible d’enregistrer : {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Sombre", - "theme.light": "Clair", - "theme.contrast": "Contraste", - "theme.title": "Thème : {label}", - "shutdown.title": "CLI arrêté", - "shutdown.sub": "Le serveur ne répond plus. La fenêtre va se fermer automatiquement.", - "shutdown.gracefulTitle": "Arrêt de ai-free…", - "shutdown.stoppingTasks": "Arrêt des tâches en arrière-plan…", - "shutdown.closingBrowsers": "Fermeture de Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Arrêt du serveur…", - "shutdown.stopped": "Arrêté", - "shutdown.stoppedSub": "La fenêtre va se fermer automatiquement.", - "welcome.title": "Bienvenue dans AI Free", - "welcome.chooseProviders": "Choisis les fournisseurs d'IA à connecter.", - "welcome.multi": "Choisissez-en un ou plusieurs. Vous pourrez en ajouter ensuite dans Paramètres.", - "welcome.prompt1": "Saisissez des numéros séparés par des virgules (par exemple \"1\" ou \"1,2\"),", - "welcome.prompt2": "ou appuyez sur Entrée pour DeepSeek par défaut :", - "welcome.invalid": "⚠️ Choix incompris. DeepSeek sera utilisé par défaut.", - "welcome.connecting": "Connexion : {providers}", - "welcome.loginFailed": "❌ Impossible de connecter {provider} : {message}", - "welcome.retryLater": "Vous pourrez réessayer plus tard depuis Paramètres dans la fenêtre de chat.", - "welcome.done": "✅ Terminé. Lancement de la fenêtre de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/fr.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/hi.mjs b/plugin-for-vscode/src/i18n/languages/hi.mjs index c771b56..c08f92a 100644 --- a/plugin-for-vscode/src/i18n/languages/hi.mjs +++ b/plugin-for-vscode/src/i18n/languages/hi.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "hi", - name: "हिन्दी", - dir: "ltr", - messages: { - "app.workspace": "वर्कस्पेस", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "रीफ्रेश", - "app.newChat": "+ नया चैट", - "app.noChat": "कोई चैट चयनित नहीं", - "app.createChatHint": "बाईं ओर चैट बनाएं। हर चैट अलग प्रोजेक्ट या काम का संदर्भ हो सकती है।", - "app.firstMessage": "इस प्रोजेक्ट के लिए पहला संदेश लिखें।", - "app.close": "बंद करें", - "app.loading": "लोड हो रहा है...", - "app.loadingShort": "लोड हो रहा है...", - "app.error": "त्रुटि: {message}", - "app.requestFailed": "अनुरोध विफल हुआ", - "app.resizeChats": "चैट सूची की चौड़ाई बदलें", - "app.resizeComposer": "इनपुट क्षेत्र की ऊँचाई बदलें", - "newChat.title": "नया चैट", - "newChat.provider": "प्रदाता", - "newChat.mode": "मोड (मॉडल)", - "newChat.modeHint": "चैट बनाते समय मोड तय हो जाता है। बाद में बदलने के लिए ज़रूरी मोड के साथ नया चैट बनाएं।", - "newChat.chatTitle": "चैट शीर्षक (वैकल्पिक)", - "newChat.chatTitlePlaceholder": "उदाहरण: auth refactor", - "newChat.workspace": "प्रोजेक्ट फ़ोल्डर", - "newChat.workspacePlaceholder": "/Users/.../project या ~/Projects/new-thing", - "newChat.browse": "📁 ब्राउज़", - "newChat.up": "↑ ऊपर", - "newChat.home": "🏠 होम", - "newChat.newFolder": "➕ नया फ़ोल्डर", - "newChat.hidden": "छिपे हुए", - "newChat.pickFolder": "यह फ़ोल्डर चुनें", - "newChat.newFolderPlaceholder": "नए फ़ोल्डर का नाम", - "newChat.create": "बनाएं", - "newChat.cancel": "रद्द करें", - "newChat.createFolder": "अगर फ़ोल्डर मौजूद नहीं है तो बनाएं (केवल आपके $HOME के अंदर)", - "newChat.submit": "चैट बनाएं", - "newChat.emptyFolderName": "नाम दर्ज करें।", - "newChat.defaultProject": "डिफ़ॉल्ट", - "newChat.truncated": "सभी फ़ोल्डर नहीं दिखाए गए। \"छिपे हुए\" चालू करें या ऊपर वाला फ़ोल्डर खोलें।", - "newChat.folderCount": "फ़ोल्डर: {total}{suffix}", - "newChat.hiddenSuffix": " (छिपे हुए .फ़ोल्डर - \"छिपे हुए\" चेकबॉक्स)", - "newChat.folderShown": "{total} में से {shown} फ़ोल्डर दिख रहे हैं", - "newChat.tooManyFolders": "(बहुत अधिक फ़ोल्डर - पथ छोटा करें या \"छिपे हुए\" चालू करें)", - "newChat.noSubfolders": "(कोई सबफ़ोल्डर नहीं - इस फ़ोल्डर को \"चुनें\" से चुना जा सकता है)", - "newChat.truncatedInline": "{total} में से पहले {shown} दिख रहे हैं। पथ छोटा करें या \"छिपे हुए\" चालू करें।", - "newChat.creating": "चैट बनाई जा रही है...", - "provider.connected": "✓ कनेक्टेड", - "provider.connectedTitle": "आप साइन इन हैं। दूसरा खाता उपयोग करने के लिए क्लिक करें", - "provider.authorize": "🔑 अधिकृत करें", - "provider.authorizeTitle": "साइन इन आवश्यक है। साइन इन करने के लिए क्लिक करें", - "provider.connectConfirm": "{label} कनेक्ट करें?\n\nब्राउज़र विंडो खुलेगी। साइट पर साइन इन करें; लॉगिन के बाद विंडो बंद हो जाएगी।", - "provider.chatgptConnectConfirm": "{label} को कनेक्ट करें?\n\nविश्वसनीय साइन-इन के लिए सामान्य Chrome विंडो एक बार खुलेगी। सक्रिय सत्र सत्यापित होने के बाद यह अपने आप बंद हो जाएगी और ChatGPT AI Free के अंदर चलता रहेगा।", - "provider.chatgptEmbedLogin": "Chrome विंडो में साइन-इन पूरा करें। सक्रिय सत्र सत्यापित होने के बाद ही यह अपने आप बंद होगी।", - "provider.chatgptEmbedLoginTimeout": "{label} में साइन-इन का समय समाप्त हो गया। «Chrome से साइन इन करें» दबाकर फिर कोशिश करें।", - "provider.connectedAlert": "{label} कनेक्ट हो गया।", - "provider.tokenMissing": "लॉगिन पूरा हुआ, लेकिन token नहीं मिला। फिर कोशिश करें या चलाएँ: npm run login-{id}", - "provider.connectFailed": "{label} कनेक्ट नहीं हो सका: {message}", - "provider.deepseekFast": "तेज़ सामान्य चैट", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "छवि पहचान", - "provider.qwenDefault": "चैट हेडर में मॉडल चुनें", - "role.assistantDescription": "सामान्य सहायक", - "role.assistant": "सहायक", - "role.assistant.label": "सहायक", - "role.assistant.description": "चैट और तेज़ उत्तरों के लिए सामान्य सहायक।", - "role.prompt_builder.label": "प्रॉम्प्ट बिल्डर", - "role.prompt_builder.description": "कार्य स्पष्ट करता है और अगले चरणों के लिए उपयोगी prompt बनाता है।", - "role.architect.label": "आर्किटेक्ट", - "role.architect.description": "समाधान, मॉड्यूल सीमाएँ, डेटा और जोखिम डिज़ाइन करता है।", - "role.developer.label": "डेवलपर", - "role.developer.description": "implementation, files, steps और technical details सुझाता है।", - "role.tester.label": "टेस्टर", - "role.tester.description": "checks, edge cases, regressions और test scenarios खोजता है।", - "role.reviewer.label": "रिव्यूअर", - "role.reviewer.description": "plan/result को आलोचनात्मक रूप से जाँचता है और कमजोरियाँ ढूँढता है।", - "role.synthesizer.label": "सिंथेसाइज़र", - "role.synthesizer.description": "pipeline outputs को छोटे summary और next steps में जोड़ता है।", - "topbar.model": "मॉडल", - "topbar.role": "pipeline में इस चैट की भूमिका", - "topbar.coderTitle": "एजेंट मोड चालू करें: मॉडल फ़ाइलें बना और संपादित कर सकता है", - "topbar.coder": "🛠 कोडर", - "topbar.coderOn": "🛠 कोडर ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "फ़्लो", - "topbar.pipelineOn": "फ़्लो ON", - "topbar.hardwareTitle": "ESP / बोर्ड firmware: hardware agent profile चालू करता है", - "topbar.pipelineTitle": "pipeline links के जरिए संदेश भेजें", - "topbar.flow": "फ़्लो", - "topbar.flowTitle": "Pipeline फ़्लो", - "topbar.theme": "थीम बदलें", - "topbar.settings": "सेटिंग्स / अनुमत कमांड", - "topbar.quit": "बाहर — ऐप बंद करें और Chrome बंद करें", - "pipeline.title": "Pipeline फ़्लो", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "हर चैट को भूमिका दें और अगला कदम चुनें।", - "pipeline.empty": "कई चैट बनाएं, फिर उन्हें यहाँ जोड़ें।", - "pipeline.end": "अंत", - "pipeline.user": "उपयोगकर्ता", - "pipeline.model": "मॉडल", - "composer.chooseChat": "बाईं ओर चैट चुनें...", - "composer.message": "{label} को संदेश...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ गहरी सोच", - "composer.thinkingTitle": "गहरी सोच: मॉडल chain-of-thought दिखाता है", - "composer.thinkingRequired": "इस मॉडल के लिए गहरी सोच आवश्यक है", - "composer.search": "🌐 स्मार्ट खोज", - "composer.searchTitle": "स्मार्ट खोज: मॉडल ताज़ा जानकारी के लिए वेब खोज उपयोग करता है", - "composer.attach": "📎 फ़ाइल", - "composer.attachTitle": "पढ़ने के लिए टेक्स्ट फ़ाइल जोड़ें", - "composer.voice": "🎙 आवाज़", - "composer.voiceTitle": "आवाज़ रिकॉर्ड करें और transcript को संदेश में डालें", - "composer.voiceStop": "■ रोकें", - "composer.stop": "■", - "composer.stopTitle": "निष्पादन रोकें", - "composer.voiceInstalling": "Parakeet V3 install हो रहा है। इसमें कुछ मिनट लग सकते हैं...", - "composer.voiceRecording": "आवाज़ रिकॉर्ड हो रही है...", - "composer.voiceTranscribing": "आवाज़ transcribe हो रही है...", - "composer.voiceMissing": "Voice helper installed नहीं है। ai-free-stt को {path} में रखें या AI_FREE_STT_BIN set करें।", - "composer.voiceUnsupported": "यह browser window microphone recording support नहीं करती।", - "composer.voiceNoSpeech": "कोई speech पहचानी नहीं गई।", - "composer.defaultImageQuestion": "इस छवि में क्या है? विस्तार से बताएं।", - "composer.imageQuestionLabel": "(छवि प्रश्न)", - "composer.uploadingImage": "छवि{num} अपलोड और प्रोसेस हो रही है: {name}...", - "composer.thinkingStatus": "सोच रहा है...", - "composer.writingStatus": "जवाब लिख रहा है…", - "composer.backgroundTask": "⚙️ कार्य पृष्ठभूमि में चल रहा है; आप दूसरे चैट पर जा सकते हैं", - "file.svgUnsupported": "SVG (\"{name}\") पहचान के लिए समर्थित नहीं है। इसे PNG या JPG के रूप में सहेजें।", - "file.imageTooLarge": "छवि \"{name}\" बहुत बड़ी है ({mb} MB)। सीमा: 10 MB।", - "file.largeImageConfirm": "\"{name}\" {mb} MB है। बड़ी फ़ाइलें DeepSeek पर अक्सर CONTENT_EMPTY लौटाती हैं।\n\nफिर भी अपलोड करें?", - "file.readFailed": "\"{name}\" पढ़ा नहीं जा सका: {message}", - "file.uploadMissingId": "Upload ने fileId नहीं लौटाया", - "file.qwenImageUnsupported": "AI Free अभी Qwen वेब ट्रांसपोर्ट के माध्यम से चित्र नहीं भेज सकता। चित्र को पूरी तरह संसाधित करने के लिए DeepSeek V4 Vision या ChatGPT चुनें।", - "file.binaryUnsupported": "फ़ाइल \"{name}\" binary है ({ext})। अभी text files और images (PNG/JPG/GIF/WEBP) समर्थित हैं।\n\nPDF और Office documents अभी काम नहीं करते - इनके लिए अलग चरण चाहिए।", - "file.textTooLarge": "फ़ाइल \"{name}\" बहुत बड़ी है ({kb} KB)। text सीमा: {limitKb} KB।", - "file.looksBinary": "फ़ाइल \"{name}\" binary लगती है। अगर यह text है, तो इसे .txt नाम दें।", - "file.remove": "हटाएँ", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "मैंने file{plural} जोड़ी है। इसे पढ़ें और उत्तर में ध्यान रखें:", - "file.promptHeader": "फ़ाइल: {name} ({kb} KB)", - "file.promptQuestion": "मेरा प्रश्न:", - "chat.delete": "चैट हटाएं", - "chat.running": "/code कार्य चल रहा है", - "chat.messages": "{count} संदेश", - "chat.deleteConfirm": "चैट हटाएं?", - "chat.history": "इतिहास: {file}", - "chat.you": "आप", - "chat.assistant": "सहायक", - "chat.reasoningProcess": "विचार प्रक्रिया", - "chat.reasoningThinking": "सोच रहा है…", - "chat.question": "प्रश्न", - "chat.system": "सिस्टम", - "install.title": "टूल इंस्टॉल करें", - "install.approve": "इंस्टॉल", - "install.reject": "रद्द करें", - "install.running": "इंस्टॉलेशन चल रहा है...", - "install.failed": "इंस्टॉलेशन विफल हुआ।", - "settings.title": "सेटिंग्स", - "settings.interface": "इंटरफ़ेस", - "settings.tabLanguage": "भाषा", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "अनुमतियाँ", - "settings.language": "भाषा", - "settings.webSearchDefault": "स्मार्ट खोज को डिफ़ॉल्ट रूप से चालू करें", - "settings.voiceTitle": "Voice input", - "settings.voiceProvider": "Model", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "तैयार", - "settings.voiceMissing": "Installed नहीं", - "settings.voiceInstallHint": "Model और runtime plugin में bundled नहीं हैं। ai-free-stt अलग से install करें या AI_FREE_STT_BIN set करें।", - "settings.languageSaved": "भाषा सहेजी गई। इंटरफ़ेस फिर से लोड हो रहा है...", - "settings.loadFailed": "सेटिंग्स लोड नहीं हो सकीं: {message}", - "settings.low": "कम जोखिम", - "settings.medium": "मध्यम जोखिम", - "settings.high": "उच्च जोखिम", - "settings.apiTitle": "OpenAI-compatible API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "OpenAI-compatible client में Base URL और ज़रूरी provider की Bearer API key डालें। Models: {models}", - "settings.anthropicApiTitle": "Anthropic-compatible API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "Auth header", - "settings.anthropicNote": "Anthropic-compatible client में /v1 के बिना Base URL और वही provider API key डालें। POST /v1/messages समर्थित है। Models: {models}", - "settings.noKey": "Key नहीं बनी", - "settings.keyCreated": "Key बन गई", - "settings.createKey": "बनाएं", - "settings.keyReady": "{label} API key तैयार है", - "settings.keyCreateFailed": "{label} API key नहीं बन सकी: {message}", - "settings.saveFailed": "सहेजा नहीं जा सका: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "डार्क", - "theme.light": "लाइट", - "theme.contrast": "कॉन्ट्रास्ट", - "theme.title": "थीम: {label}", - "shutdown.title": "CLI बंद हो गया", - "shutdown.sub": "सर्वर जवाब नहीं दे रहा। विंडो अपने आप बंद हो जाएगी।", - "shutdown.gracefulTitle": "ai-free बंद हो रहा है…", - "shutdown.stoppingTasks": "पृष्ठभूमि कार्य रोक रहे हैं…", - "shutdown.closingBrowsers": "Chrome बंद कर रहे हैं (ChatGPT / Qwen)…", - "shutdown.closingServer": "सर्वर बंद कर रहे हैं…", - "shutdown.stopped": "बंद हो गया", - "shutdown.stoppedSub": "विंडो अपने आप बंद हो जाएगी।", - "welcome.title": "AI Free में आपका स्वागत है", - "welcome.chooseProviders": "वे AI प्रदाता चुनें जिन्हें आप कनेक्ट करना चाहते हैं।", - "welcome.multi": "एक या कई चुनें। बाद में Settings में और जोड़ सकते हैं।", - "welcome.prompt1": "कॉमा से अलग नंबर दर्ज करें (जैसे \"1\" या \"1,2\"),", - "welcome.prompt2": "या DeepSeek को डिफ़ॉल्ट रखने के लिए Enter दबाएँ:", - "welcome.invalid": "⚠️ चुनाव समझ नहीं आया। DeepSeek डिफ़ॉल्ट रूप से उपयोग हो रहा है।", - "welcome.connecting": "कनेक्ट हो रहा है: {providers}", - "welcome.loginFailed": "❌ {provider} कनेक्ट नहीं हो सका: {message}", - "welcome.retryLater": "आप बाद में चैट विंडो की Settings से फिर कोशिश कर सकते हैं।", - "welcome.done": "✅ हो गया। चैट विंडो शुरू हो रही है...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/hi.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/pt.mjs b/plugin-for-vscode/src/i18n/languages/pt.mjs index ff9cf0f..70baa9c 100644 --- a/plugin-for-vscode/src/i18n/languages/pt.mjs +++ b/plugin-for-vscode/src/i18n/languages/pt.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "pt", - name: "Português", - dir: "ltr", - messages: { - "app.workspace": "Área de trabalho", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Atualizar", - "app.newChat": "+ Novo chat", - "app.noChat": "Nenhum chat selecionado", - "app.createChatHint": "Crie um chat à esquerda. Cada chat pode ser um projeto ou contexto de trabalho separado.", - "app.firstMessage": "Escreva a primeira mensagem para este projeto.", - "app.close": "Fechar", - "app.loading": "Carregando...", - "app.loadingShort": "Carregando...", - "app.error": "Erro: {message}", - "app.requestFailed": "A solicitação falhou", - "app.resizeChats": "Redimensionar lista de chats", - "app.resizeComposer": "Redimensionar área de entrada", - "newChat.title": "Novo chat", - "newChat.provider": "Provedor", - "newChat.mode": "Modo (modelo)", - "newChat.modeHint": "O modo fica fixo ao criar o chat. Para trocar depois, crie um novo chat com o modo desejado.", - "newChat.chatTitle": "Título do chat (opcional)", - "newChat.chatTitlePlaceholder": "Exemplo: refatoração auth", - "newChat.workspace": "Pasta do projeto", - "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", - "newChat.browse": "📁 Procurar", - "newChat.up": "↑ Acima", - "newChat.home": "🏠 Início", - "newChat.newFolder": "➕ Nova pasta", - "newChat.hidden": "Ocultos", - "newChat.pickFolder": "Selecionar esta pasta", - "newChat.newFolderPlaceholder": "Nome da nova pasta", - "newChat.create": "Criar", - "newChat.cancel": "Cancelar", - "newChat.createFolder": "Criar a pasta se ela não existir (somente dentro do seu $HOME)", - "newChat.submit": "Criar chat", - "newChat.emptyFolderName": "Digite um nome.", - "newChat.defaultProject": "padrão", - "newChat.truncated": "Nem todas as pastas são exibidas. Ative \"Ocultas\" ou abra a pasta superior.", - "newChat.folderCount": "Pastas: {total}{suffix}", - "newChat.hiddenSuffix": " (pastas . ocultas - caixa \"Ocultas\")", - "newChat.folderShown": "Mostrando {shown} de {total} pastas", - "newChat.tooManyFolders": "(pastas demais - refine o caminho ou ative \"Ocultas\")", - "newChat.noSubfolders": "(sem subpastas - você pode selecionar esta pasta com \"Selecionar\")", - "newChat.truncatedInline": "Mostrando as primeiras {shown} de {total}. Refine o caminho ou ative \"Ocultas\".", - "newChat.creating": "Criando chat...", - "provider.connected": "✓ Conectado", - "provider.connectedTitle": "Você está conectado. Clique para usar outra conta", - "provider.authorize": "🔑 Autorizar", - "provider.authorizeTitle": "Login necessário. Clique para entrar", - "provider.connectConfirm": "Conectar {label}?\n\nUma janela do navegador será aberta. Faça login no site; a janela fechará depois.", - "provider.chatgptConnectConfirm": "Conectar {label}?\n\nUma janela normal do Chrome será aberta uma vez para um login confiável. Ela será fechada automaticamente após a verificação da sessão ativa, e o ChatGPT continuará dentro do AI Free.", - "provider.chatgptEmbedLogin": "Conclua o login na janela do Chrome. Ela será fechada automaticamente somente após a verificação da sessão ativa.", - "provider.chatgptEmbedLoginTimeout": "O tempo de login em {label} expirou. Clique em «Entrar com o Chrome» e tente novamente.", - "provider.connectedAlert": "{label} conectado.", - "provider.tokenMissing": "O login terminou, mas nenhum token foi encontrado. Tente novamente ou execute: npm run login-{id}", - "provider.connectFailed": "Não foi possível conectar {label}: {message}", - "provider.deepseekFast": "chat normal rápido", - "provider.deepseekExpert": "raciocínio / R1", - "provider.deepseekVision": "reconhecimento de imagens", - "provider.qwenDefault": "escolha o modelo no cabeçalho do chat", - "role.assistantDescription": "Assistente normal", - "role.assistant": "Assistente", - "role.assistant.label": "Assistente", - "role.assistant.description": "Assistente normal para chat e respostas rápidas.", - "role.prompt_builder.label": "Construtor de prompts", - "role.prompt_builder.description": "Esclarece a tarefa e a transforma em um prompt de trabalho para os próximos passos.", - "role.architect.label": "Arquiteto", - "role.architect.description": "Projeta a solução, limites dos módulos, dados e riscos.", - "role.developer.label": "Desenvolvedor", - "role.developer.description": "Propõe implementação, arquivos, passos e detalhes técnicos.", - "role.tester.label": "Testador", - "role.tester.description": "Encontra verificações, casos extremos, regressões e cenários de teste.", - "role.reviewer.label": "Revisor", - "role.reviewer.description": "Verifica criticamente o plano/resultado e procura pontos fracos.", - "role.synthesizer.label": "Sintetizador", - "role.synthesizer.description": "Combina as saídas do pipeline em um resumo curto e próximos passos.", - "topbar.model": "Modelo", - "topbar.role": "Função deste chat no pipeline", - "topbar.coderTitle": "Ativar modo agente: o modelo pode criar e editar arquivos", - "topbar.coder": "🛠 Programador", - "topbar.coderOn": "🛠 Programador ATIVO", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ATIVO", - "topbar.pipeline": "Fluxo", - "topbar.pipelineOn": "Fluxo ON", - "topbar.hardwareTitle": "ESP / firmware de placas: ativa o perfil de agente de hardware", - "topbar.pipelineTitle": "Passar mensagens pelos links do pipeline", - "topbar.flow": "Fluxo", - "topbar.flowTitle": "Fluxo do pipeline", - "topbar.theme": "Alterar tema", - "topbar.settings": "Configurações / comandos permitidos", - "topbar.quit": "Sair — parar o app e fechar o Chrome", - "pipeline.title": "Fluxo do pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Atribua uma função a cada chat e escolha o próximo passo.", - "pipeline.empty": "Crie vários chats e conecte-os aqui.", - "pipeline.end": "Fim", - "pipeline.user": "Usuário", - "pipeline.model": "modelo", - "composer.chooseChat": "Escolha um chat à esquerda...", - "composer.message": "Mensagem para {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Pensamento profundo", - "composer.thinkingTitle": "Pensamento profundo: o modelo mostra a cadeia de raciocínio", - "composer.thinkingRequired": "Pensamento profundo é obrigatório para este modelo", - "composer.search": "🌐 Busca inteligente", - "composer.searchTitle": "Busca inteligente: o modelo usa busca na web para informações atuais", - "composer.attach": "📎 Arquivo", - "composer.attachTitle": "Anexar um arquivo de texto para leitura", - "composer.voice": "🎙 Voz", - "composer.voiceTitle": "Gravar voz e inserir a transcrição na mensagem", - "composer.voiceStop": "■ Parar", - "composer.stop": "■", - "composer.stopTitle": "Parar execução", - "composer.voiceInstalling": "Instalando Parakeet V3. Isso pode levar alguns minutos...", - "composer.voiceRecording": "Gravando voz...", - "composer.voiceTranscribing": "Transcrevendo voz...", - "composer.voiceMissing": "O helper de voz não está instalado. Coloque ai-free-stt em {path} ou defina AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Esta janela do navegador não suporta gravação de microfone.", - "composer.voiceNoSpeech": "Nenhuma fala foi reconhecida.", - "composer.defaultImageQuestion": "O que há nesta imagem? Descreva em detalhes.", - "composer.imageQuestionLabel": "(pergunta sobre imagem)", - "composer.uploadingImage": "Enviando e processando imagem{num}: {name}...", - "composer.thinkingStatus": "Pensando...", - "composer.writingStatus": "Escrevendo resposta…", - "composer.backgroundTask": "⚙️ A tarefa está rodando em segundo plano; você pode mudar para outro chat", - "file.svgUnsupported": "SVG (\"{name}\") não é suportado para reconhecimento. Salve como PNG ou JPG.", - "file.imageTooLarge": "A imagem \"{name}\" é grande demais ({mb} MB). Limite: 10 MB.", - "file.largeImageConfirm": "\"{name}\" tem {mb} MB. Arquivos grandes frequentemente retornam CONTENT_EMPTY no DeepSeek.\n\nEnviar mesmo assim?", - "file.readFailed": "Não foi possível ler \"{name}\": {message}", - "file.uploadMissingId": "O upload retornou sem fileId", - "file.qwenImageUnsupported": "O AI Free ainda não pode enviar imagens pelo transporte web do Qwen. Selecione DeepSeek V4 Vision ou ChatGPT para processar a imagem.", - "file.binaryUnsupported": "O arquivo \"{name}\" é binário ({ext}). Atualmente há suporte a arquivos de texto e imagens (PNG/JPG/GIF/WEBP).\n\nPDFs e documentos Office ainda não funcionam: precisam de uma fase separada.", - "file.textTooLarge": "O arquivo \"{name}\" é grande demais ({kb} KB). Limite para texto: {limitKb} KB.", - "file.looksBinary": "O arquivo \"{name}\" parece binário. Se for texto, renomeie para .txt.", - "file.remove": "Remover", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "Anexei arquivo{plural}. Leia e considere na sua resposta:", - "file.promptHeader": "Arquivo: {name} ({kb} KB)", - "file.promptQuestion": "Minha pergunta:", - "chat.delete": "Excluir chat", - "chat.running": "A tarefa /code está em execução", - "chat.messages": "{count} mensagens", - "chat.deleteConfirm": "Excluir chat?", - "chat.history": "Histórico: {file}", - "chat.you": "Você", - "chat.assistant": "Assistente", - "chat.reasoningProcess": "Processo de raciocínio", - "chat.reasoningThinking": "Pensando…", - "chat.question": "Pergunta", - "chat.system": "Sistema", - "install.title": "Instalar ferramenta", - "install.approve": "Instalar", - "install.reject": "Cancelar", - "install.running": "Instalação em andamento...", - "install.failed": "A instalação falhou.", - "settings.title": "Configurações", - "settings.interface": "Interface", - "settings.tabLanguage": "Idioma", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permissões", - "settings.language": "Idioma", - "settings.webSearchDefault": "Ativar busca inteligente por padrão", - "settings.voiceTitle": "Entrada de voz", - "settings.voiceProvider": "Modelo", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Pronto", - "settings.voiceMissing": "Não instalado", - "settings.voiceInstallHint": "O modelo e o runtime não vêm no plugin. Instale ai-free-stt separadamente ou defina AI_FREE_STT_BIN.", - "settings.languageSaved": "Idioma salvo. Recarregando a interface...", - "settings.loadFailed": "Não foi possível carregar as configurações: {message}", - "settings.low": "Baixo risco", - "settings.medium": "Risco médio", - "settings.high": "Alto risco", - "settings.apiTitle": "API compatível com OpenAI", - "settings.baseUrl": "URL base", - "settings.apiNote": "Em um cliente compatível com OpenAI, use a URL base e a chave Bearer do provedor necessário. Modelos: {models}", - "settings.anthropicApiTitle": "API compatível com Anthropic", - "settings.anthropicBaseUrl": "URL base", - "settings.anthropicEndpoint": "Endpoint de Messages", - "settings.anthropicAuth": "Cabeçalho de autenticação", - "settings.anthropicNote": "Em um cliente compatível com Anthropic, use a URL base sem /v1 e a mesma chave do provedor. POST /v1/messages é suportado. Modelos: {models}", - "settings.noKey": "Chave não criada", - "settings.keyCreated": "Chave criada", - "settings.createKey": "Criar", - "settings.keyReady": "Chave API de {label} pronta", - "settings.keyCreateFailed": "Não foi possível criar a chave API de {label}: {message}", - "settings.saveFailed": "Não foi possível salvar: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Escuro", - "theme.light": "Claro", - "theme.contrast": "Contraste", - "theme.title": "Tema: {label}", - "shutdown.title": "CLI parado", - "shutdown.sub": "O servidor não responde mais. A janela será fechada automaticamente.", - "shutdown.gracefulTitle": "Parando ai-free…", - "shutdown.stoppingTasks": "Parando tarefas em segundo plano…", - "shutdown.closingBrowsers": "Fechando Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Parando o servidor…", - "shutdown.stopped": "Parado", - "shutdown.stoppedSub": "A janela será fechada automaticamente.", - "welcome.title": "Bem-vindo ao AI Free", - "welcome.chooseProviders": "Escolha os provedores de IA que deseja conectar.", - "welcome.multi": "Escolha um ou vários. Você pode adicionar mais depois em Configurações.", - "welcome.prompt1": "Digite números separados por vírgulas (por exemplo \"1\" ou \"1,2\"),", - "welcome.prompt2": "ou pressione Enter para usar DeepSeek por padrão:", - "welcome.invalid": "⚠️ Não foi possível entender a escolha. Usando DeepSeek por padrão.", - "welcome.connecting": "Conectando: {providers}", - "welcome.loginFailed": "❌ Não foi possível conectar {provider}: {message}", - "welcome.retryLater": "Você pode tentar novamente mais tarde em Configurações na janela de chat.", - "welcome.done": "✅ Pronto. Iniciando a janela de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/pt.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/ru.mjs b/plugin-for-vscode/src/i18n/languages/ru.mjs index 61346a6..8150268 100644 --- a/plugin-for-vscode/src/i18n/languages/ru.mjs +++ b/plugin-for-vscode/src/i18n/languages/ru.mjs @@ -1,315 +1,2 @@ -export const language = { - code: "ru", - name: "Русский", - dir: "ltr", - messages: { - "app.workspace": "Рабочая область", - "sidebar.menu": "Меню", - "sidebar.plugins": "Плагины", - "sidebar.telegram": "Telegram", - "app.refresh": "Обновить", - "app.newChat": "+ Новый чат", - "app.noChat": "Чат не выбран", - "app.createChatHint": "Создай чат слева. Каждый чат можно использовать как отдельный проект или рабочий контекст.", - "app.firstMessage": "Напиши первое сообщение для этого проекта.", - "app.close": "Закрыть", - "app.loading": "Загрузка...", - "app.loadingShort": "Загружаю...", - "app.error": "Ошибка: {message}", - "app.requestFailed": "Запрос не удался", - "app.resizeChats": "Изменить ширину списка чатов", - "app.resizeComposer": "Изменить высоту формы ввода", - "newChat.title": "Новый чат", - "newChat.provider": "Провайдер", - "newChat.mode": "Режим (модель)", - "newChat.modeHint": "Режим зафиксируется при создании чата. Переключить потом нельзя - создавай новый чат в нужном режиме.", - "newChat.chatTitle": "Название чата (опционально)", - "newChat.chatTitlePlaceholder": "Например: рефакторинг auth", - "newChat.workspace": "Папка проекта", - "newChat.workspacePlaceholder": "/Users/.../project или ~/Projects/new-thing", - "newChat.browse": "📁 Обзор", - "newChat.up": "↑ Вверх", - "newChat.home": "🏠 Домой", - "newChat.newFolder": "➕ Новая папка", - "newChat.hidden": "Скрытые", - "newChat.pickFolder": "Выбрать эту папку", - "newChat.newFolderPlaceholder": "Имя новой папки", - "newChat.create": "Создать", - "newChat.cancel": "Отмена", - "newChat.createFolder": "Создать папку, если её ещё нет (только под твоим $HOME)", - "newChat.submit": "Создать чат", - "newChat.emptyFolderName": "Введи имя.", - "newChat.defaultProject": "по умолчанию", - "newChat.truncated": "Показаны не все папки - включи \"Скрытые\" или открой родительскую папку выше.", - "newChat.folderCount": "Папок: {total}{suffix}", - "newChat.hiddenSuffix": " (скрытые .папки - чекбокс \"Скрытые\")", - "newChat.folderShown": "Показано {shown} из {total} папок", - "newChat.tooManyFolders": "(слишком много папок - уточни путь или включи \"Скрытые\")", - "newChat.noSubfolders": "(нет подпапок - можно выбрать эту папку кнопкой \"Выбрать\")", - "newChat.truncatedInline": "Показаны первые {shown} из {total} - сузь путь или включи \"Скрытые\".", - "newChat.creating": "Создаю чат...", - "provider.connected": "✓ Подключено", - "provider.connectedTitle": "Вы авторизованы. Нажмите, если хотите войти под другим аккаунтом", - "provider.authorize": "🔑 Авторизоваться", - "provider.authorizeTitle": "Требуется авторизация. Нажмите, чтобы войти в аккаунт", - "provider.connectConfirm": "Подключить {label}?\n\nОткроется окно браузера - залогинься на сайте. Окно закроется само после входа.", - "provider.chatgptConnectConfirm": "Подключить {label}?\n\nДля надёжного входа один раз откроется обычный Chrome. После проверки активной сессии окно закроется автоматически, а ChatGPT продолжит работать внутри AI Free.", - "provider.chatgptEmbedLogin": "Завершите вход в открывшемся окне Chrome. Оно закроется автоматически только после проверки активной сессии.", - "provider.chatgptEmbedLoginTimeout": "Время ожидания входа в {label} истекло. Нажмите «Войти через Chrome» и повторите вход.", - "provider.connectedAlert": "{label} подключён.", - "provider.tokenMissing": "Логин завершён, но токен не найден. Попробуй ещё раз или: npm run login-{id}", - "provider.connectFailed": "Не удалось подключить {label}: {message}", - "provider.deepseekFast": "быстрый обычный чат", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "распознавание изображений", - "provider.qwenDefault": "выбор модели в шапке чата", - "role.assistantDescription": "Обычный помощник", - "role.assistant": "Ассистент", - "role.assistant.label": "Ассистент", - "role.assistant.description": "Обычный помощник для чата и быстрых ответов.", - "role.prompt_builder.label": "Конструктор промптов", - "role.prompt_builder.description": "Уточняет задачу и превращает её в рабочий промпт для следующих шагов.", - "role.architect.label": "Архитектор", - "role.architect.description": "Проектирует решение, границы модулей, данные и риски.", - "role.developer.label": "Разработчик", - "role.developer.description": "Предлагает реализацию, файлы, шаги и технические детали.", - "role.tester.label": "Тестировщик", - "role.tester.description": "Ищет проверки, edge cases, регрессии и сценарии тестирования.", - "role.reviewer.label": "Ревьюер", - "role.reviewer.description": "Критически проверяет план/результат и ищет слабые места.", - "role.synthesizer.label": "Синтезатор", - "role.synthesizer.description": "Собирает выводы цепочки в короткий итог и следующие шаги.", - "topbar.model": "Модель", - "topbar.role": "Роль этого чата в pipeline", - "topbar.coderTitle": "Включить режим агента - модель сама создаёт/редактирует файлы", - "topbar.coder": "🛠 Кодер", - "topbar.coderOn": "🛠 Кодер ВКЛ", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ВКЛ", - "topbar.pipeline": "Цепочка", - "topbar.pipelineOn": "Цепочка ВКЛ", - "topbar.hardwareTitle": "ESP / прошивка плат - включает аппаратный профиль агента", - "topbar.pipelineTitle": "Передавать сообщения по связям pipeline", - "topbar.memoryTitle": "Долговременная память агента — прошлые ошибки и решения", - "topbar.memory": "🧠 Память", - "topbar.memoryOn": "🧠 Память ВКЛ", - "topbar.autoSkillTitle": "Автоматически подбирать skill по задаче", - "topbar.autoSkill": "Skill авто", - "topbar.autoSkillOn": "Skill авто ВКЛ", - "topbar.skillTitle": "Skill для code-agent в этом чате", - "topbar.skillNone": "Skill: авто", - "topbar.flow": "Схема", - "topbar.flowTitle": "Схема цепочки", - "topbar.theme": "Сменить тему", - "topbar.settings": "Настройки / разрешённые команды", - "topbar.quit": "Выход — остановить приложение и закрыть Chrome", - "pipeline.title": "Схема цепочки", - "pipeline.makeLeader": "Сделать текущий чат главным", - "pipeline.addAgent": "+ Добавить подчинённого агента", - "pipeline.leaderSet": "Главный агент: {title}", - "pipeline.rolePrompt": "Роль нового агента: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Агент добавлен: {title}", - "agentDrawer.title": "Агент: память и skills", - "agentDrawer.sub": "Режимы, память, skills, браузер workspace", - "agentDrawer.tabAgent": "Агент", - "agentDrawer.tabBrowser": "Браузер", - "agentDrawer.modes": "Режимы", - "agentDrawer.memorySkills": "Память и skills", - "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — отдельный Chrome.", - "pipeline.sub": "Задай роль каждому чату и выбери следующий шаг.", - "pipeline.empty": "Создай несколько чатов, затем свяжи их здесь.", - "pipeline.end": "Конец", - "pipeline.user": "Пользователь", - "pipeline.model": "модель", - "composer.chooseChat": "Выбери чат слева...", - "composer.message": "Сообщение {label}...", - "composer.coderActive": "Режим Coder: опишите задачу для code-agent…", - "composer.thinking": "⚛ Глубокое мышление", - "composer.thinkingTitle": "Глубокое мышление - модель показывает chain-of-thought", - "composer.thinkingRequired": "Глубокое мышление обязательно для этой модели", - "composer.search": "🌐 Умный поиск", - "composer.searchTitle": "Умный поиск - модель использует веб-поиск для актуальной инфы", - "composer.attach": "📎 Файл", - "composer.attachTitle": "Прикрепить текстовый файл для чтения", - "composer.voice": "🎙 Голос", - "composer.voiceTitle": "Записать голос и вставить расшифровку в сообщение", - "composer.voiceStop": "■ Стоп", - "composer.stop": "■", - "composer.stopTitle": "Остановить выполнение", - "composer.voiceInstalling": "Устанавливаю Parakeet V3. Это может занять несколько минут...", - "composer.voiceRecording": "Идёт запись голоса...", - "composer.voiceTranscribing": "Расшифровываю голос...", - "composer.voiceMissing": "Голосовой helper не установлен. Поставь ai-free-stt в {path} или укажи AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Браузерное окно не поддерживает запись микрофона.", - "composer.voiceNoSpeech": "Не получилось распознать речь.", - "composer.defaultImageQuestion": "Что на этом изображении? Опиши подробно.", - "composer.imageQuestionLabel": "(вопрос по изображению)", - "composer.uploadingImage": "Заливаю и обрабатываю изображение{num}: {name}...", - "composer.thinkingStatus": "Думаю...", - "composer.writingStatus": "Пишет ответ…", - "composer.backgroundTask": "⚙️ Задача выполняется в фоне - можно перейти в другой чат", - "file.svgUnsupported": "SVG (\"{name}\") не поддерживается для распознавания. Сохрани как PNG или JPG.", - "file.imageTooLarge": "Картинка \"{name}\" слишком большая ({mb} МБ). Лимит 10 МБ.", - "file.largeImageConfirm": "\"{name}\" - {mb} МБ. Большие файлы часто получают CONTENT_EMPTY на DeepSeek.\n\nЗагрузить всё равно?", - "file.readFailed": "Не удалось прочитать \"{name}\": {message}", - "file.uploadMissingId": "Загрузка вернулась без fileId", - "file.qwenImageUnsupported": "AI Free пока не может передать изображение в веб-транспорт Qwen. Выберите DeepSeek V4 Vision или ChatGPT — там картинка будет обработана полностью.", - "file.binaryUnsupported": "Файл \"{name}\" - бинарный ({ext}). Сейчас поддерживаются текстовые файлы и изображения (PNG/JPG/GIF/WEBP).\n\nPDF и Office-документы пока не работают - для них нужна отдельная фаза.", - "file.textTooLarge": "Файл \"{name}\" слишком большой ({kb} КБ). Лимит {limitKb} КБ для текстовых.", - "file.looksBinary": "Файл \"{name}\" похож на бинарный. Если уверен, что текстовый - переименуй в .txt.", - "file.remove": "Удалить", - "file.sizeKb": "{kb} КБ", - "file.promptPrefix": "Я прикрепил файл{plural} - прочитай и учитывай при ответе:", - "file.promptHeader": "Файл: {name} ({kb} КБ)", - "file.promptQuestion": "Мой вопрос:", - "chat.delete": "Удалить чат", - "chat.running": "Выполняется /code-задача", - "chat.messages": "{count} сообщений", - "chat.deleteConfirm": "Удалить чат?", - "chat.history": "История: {file}", - "chat.you": "Вы", - "chat.assistant": "Ассистент", - "chat.reasoningProcess": "Процесс размышления", - "chat.reasoningThinking": "Размышляет…", - "chat.question": "Вопрос", - "chat.system": "Система", - "install.title": "Установить инструмент", - "install.approve": "Установить", - "install.reject": "Отмена", - "install.running": "Установка выполняется...", - "install.failed": "Установка завершилась ошибкой.", - "settings.title": "Настройки", - "settings.agentTitle": "Память и skills", - "settings.memoryDefault": "Память включена для новых чатов", - "settings.memoryDefaultDesc": "Агент ищет прошлые ошибки и решения перед /code-задачей.", - "settings.autoSkillDefault": "Auto-skill для новых чатов", - "settings.autoSkillDefaultDesc": "Подбирает skill по ключевым словам (review, fix, bug…).", - "settings.installedSkills": "Установленные skills", - "settings.noSkills": "Skills не найдены. Встроенные: code-review, bug-fix.", - "settings.installedPlugins": "Плагины (Codex / Claude Code)", - "settings.noPlugins": "Плагины не установлены.", - "settings.installPlugin": "Установить", - "settings.installPluginHint": "Поддержка .codex-plugin/plugin.json и .claude-plugin/plugin.json со skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo или URL GitHub", - "settings.pluginInstalled": "Плагин установлен", - "settings.pluginRemoved": "Плагин удалён", - "settings.uninstallPlugin": "Удалить плагин", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Настройки агента сохранены", - "settings.recentMemory": "Недавняя память", - "settings.recentMemoryHint": "Записи агента для текущего workspace. Можно удалить устаревшие.", - "settings.memoryEmpty": "Память пуста для этого проекта.", - "settings.memoryNoWorkspace": "без workspace", - "settings.deleteMemory": "Удалить запись", - "settings.memoryDeleted": "Запись памяти удалена", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS или JSON fallback)", - "agent.memoryUsed": "Память: использовано {count}", - "agent.graphUsed": "граф: {count}", - "agent.memoryPending": "память сохраняется…", - "agent.memorySaved": "сохранено {count}", - "agent.skillUsed": "skill: {skill}", - "settings.interface": "Интерфейс", - "settings.tabLanguage": "Язык", - "settings.tabAgent": "Агент", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Подключение Telegram", - "settings.telegramHint": "Укажите только токен бота. Chat ID можно оставить пустым: он привяжется автоматически после команды /start в Telegram.", - "settings.telegramEnabled": "Включить Telegram", - "settings.telegramEnabledDesc": "Сохранить настройки подключения.", - "settings.telegramBotToken": "Токен бота", - "settings.telegramChatId": "Chat ID (необязательно)", - "settings.telegramSave": "Сохранить", - "settings.telegramSaved": "Настройки Telegram сохранены", - "settings.tabUpdate": "Обновление", - "settings.tabApi": "API", - "settings.tabPermissions": "Разрешения", - "settings.tabStatus": "Статус", - "health.title": "Статус системы", - "health.refresh": "Обновить", - "health.copyReport": "Скопировать отчёт", - "health.ready": "Готов", - "health.needsLogin": "Нужен вход", - "health.copied": "Диагностический отчёт скопирован", - "health.copyManual": "Выделил отчёт, скопируй вручную", - "settings.language": "Язык", - "settings.webSearchDefault": "Включать умный поиск по умолчанию", - "settings.voiceTitle": "Голосовой ввод", - "settings.voiceProvider": "Модель", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Готово", - "settings.voiceMissing": "Не установлен", - "settings.voiceInstallHint": "Модель и runtime не входят в плагин. Установи ai-free-stt отдельно или укажи AI_FREE_STT_BIN.", - "settings.languageSaved": "Язык сохранён. Перезагружаю интерфейс...", - "settings.loadFailed": "Не удалось загрузить настройки: {message}", - "settings.low": "Низкий риск", - "settings.medium": "Средний риск", - "settings.high": "Высокий риск", - "settings.apiTitle": "API, совместимое с OpenAI", - "settings.baseUrl": "Базовый URL", - "settings.apiNote": "В OpenAI-compatible клиенте укажи Base URL и Bearer API key нужного провайдера. Модели: {models}", - "settings.anthropicApiTitle": "API, совместимое с Anthropic", - "settings.anthropicBaseUrl": "Базовый URL", - "settings.anthropicEndpoint": "Эндпоинт Messages", - "settings.anthropicAuth": "Заголовок авторизации", - "settings.anthropicNote": "В Anthropic-compatible клиенте укажи Base URL без /v1 и API key того же провайдера. Поддерживается POST /v1/messages. Модели: {models}", - "settings.noKey": "Ключ не создан", - "settings.keyCreated": "Ключ создан", - "settings.createKey": "Создать", - "settings.keyReady": "{label} API key готов", - "settings.keyCreateFailed": "Не удалось создать {label} API key: {message}", - "settings.saveFailed": "Не удалось сохранить: {message}", - "settings.agentPermissions": "Разрешения агентов", - "settings.allowPythonModuleAndEval": "Разрешить python -m и python -c", - "settings.allowPythonModuleAndEvalDesc": "Позволяет агенту запускать Python-модули и inline-код. Включай только для доверенных проектов.", - "settings.allowShell": "Разрешить shell-команды (run_shell)", - "settings.allowShellDesc": "Пайпы, &&, перенаправления: grep -r foo . | head, find … | xargs и т.д.", - "permission.title": "Нужно разрешение", - "permission.description": "Агент запросил действие, которое отключено в настройках безопасности.", - "permission.settingsHint": "Можно включить это сейчас или позже в Settings → Разрешения.", - "permission.approve": "Включить", - "permission.reject": "Не включать", - "permission.enabled": "Разрешение включено. Повтори задачу.", - - "update.title": "Обновление десктопной версии", - "update.notChecked": "Проверка ещё не выполнялась.", - "update.check": "Проверить", - "update.install": "Обновить", - "update.checking": "Проверяю GitHub...", - "update.available": "Доступна новая версия.", - "update.upToDate": "Установлена актуальная версия.", - "update.gitRequired": "Новая версия есть, но автообновление доступно только для git-установки.", - "update.checkFailed": "Не удалось проверить обновление: {message}", - "update.installing": "Обновляю через git. Если npm доступен, зависимости установятся автоматически...", - "update.installed": "Обновление установлено. Перезапусти AI Free.", - "update.installFailed": "Не удалось обновить: {message}", - "update.confirm": "Запустить обновление AI Free?\n\nБудет выполнено: git pull --ff-only и npm install. Чаты в ~/.deepseek-cli/state.json не удаляются.", - "update.note": "Обновляется только код приложения в папке проекта. Чаты, настройки и авторизация хранятся отдельно в ~/.deepseek-cli и ~/.qwen-cli.", - "update.currentVersion": "Текущая", - "update.latestVersion": "Последняя", - "update.projectRoot": "Папка", - - "theme.dark": "Тёмная", - "theme.light": "Светлая", - "theme.contrast": "Контраст", - "theme.title": "Тема: {label}", - "shutdown.title": "CLI остановлен", - "shutdown.sub": "Сервер больше не отвечает. Окно закроется автоматически.", - "shutdown.gracefulTitle": "Останавливаем ai-free…", - "shutdown.stoppingTasks": "Останавливаем фоновые задачи…", - "shutdown.closingBrowsers": "Закрываем Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Останавливаем сервер…", - "shutdown.stopped": "Остановлено", - "shutdown.stoppedSub": "Окно закроется автоматически.", - "welcome.title": "Добро пожаловать в AI Free", - "welcome.chooseProviders": "Выбери AI-провайдеров, которых хочешь подключить.", - "welcome.multi": "Можно один, можно несколько - позже добавишь ещё через Settings.", - "welcome.prompt1": "Введи номера через запятую (например \"1\" или \"1,2\"),", - "welcome.prompt2": "или нажми Enter для DeepSeek по умолчанию:", - "welcome.invalid": "⚠️ Не понял выбор. Использую DeepSeek по умолчанию.", - "welcome.connecting": "Подключаю: {providers}", - "welcome.loginFailed": "❌ Не удалось подключить {provider}: {message}", - "welcome.retryLater": "Можно повторить позже через Settings в окне чатов.", - "welcome.done": "✅ Готово. Запускаю окно чатов...", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/ru.mjs"; diff --git a/plugin-for-vscode/src/i18n/languages/zh.mjs b/plugin-for-vscode/src/i18n/languages/zh.mjs index adaee8a..66bd1f2 100644 --- a/plugin-for-vscode/src/i18n/languages/zh.mjs +++ b/plugin-for-vscode/src/i18n/languages/zh.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "zh", - name: "中文", - dir: "ltr", - messages: { - "app.workspace": "工作区", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "刷新", - "app.newChat": "+ 新聊天", - "app.noChat": "未选择聊天", - "app.createChatHint": "在左侧创建聊天。每个聊天都可以作为单独的项目或工作上下文。", - "app.firstMessage": "为这个项目写第一条消息。", - "app.close": "关闭", - "app.loading": "加载中...", - "app.loadingShort": "正在加载...", - "app.error": "错误:{message}", - "app.requestFailed": "请求失败", - "app.resizeChats": "调整聊天列表宽度", - "app.resizeComposer": "调整输入区域高度", - "newChat.title": "新聊天", - "newChat.provider": "提供商", - "newChat.mode": "模式(模型)", - "newChat.modeHint": "模式在创建聊天时固定。之后如需切换,请用所需模式创建新聊天。", - "newChat.chatTitle": "聊天标题(可选)", - "newChat.chatTitlePlaceholder": "例如:auth 重构", - "newChat.workspace": "项目文件夹", - "newChat.workspacePlaceholder": "/Users/.../project 或 ~/Projects/new-thing", - "newChat.browse": "📁 浏览", - "newChat.up": "↑ 上级", - "newChat.home": "🏠 主页", - "newChat.newFolder": "➕ 新建文件夹", - "newChat.hidden": "隐藏", - "newChat.pickFolder": "选择此文件夹", - "newChat.newFolderPlaceholder": "新文件夹名称", - "newChat.create": "创建", - "newChat.cancel": "取消", - "newChat.createFolder": "如果文件夹不存在则创建(仅限你的 $HOME 下)", - "newChat.submit": "创建聊天", - "newChat.emptyFolderName": "请输入名称。", - "newChat.defaultProject": "默认", - "newChat.truncated": "未显示所有文件夹。启用“隐藏”或打开上级文件夹。", - "newChat.folderCount": "文件夹:{total}{suffix}", - "newChat.hiddenSuffix": "(隐藏的 .文件夹 - “隐藏”复选框)", - "newChat.folderShown": "显示 {shown} / {total} 个文件夹", - "newChat.tooManyFolders": "(文件夹太多 - 缩小路径或启用“隐藏”)", - "newChat.noSubfolders": "(没有子文件夹 - 可用“选择”按钮选择此文件夹)", - "newChat.truncatedInline": "显示前 {shown} / {total} 个。缩小路径或启用“隐藏”。", - "newChat.creating": "正在创建聊天...", - "provider.connected": "✓ 已连接", - "provider.connectedTitle": "你已登录。点击可使用其他账号", - "provider.authorize": "🔑 授权", - "provider.authorizeTitle": "需要登录。点击登录", - "provider.connectConfirm": "连接 {label}?\n\n将打开浏览器窗口。请在网站登录;登录后窗口会关闭。", - "provider.chatgptConnectConfirm": "连接 {label}?\n\n首次可靠登录会打开普通 Chrome 窗口。验证有效会话后窗口将自动关闭,ChatGPT 随后会继续在 AI Free 内运行。", - "provider.chatgptEmbedLogin": "请在 Chrome 窗口中完成登录。只有验证有效会话后,该窗口才会自动关闭。", - "provider.chatgptEmbedLoginTimeout": "登录 {label} 超时。请点击“使用 Chrome 登录”后重试。", - "provider.connectedAlert": "{label} 已连接。", - "provider.tokenMissing": "登录完成,但未找到令牌。请重试或运行:npm run login-{id}", - "provider.connectFailed": "无法连接 {label}:{message}", - "provider.deepseekFast": "快速普通聊天", - "provider.deepseekExpert": "推理 / R1", - "provider.deepseekVision": "图像识别", - "provider.qwenDefault": "在聊天顶部选择模型", - "role.assistantDescription": "普通助手", - "role.assistant": "助手", - "role.assistant.label": "助手", - "role.assistant.description": "用于聊天和快速回答的普通助手。", - "role.prompt_builder.label": "提示词构建器", - "role.prompt_builder.description": "澄清任务并将其转成后续步骤可执行的提示词。", - "role.architect.label": "架构师", - "role.architect.description": "设计方案、模块边界、数据和风险。", - "role.developer.label": "开发者", - "role.developer.description": "提出实现、文件、步骤和技术细节。", - "role.tester.label": "测试者", - "role.tester.description": "寻找检查项、边界情况、回归风险和测试场景。", - "role.reviewer.label": "审查者", - "role.reviewer.description": "批判性检查计划/结果并寻找薄弱点。", - "role.synthesizer.label": "汇总者", - "role.synthesizer.description": "将 pipeline 输出合并为简短总结和下一步。", - "topbar.model": "模型", - "topbar.role": "此聊天在 pipeline 中的角色", - "topbar.coderTitle": "启用代理模式:模型可创建和编辑文件", - "topbar.coder": "🛠 编码器", - "topbar.coderOn": "🛠 编码器开", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP 开", - "topbar.pipeline": "流程", - "topbar.pipelineOn": "流程开", - "topbar.hardwareTitle": "ESP / 板卡固件:启用硬件代理配置", - "topbar.pipelineTitle": "沿 pipeline 连接传递消息", - "topbar.flow": "流程", - "topbar.flowTitle": "Pipeline 流程", - "topbar.theme": "切换主题", - "topbar.settings": "设置 / 允许的命令", - "topbar.quit": "退出 — 停止应用并关闭 Chrome", - "pipeline.title": "Pipeline 流程", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "为每个聊天分配角色并选择下一步。", - "pipeline.empty": "创建多个聊天,然后在这里连接它们。", - "pipeline.end": "结束", - "pipeline.user": "用户", - "pipeline.model": "模型", - "composer.chooseChat": "在左侧选择聊天...", - "composer.message": "发送给 {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ 深度思考", - "composer.thinkingTitle": "深度思考:模型显示思维链", - "composer.thinkingRequired": "此模型必须启用深度思考", - "composer.search": "🌐 智能搜索", - "composer.searchTitle": "智能搜索:模型使用网页搜索获取最新信息", - "composer.attach": "📎 文件", - "composer.attachTitle": "附加要读取的文本文件", - "composer.voice": "🎙 语音", - "composer.voiceTitle": "录音并把转写插入消息", - "composer.voiceStop": "■ 停止", - "composer.stop": "■", - "composer.stopTitle": "停止执行", - "composer.voiceInstalling": "正在安装 Parakeet V3。这可能需要几分钟...", - "composer.voiceRecording": "正在录音...", - "composer.voiceTranscribing": "正在转写语音...", - "composer.voiceMissing": "未安装语音 helper。请把 ai-free-stt 放到 {path},或设置 AI_FREE_STT_BIN。", - "composer.voiceUnsupported": "此浏览器窗口不支持麦克风录音。", - "composer.voiceNoSpeech": "未识别到语音。", - "composer.defaultImageQuestion": "这张图片里有什么?请详细描述。", - "composer.imageQuestionLabel": "(图片问题)", - "composer.uploadingImage": "正在上传并处理图片{num}:{name}...", - "composer.thinkingStatus": "正在思考...", - "composer.writingStatus": "正在撰写回复…", - "composer.backgroundTask": "⚙️ 任务正在后台运行;你可以切换到其他聊天", - "file.svgUnsupported": "不支持识别 SVG(\"{name}\")。请保存为 PNG 或 JPG。", - "file.imageTooLarge": "图片 \"{name}\" 太大({mb} MB)。限制:10 MB。", - "file.largeImageConfirm": "\"{name}\" 为 {mb} MB。大文件在 DeepSeek 上经常返回 CONTENT_EMPTY。\n\n仍要上传吗?", - "file.readFailed": "无法读取 \"{name}\":{message}", - "file.uploadMissingId": "上传返回时没有 fileId", - "file.qwenImageUnsupported": "AI Free 暂时无法通过 Qwen 网页传输发送图片。请选择 DeepSeek V4 Vision 或 ChatGPT 来完整处理图片。", - "file.binaryUnsupported": "文件 \"{name}\" 是二进制文件({ext})。当前支持文本文件和图片(PNG/JPG/GIF/WEBP)。\n\nPDF 和 Office 文档暂不支持,需要单独阶段。", - "file.textTooLarge": "文件 \"{name}\" 太大({kb} KB)。文本限制:{limitKb} KB。", - "file.looksBinary": "文件 \"{name}\" 看起来像二进制。如果确定是文本,请重命名为 .txt。", - "file.remove": "移除", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "我附加了文件{plural}。请阅读并在回答中考虑:", - "file.promptHeader": "文件:{name}({kb} KB)", - "file.promptQuestion": "我的问题:", - "chat.delete": "删除聊天", - "chat.running": "/code 任务正在运行", - "chat.messages": "{count} 条消息", - "chat.deleteConfirm": "删除聊天?", - "chat.history": "历史:{file}", - "chat.you": "你", - "chat.assistant": "助手", - "chat.reasoningProcess": "思考过程", - "chat.reasoningThinking": "思考中…", - "chat.question": "问题", - "chat.system": "系统", - "install.title": "安装工具", - "install.approve": "安装", - "install.reject": "取消", - "install.running": "正在安装...", - "install.failed": "安装失败。", - "settings.title": "设置", - "settings.interface": "界面", - "settings.tabLanguage": "语言", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "权限", - "settings.language": "语言", - "settings.webSearchDefault": "默认启用智能搜索", - "settings.voiceTitle": "语音输入", - "settings.voiceProvider": "模型", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "已就绪", - "settings.voiceMissing": "未安装", - "settings.voiceInstallHint": "模型和 runtime 不随插件打包。请单独安装 ai-free-stt,或设置 AI_FREE_STT_BIN。", - "settings.languageSaved": "语言已保存。正在重新加载界面...", - "settings.loadFailed": "无法加载设置:{message}", - "settings.low": "低风险", - "settings.medium": "中等风险", - "settings.high": "高风险", - "settings.apiTitle": "OpenAI 兼容 API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "在 OpenAI 兼容客户端中,填写 Base URL 和对应提供商的 Bearer API key。模型:{models}", - "settings.anthropicApiTitle": "Anthropic 兼容 API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "认证 header", - "settings.anthropicNote": "在 Anthropic 兼容客户端中,使用不带 /v1 的 Base URL 和同一个提供商 API key。支持 POST /v1/messages。模型:{models}", - "settings.noKey": "尚未创建密钥", - "settings.keyCreated": "密钥已创建", - "settings.createKey": "创建", - "settings.keyReady": "{label} API key 已就绪", - "settings.keyCreateFailed": "无法创建 {label} API key:{message}", - "settings.saveFailed": "保存失败:{message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "深色", - "theme.light": "浅色", - "theme.contrast": "高对比", - "theme.title": "主题:{label}", - "shutdown.title": "CLI 已停止", - "shutdown.sub": "服务器不再响应。窗口将自动关闭。", - "shutdown.gracefulTitle": "正在停止 ai-free…", - "shutdown.stoppingTasks": "正在停止后台任务…", - "shutdown.closingBrowsers": "正在关闭 Chrome(ChatGPT / Qwen)…", - "shutdown.closingServer": "正在停止服务器…", - "shutdown.stopped": "已停止", - "shutdown.stoppedSub": "窗口将自动关闭。", - "welcome.title": "欢迎使用 AI Free", - "welcome.chooseProviders": "选择要连接的 AI 提供商。", - "welcome.multi": "可选择一个或多个。之后可在设置中继续添加。", - "welcome.prompt1": "输入用逗号分隔的编号(例如 \"1\" 或 \"1,2\"),", - "welcome.prompt2": "或按 Enter 默认使用 DeepSeek:", - "welcome.invalid": "⚠️ 无法理解选择。默认使用 DeepSeek。", - "welcome.connecting": "正在连接:{providers}", - "welcome.loginFailed": "❌ 无法连接 {provider}:{message}", - "welcome.retryLater": "你可以稍后在聊天窗口的设置中重试。", - "welcome.done": "✅ 完成。正在启动聊天窗口...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/i18n/languages/zh.mjs"; diff --git a/plugin-for-vscode/src/memory/markdown.mjs b/plugin-for-vscode/src/memory/markdown.mjs index f634d40..da65762 100644 --- a/plugin-for-vscode/src/memory/markdown.mjs +++ b/plugin-for-vscode/src/memory/markdown.mjs @@ -1,95 +1,2 @@ -// Markdown vault — человекочитаемые заметки с YAML frontmatter. - -import fs from "node:fs"; -import path from "node:path"; -import { MEMORY_VAULT } from "./paths.mjs"; - -export function serializeFrontmatter(fields = {}) { - const lines = []; - for (const [key, value] of Object.entries(fields)) { - if (value === undefined || value === null) continue; - if (Array.isArray(value)) { - lines.push(`${key}: [${value.map((v) => JSON.stringify(String(v))).join(", ")}]`); - continue; - } - if (typeof value === "object") { - lines.push(`${key}: ${JSON.stringify(value)}`); - continue; - } - lines.push(`${key}: ${String(value)}`); - } - return `${lines.join("\n")}\n`; -} - -export function parseFrontmatter(text) { - const raw = String(text || ""); - const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/); - if (!match) { - return { meta: {}, content: raw.trim() }; - } - - const meta = {}; - for (const line of match[1].split("\n")) { - const idx = line.indexOf(":"); - if (idx <= 0) continue; - const key = line.slice(0, idx).trim(); - let value = line.slice(idx + 1).trim(); - if (value.startsWith("[") && value.endsWith("]")) { - try { - meta[key] = JSON.parse(value.replace(/'/g, '"')); - } catch { - meta[key] = value.slice(1, -1).split(",").map((v) => v.trim().replace(/^"|"$/g, "")); - } - continue; - } - if ((value.startsWith("{") && value.endsWith("}")) || (value.startsWith("[") && value.endsWith("]"))) { - try { meta[key] = JSON.parse(value); continue; } catch {} - } - meta[key] = value; - } - - return { meta, content: match[2].trim() }; -} - -export function writeMemoryMarkdown(item) { - if (!item?.id) return null; - fs.mkdirSync(MEMORY_VAULT, { recursive: true }); - const filePath = path.join(MEMORY_VAULT, `${item.id}.md`); - const frontmatter = serializeFrontmatter({ - id: item.id, - type: item.type, - tags: item.tags || [], - workspace: item.workspace || "", - createdAt: item.createdAt, - updatedAt: item.updatedAt, - }); - fs.writeFileSync(filePath, `---\n${frontmatter}---\n\n${item.content || ""}\n`, "utf8"); - return filePath; -} - -export function readMemoryMarkdown(id) { - const filePath = path.join(MEMORY_VAULT, `${id}.md`); - if (!fs.existsSync(filePath)) return null; - const parsed = parseFrontmatter(fs.readFileSync(filePath, "utf8")); - return normalizeVaultItem(parsed.meta, parsed.content); -} - -export function deleteMemoryMarkdown(id) { - const filePath = path.join(MEMORY_VAULT, `${id}.md`); - if (!fs.existsSync(filePath)) return false; - fs.unlinkSync(filePath); - return true; -} - -function normalizeVaultItem(meta, content) { - return { - id: String(meta.id || ""), - type: String(meta.type || "note"), - content: String(content || ""), - tags: Array.isArray(meta.tags) ? meta.tags : [], - workspace: String(meta.workspace || ""), - meta: {}, - createdAt: String(meta.createdAt || new Date().toISOString()), - updatedAt: String(meta.updatedAt || meta.createdAt || new Date().toISOString()), - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/memory/markdown.mjs"; diff --git a/plugin-for-vscode/src/memory/paths.mjs b/plugin-for-vscode/src/memory/paths.mjs index 4f93e16..4732937 100644 --- a/plugin-for-vscode/src/memory/paths.mjs +++ b/plugin-for-vscode/src/memory/paths.mjs @@ -1,19 +1,2 @@ -// Пути хранилища памяти (~/.ai-free/memory/). - -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; - -export const MEMORY_BASE = process.env.AI_FREE_MEMORY_DIR - ? path.resolve(process.env.AI_FREE_MEMORY_DIR) - : path.join(os.homedir(), ".ai-free", "memory"); - -export const MEMORY_DB = path.join(MEMORY_BASE, "memory.db"); -export const MEMORY_VAULT = path.join(MEMORY_BASE, "vault"); -export const LEGACY_INDEX = path.join(MEMORY_BASE, "index.json"); -export const MIGRATION_FLAG = path.join(MEMORY_BASE, ".migrated-v2.json"); - -export function ensureMemoryDirs() { - fs.mkdirSync(MEMORY_BASE, { recursive: true }); - fs.mkdirSync(MEMORY_VAULT, { recursive: true }); -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/memory/paths.mjs"; diff --git a/plugin-for-vscode/src/memory/search/fts-query.mjs b/plugin-for-vscode/src/memory/search/fts-query.mjs index 79307db..6df97ca 100644 --- a/plugin-for-vscode/src/memory/search/fts-query.mjs +++ b/plugin-for-vscode/src/memory/search/fts-query.mjs @@ -1,33 +1,2 @@ -// FTS query builder для SQLite FTS5. - -export function buildFtsMatchQuery(query = "") { - const tokens = String(query || "") - .trim() - .split(/\s+/) - .filter(Boolean) - .map((token) => token.replace(/["*]/g, "").trim()) - .filter(Boolean); - - if (!tokens.length) return ""; - - return tokens.map((token) => `"${token.replace(/"/g, '""')}"`).join(" OR "); -} - -export function rankFtsResults(rows, query = "") { - const q = String(query || "").toLowerCase(); - if (!q) return rows; - - return [...rows].sort((a, b) => scoreItem(b, q) - scoreItem(a, q)); -} - -function scoreItem(item, query) { - const content = String(item.content || "").toLowerCase(); - let score = 0; - if (content.includes(query)) score += 4; - for (const token of query.split(/\s+/).filter(Boolean)) { - if (content.includes(token)) score += 1; - if (item.type?.toLowerCase() === token) score += 2; - if (item.tags?.some((tag) => String(tag).toLowerCase() === token)) score += 2; - } - return score; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../../packages/core/src/memory/search/fts-query.mjs"; diff --git a/plugin-for-vscode/src/providers/model-catalog.mjs b/plugin-for-vscode/src/providers/model-catalog.mjs index d2d4d53..2416b2c 100644 --- a/plugin-for-vscode/src/providers/model-catalog.mjs +++ b/plugin-for-vscode/src/providers/model-catalog.mjs @@ -1,189 +1,2 @@ -// Единый каталог моделей для desktop и расширения VS Code. -// Здесь храним и OpenAI-compatible id, и UI-метаданные, чтобы API, ACP и webview -// не расходились между собой после очередного обновления списка моделей. - -export const PROVIDER_CATALOG = { - deepseek: { - id: "deepseek", - label: "DeepSeek", - icon: "DS", - sub: "chat.deepseek.com", - defaultMode: "fast", - defaultModel: "deepseek-v4-flash", - modes: [ - { - id: "fast", - title: "DeepSeek v4 Flash", - sub: "быстрый обычный чат", - model: "deepseek-v4-flash", - }, - { - id: "expert", - title: "DeepSeek v4 Pro", - sub: "reasoning / R1", - model: "deepseek-v4-pro", - reasoning: true, - }, - { - id: "vision", - title: "DeepSeek v4 Vision", - sub: "распознавание изображений", - model: "deepseek-v4-vision", - vision: true, - }, - ], - models: [ - { id: "deepseek-v4-flash", label: "DeepSeek v4 Flash", apiModel: null }, - { id: "deepseek-v4-pro", label: "DeepSeek v4 Pro", apiModel: "expert", reasoning: true }, - { id: "deepseek-v4-vision", label: "DeepSeek v4 Vision", apiModel: "vision", vision: true }, - { id: "deepseek-chat", label: "DeepSeek Chat", apiModel: null, legacy: true }, - { id: "deepseek-reasoner", label: "DeepSeek Reasoner", apiModel: "expert", reasoning: true, legacy: true }, - ], - }, - qwen: { - id: "qwen", - label: "Qwen", - icon: "QW", - sub: "chat.qwen.ai", - defaultMode: "default", - defaultModel: "qwen3.7-plus", - modes: [ - { - id: "default", - title: "Qwen Chat", - sub: "выбор модели в шапке чата", - model: "qwen3.7-plus", - }, - ], - models: [ - { id: "qwen3.8-max", label: "Qwen3.8 Max", sub: "актуальная флагманская модель", reasoning: true, vision: true, search: true }, - { id: "qwen3.7-plus", label: "Qwen3.7 Plus", sub: "default, актуальный web-default" }, - { id: "qwen3.7-max", label: "Qwen3.7 MAX", sub: "мощнее, может требовать доступ" }, - { id: "qwen-latest-series-invite-beta-v24", label: "Qwen3.7 Max Preview", sub: "актуальный preview max" }, - { id: "qwen-latest-series-invite-beta-v16", label: "Qwen3.7 Plus Preview", sub: "актуальный preview plus" }, - { id: "qwen3.6-plus", label: "Qwen3.6 Plus", sub: "стабильный быстрый чат" }, - { id: "qwen3.6-max-preview", label: "Qwen3.6 Max Preview", sub: "предыдущий preview max" }, - { id: "qwen3.6-27b", label: "Qwen3.6 27B", sub: "быстрая средняя модель" }, - { id: "qwen3.6-35b-a3b", label: "Qwen3.6 35B A3B", sub: "MoE-модель" }, - { id: "qwen3.5-plus", label: "Qwen3.5 Plus", sub: "стабильный fallback" }, - { id: "qwen3.5-27b", label: "Qwen3.5 27B", sub: "стабильный fallback" }, - { id: "qwen3.5-35b-a3b", label: "Qwen3.5 35B A3B", sub: "стабильный fallback MoE" }, - { id: "qwen3-max-2026-01-23", label: "Qwen3 Max", sub: "актуальный Qwen3 Max" }, - { id: "qwen3-coder-plus", label: "Qwen3 Coder", sub: "coding model" }, - ], - }, - chatgpt: { - id: "chatgpt", - label: "ChatGPT", - icon: "GP", - sub: "chatgpt.com", - defaultMode: "default", - defaultModel: "gpt-5.5-instant", - modes: [ - { - id: "default", - title: "ChatGPT Web", - sub: "модели chatgpt.com сессии", - model: "gpt-5.5-instant", - }, - ], - models: [ - { id: "gpt-5.5-instant", label: "GPT-5.5 Instant", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "Мгновенный", "ChatGPT", "Auto", "Авто", "Default", "GPT-4o", "GPT-4o mini"] }, - { id: "gpt-5.6-sol-medium", label: "GPT-5.6 Sol · Medium", apiModel: "gpt-5.6-sol-medium", webLabels: ["Medium", "Средний", "Thinking", "Reasoning", "Рассуждения"], reasoning: true }, - { id: "gpt-5.6-sol-high", label: "GPT-5.6 Sol · High", apiModel: "gpt-5.6-sol-high", webLabels: ["High", "Высокий"], reasoning: true }, - { id: "gpt-5.6-sol-extra-high", label: "GPT-5.6 Sol · Extra High", apiModel: "gpt-5.6-sol-extra-high", webLabels: ["Extra High", "Очень высокий"], reasoning: true }, - { id: "gpt-5.6-sol-pro-standard", label: "GPT-5.6 Sol Pro · Standard", apiModel: "gpt-5.6-sol-pro-standard", webLabels: ["Pro Standard", "Pro стандартный", "Pro"], reasoning: true }, - { id: "gpt-5.6-sol-pro-extended", label: "GPT-5.6 Sol Pro · Extended", apiModel: "gpt-5.6-sol-pro-extended", webLabels: ["Pro Extended", "Pro расширенный"], reasoning: true }, - { id: "gpt-5.5", label: "GPT-5.5", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "ChatGPT", "GPT-4o", "Default"], legacy: true }, - { id: "gpt-4o", label: "GPT-4o", apiModel: "gpt-4o", webLabels: ["GPT-4o", "4o", "ChatGPT"], legacy: true }, - { id: "gpt-4o-mini", label: "GPT-4o mini", apiModel: "gpt-4o-mini", webLabels: ["GPT-4o mini", "4o mini", "ChatGPT"], legacy: true }, - { id: "o1-mini", label: "o1 mini", apiModel: "o1-mini", webLabels: ["o1-mini", "o1 mini", "o1"], reasoning: true, legacy: true }, - { id: "o3-mini", label: "o3 mini", apiModel: "o3-mini", webLabels: ["o3-mini", "o3 mini", "o3"], reasoning: true, legacy: true }, - ], - }, -}; - -export const OPENAI_COMPAT_MODELS = Object.values(PROVIDER_CATALOG).flatMap((provider) => - provider.models.map((model) => ({ - name: model.id, - provider: provider.id, - model: model.apiModel === undefined ? model.id : model.apiModel, - label: model.label, - reasoning: model.reasoning === true, - vision: model.vision === true, - legacy: model.legacy === true, - })), -); - -export function getProviderCatalog(providerId) { - return PROVIDER_CATALOG[providerId] || null; -} - -export function getProviderIds() { - return Object.keys(PROVIDER_CATALOG); -} - -export function getProviderDefaultModel(providerId, modeId = null) { - const provider = getProviderCatalog(providerId); - if (!provider) return null; - if (modeId) { - const mode = provider.modes.find((item) => item.id === modeId); - if (mode?.model) return mode.model; - } - return provider.defaultModel || provider.models[0]?.id || null; -} - -export function findProviderModel(providerId, modelId) { - const provider = getProviderCatalog(providerId); - if (!provider) return null; - return provider.models.find((model) => model.id === modelId) || null; -} - -export function findModel(name) { - return OPENAI_COMPAT_MODELS.find((model) => model.name === name); -} - -export function modelsList(overrides = {}) { - const models = Object.entries(PROVIDER_CATALOG).flatMap(([providerId, provider]) => { - const providerModels = overrides[providerId]?.models || provider.models; - return providerModels.map((model) => ({ - name: model.id, - provider: providerId, - })); - }); - return { - object: "list", - data: models.map((model) => ({ - id: model.name, - object: "model", - created: 1700000000, - owned_by: model.provider, - })), - }; -} - -export function uiModelCatalog(overrides = {}) { - return { - providers: Object.fromEntries( - Object.entries(PROVIDER_CATALOG).map(([providerId, provider]) => [ - providerId, - (() => { - const override = overrides[providerId] || {}; - const modes = override.modes || provider.modes; - const models = override.models || provider.models; - return { - label: provider.label, - icon: provider.icon, - sub: provider.sub, - defaultMode: provider.defaultMode, - defaultModel: override.defaultModel || provider.defaultModel, - modes: modes.map((mode) => ({ ...mode })), - models: models - .filter((model) => model.legacy !== true) - .map((model) => ({ ...model })), - }; - })(), - ]), - ), - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/providers/model-catalog.mjs"; diff --git a/scripts/check-ci-invariants.mjs b/scripts/check-ci-invariants.mjs index 9007f0f..6ff2dfd 100644 --- a/scripts/check-ci-invariants.mjs +++ b/scripts/check-ci-invariants.mjs @@ -57,11 +57,12 @@ check("desktop, VS Code and JetBrains package versions are synchronized", () => assert.equal(json("package.json").version, jetbrainsVersion, "desktop and JetBrains versions differ"); }); -check("desktop and VS Code model catalogs are synchronized", () => { - assert.equal( - read("plugin-for-vscode/src/providers/model-catalog.mjs"), - read("src/providers/model-catalog.mjs"), - ); +check("desktop, VS Code and shared core model catalogs are synchronized", async () => { + const { PROVIDER_CATALOG: desktop } = await import("../src/providers/model-catalog.mjs"); + const { PROVIDER_CATALOG: plugin } = await import("../plugin-for-vscode/src/providers/model-catalog.mjs"); + const { PROVIDER_CATALOG: core } = await import("../packages/core/src/providers/model-catalog.mjs"); + assert.deepEqual(desktop, core, "desktop catalog differs from core"); + assert.deepEqual(plugin, core, "plugin catalog differs from core"); }); check("desktop and VS Code diagnostics are synchronized", () => { @@ -157,7 +158,10 @@ check("desktop and VS Code STT and memory runtimes are synchronized", () => { check("desktop and VS Code duplicate module inventory is synchronized", () => { const inventory = assertInventoryInvariants(); assert.equal(inventory.divergent.length, 0, "Divergent modules detected between desktop and VS Code"); - assert.ok(inventory.summary.identicalCount >= 150, "Expected at least 150 tracked identical modules"); + assert.ok( + inventory.summary.identicalCount + inventory.summary.coreSharedCount >= 150, + "Expected at least 150 tracked identical or core-shared modules", + ); }); check("Git does not track generated VSIX or operating-system metadata", () => { diff --git a/scripts/inventory-duplicates.mjs b/scripts/inventory-duplicates.mjs index e32acee..433faba 100644 --- a/scripts/inventory-duplicates.mjs +++ b/scripts/inventory-duplicates.mjs @@ -66,6 +66,17 @@ function scanFiles(baseDir) { return result; } +function isCoreReExport(filePath) { + try { + const full = path.join(root, filePath); + if (!fs.existsSync(full)) return false; + const content = fs.readFileSync(full, "utf8"); + return content.includes("packages/core/") || content.includes("@ai-free/core"); + } catch { + return false; + } +} + export function getDuplicateInventory() { const pairs = [ { name: "src", desktop: "src", vscode: "plugin-for-vscode/src" }, @@ -73,6 +84,7 @@ export function getDuplicateInventory() { ]; const identical = []; + const coreShared = []; const platformSpecific = []; const divergent = []; const desktopOnly = []; @@ -98,6 +110,13 @@ export function getDuplicateInventory() { size: d.size, hash: d.hash, }); + } else if (isCoreReExport(desktopRel) && isCoreReExport(vscodeRel)) { + coreShared.push({ + subPath: key, + desktopPath: desktopRel, + vscodePath: vscodeRel, + corePath: `packages/core/src/${key}`, + }); } else if (KNOWN_PLATFORM_SPECIFIC.has(desktopRel)) { platformSpecific.push({ subPath: key, @@ -148,12 +167,14 @@ export function getDuplicateInventory() { return { identical, + coreShared, platformSpecific, desktopOnly, vscodeOnly, divergent, summary: { identicalCount: identical.length, + coreSharedCount: coreShared.length, platformSpecificCount: platformSpecific.length, desktopOnlyCount: desktopOnly.length, vscodeOnlyCount: vscodeOnly.length, @@ -170,18 +191,25 @@ export function formatInventoryReport(inventory = getDuplicateInventory()) { "", `Дата формирования: ${new Date().toISOString().split("T")[0]}`, "", - "## Сводка", - "", + `- **Вынесено в @ai-free/core (Unified Shared Core):** ${inventory.summary.coreSharedCount} файлов`, `- **Полностью идентичные модули:** ${inventory.summary.identicalCount} файлов (${inventory.summary.totalDuplicateKilobytes} KB)`, `- **Платформенно-специфичные модули:** ${inventory.summary.platformSpecificCount} файла`, `- **Модули только для Desktop:** ${inventory.summary.desktopOnlyCount} файла`, `- **Модули только для VS Code:** ${inventory.summary.vscodeOnlyCount} файл`, `- **Случайно разошедшиеся модули (Divergent):** ${inventory.summary.divergentCount} файлов`, "", - "## Платформенно-специфичные модули (Намеренные различия)", + "## Модули общего ядра (@ai-free/core)", "", ]; + for (const item of inventory.coreShared) { + lines.push(`- \`${item.corePath}\` (re-exported in Desktop and VS Code)`); + } + lines.push(""); + + lines.push("## Платформенно-специфичные модули (Намеренные различия)"); + lines.push(""); + for (const item of inventory.platformSpecific) { lines.push(`### \`${item.desktopPath}\``); lines.push(`- **Причина:** ${item.reason}`); diff --git a/src/code-agent/parser.mjs b/src/code-agent/parser.mjs index eb8012d..2e87e6b 100644 --- a/src/code-agent/parser.mjs +++ b/src/code-agent/parser.mjs @@ -1,143 +1,2 @@ -// Парсер JSON-tool-call'а из ответа LLM. -// Устойчив к markdown-блокам, тексту до/после JSON, нескольким JSON-объектам. -// -// 3 стратегии последовательно: -// 1. Пройтись по всем fenced-блокам ```...``` (любой язык: json, python, tool_calls), -// искать tool в содержимом каждого. -// 2. Вырезать ВСЕ fenced-блоки (они часто содержат пояснения на python и т.п.) -// и искать tool в остатке. Спасает Qwen-кейс: ```python ...``` + текст + -// {"tool":"write_file",...} снаружи блока. -// 3. Fallback — искать в исходном тексте целиком. - -export function parseToolCall(text) { - const trimmed = String(text || "").trim(); - - const xmlResult = findXmlToolCall(trimmed); - if (xmlResult) return xmlResult; - - const fencedBlocks = [ - ...trimmed.matchAll(/```[a-zA-Z0-9]*\n?([\s\S]*?)```/gi), - ]; - for (const match of fencedBlocks) { - const result = findToolCallInText(match[1].trim()); - if (result) return result; - } - - const stripped = trimmed.replace(/```[a-zA-Z0-9]*\n?[\s\S]*?```/gi, " "); - const result2 = findToolCallInText(stripped); - if (result2) return result2; - - return findToolCallInText(trimmed); -} - -function findXmlToolCall(text) { - const match = text.match(/([\s\S]*?)<\/tool_call>/i); - if (!match) return null; - - const tool = match[2]; - const rawBody = match[3].trim(); - if (!rawBody) return { tool }; - - try { - const parsed = JSON.parse(rawBody); - if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { - return { tool, ...parsed }; - } - } catch { - // Fall through to JSON extraction below. - } - - const json = extractFirstJsonObject(rawBody); - if (!json) return { tool }; - try { - const parsed = JSON.parse(json); - if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { - return { tool, ...parsed }; - } - } catch { - // ignore - } - return { tool }; -} - -// Ищет первый JSON-объект с полем "tool" (string) в тексте. -// Если первый {...} не tool-call — пропускает и берёт следующий. -function findToolCallInText(text) { - let offset = 0; - - while (offset < text.length) { - const start = text.indexOf("{", offset); - if (start < 0) return null; - - const candidate = extractFirstJsonObject(text.slice(start)); - if (!candidate) { - return null; - } - - try { - const parsed = normalizeToolCall(JSON.parse(candidate)); - if (parsed) return parsed; - } catch { - // Невалидный JSON — пробуем следующий объект. - } - - offset = start + Math.max(candidate.length, 1); - } - - return null; -} - -function normalizeToolCall(parsed) { - if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null; - if (typeof parsed.tool === "string") return parsed; - - // Some models emit ACP-ish or malformed tool JSON, for example: - // {"":"write_file","path":"x","content":""} - // {"name":"write_file","arguments":{"path":"x","content":""}} - const emptyKeyTool = parsed[""]; - if (typeof emptyKeyTool === "string") { - const { [""]: _ignored, ...rest } = parsed; - return { tool: emptyKeyTool, ...rest }; - } - - if (typeof parsed.name === "string" && parsed.arguments && typeof parsed.arguments === "object") { - return { tool: parsed.name, ...parsed.arguments }; - } - - return null; -} - -// Безопасный экстрактор первого валидного JSON-объекта из текста. -// Уважает строки и эскейпы, не путается на скобках внутри значений. -export function extractFirstJsonObject(text) { - const start = text.indexOf("{"); - if (start < 0) return null; - - let depth = 0; - let inString = false; - let escaped = false; - - for (let index = start; index < text.length; index += 1) { - const char = text[index]; - - if (inString) { - if (escaped) { - escaped = false; - } else if (char === "\\") { - escaped = true; - } else if (char === '"') { - inString = false; - } - continue; - } - - if (char === '"') inString = true; - else if (char === "{") depth += 1; - else if (char === "}") { - depth -= 1; - if (depth === 0) return text.slice(start, index + 1); - } - } - - return null; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../packages/core/src/code-agent/parser.mjs"; diff --git a/src/i18n/index.mjs b/src/i18n/index.mjs index 51dd6e9..441c414 100644 --- a/src/i18n/index.mjs +++ b/src/i18n/index.mjs @@ -1,94 +1,2 @@ -import { language as ru } from "./languages/ru.mjs"; -import { language as en } from "./languages/en.mjs"; -import { language as es } from "./languages/es.mjs"; -import { language as pt } from "./languages/pt.mjs"; -import { language as fr } from "./languages/fr.mjs"; -import { language as de } from "./languages/de.mjs"; -import { language as zh } from "./languages/zh.mjs"; -import { language as hi } from "./languages/hi.mjs"; -import { language as ar } from "./languages/ar.mjs"; - -export const DEFAULT_LANGUAGE = "ru"; - -export const LANGUAGES = Object.freeze({ - ru, - en, - es, - pt, - fr, - de, - zh, - hi, - ar, -}); - -const ALIASES = Object.freeze({ - "pt-br": "pt", - "pt-pt": "pt", - "zh-cn": "zh", - "zh-hans": "zh", - "zh-tw": "zh", - "zh-hant": "zh", -}); - -export function normalizeLanguage(value) { - const raw = String(value || "") - .trim() - .replace(/\..*$/, "") - .replace(/_/g, "-") - .toLowerCase(); - if (!raw) return DEFAULT_LANGUAGE; - const exact = ALIASES[raw] || raw; - if (LANGUAGES[exact]) return exact; - const short = exact.split("-")[0]; - return LANGUAGES[short] ? short : DEFAULT_LANGUAGE; -} - -export function resolveUserLanguage(explicitLanguage = "") { - return normalizeLanguage( - explicitLanguage - || process.env.AI_FREE_LANG - || process.env.LC_ALL - || process.env.LC_MESSAGES - || process.env.LANG - || DEFAULT_LANGUAGE, - ); -} - -export function getLanguageMeta(languageCode = DEFAULT_LANGUAGE) { - const language = LANGUAGES[normalizeLanguage(languageCode)] || LANGUAGES[DEFAULT_LANGUAGE]; - return { - code: language.code, - name: language.name, - dir: language.dir || "ltr", - }; -} - -export function getMessages(languageCode = DEFAULT_LANGUAGE) { - const code = normalizeLanguage(languageCode); - const base = code === DEFAULT_LANGUAGE - ? LANGUAGES[DEFAULT_LANGUAGE].messages - : LANGUAGES.en.messages; - return { - ...base, - ...(LANGUAGES[code]?.messages || {}), - }; -} - -export function formatMessage(template, vars = {}) { - return String(template || "").replace(/\{([a-zA-Z0-9_]+)\}/g, (match, key) => ( - Object.prototype.hasOwnProperty.call(vars, key) ? String(vars[key]) : match - )); -} - -export function createTranslator(languageCode = DEFAULT_LANGUAGE) { - const language = getLanguageMeta(languageCode); - const messages = getMessages(language.code); - return { - language, - messages, - t(key, vars = {}) { - return formatMessage(messages[key] || key, vars); - }, - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../packages/core/src/i18n/index.mjs"; diff --git a/src/i18n/languages/ar.mjs b/src/i18n/languages/ar.mjs index 6bba4bb..89454c8 100644 --- a/src/i18n/languages/ar.mjs +++ b/src/i18n/languages/ar.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "ar", - name: "العربية", - dir: "rtl", - messages: { - "app.workspace": "مساحة العمل", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "تحديث", - "app.newChat": "+ محادثة جديدة", - "app.noChat": "لم يتم اختيار محادثة", - "app.createChatHint": "أنشئ محادثة من اليسار. يمكن أن تكون كل محادثة مشروعا أو سياق عمل منفصلا.", - "app.firstMessage": "اكتب أول رسالة لهذا المشروع.", - "app.close": "إغلاق", - "app.loading": "جار التحميل...", - "app.loadingShort": "جارٍ التحميل...", - "app.error": "خطأ: {message}", - "app.requestFailed": "فشل الطلب", - "app.resizeChats": "تغيير عرض قائمة المحادثات", - "app.resizeComposer": "تغيير ارتفاع منطقة الإدخال", - "newChat.title": "محادثة جديدة", - "newChat.provider": "المزوّد", - "newChat.mode": "الوضع (النموذج)", - "newChat.modeHint": "يتم تثبيت الوضع عند إنشاء المحادثة. للتبديل لاحقًا، أنشئ محادثة جديدة بالوضع المطلوب.", - "newChat.chatTitle": "عنوان المحادثة (اختياري)", - "newChat.chatTitlePlaceholder": "مثال: إعادة تنظيم auth", - "newChat.workspace": "مجلد المشروع", - "newChat.workspacePlaceholder": "/Users/.../project أو ~/Projects/new-thing", - "newChat.browse": "📁 تصفح", - "newChat.up": "↑ للأعلى", - "newChat.home": "🏠 الرئيسية", - "newChat.newFolder": "➕ مجلد جديد", - "newChat.hidden": "مخفي", - "newChat.pickFolder": "اختر هذا المجلد", - "newChat.newFolderPlaceholder": "اسم المجلد الجديد", - "newChat.create": "إنشاء", - "newChat.cancel": "إلغاء", - "newChat.createFolder": "إنشاء المجلد إذا لم يكن موجودًا (فقط داخل $HOME الخاص بك)", - "newChat.submit": "إنشاء محادثة", - "newChat.emptyFolderName": "أدخل اسمًا.", - "newChat.defaultProject": "افتراضي", - "newChat.truncated": "لا تظهر كل المجلدات. فعّل \"المخفية\" أو افتح المجلد الأعلى.", - "newChat.folderCount": "المجلدات: {total}{suffix}", - "newChat.hiddenSuffix": " (مجلدات . مخفية - مربع \"المخفية\")", - "newChat.folderShown": "يتم عرض {shown} من {total} مجلدات", - "newChat.tooManyFolders": "(مجلدات كثيرة جدًا - ضيّق المسار أو فعّل \"المخفية\")", - "newChat.noSubfolders": "(لا توجد مجلدات فرعية - يمكنك اختيار هذا المجلد بزر \"اختيار\")", - "newChat.truncatedInline": "يتم عرض أول {shown} من {total}. ضيّق المسار أو فعّل \"المخفية\".", - "newChat.creating": "جارٍ إنشاء المحادثة...", - "provider.connected": "✓ متصل", - "provider.connectedTitle": "أنت مسجل الدخول. انقر لاستخدام حساب آخر", - "provider.authorize": "🔑 تسجيل الدخول", - "provider.authorizeTitle": "تسجيل الدخول مطلوب. انقر لتسجيل الدخول", - "provider.connectConfirm": "هل تريد توصيل {label}؟\n\nستفتح نافذة متصفح. سجّل الدخول في الموقع؛ ستُغلق النافذة بعد ذلك.", - "provider.chatgptConnectConfirm": "هل تريد توصيل {label}؟\n\nستُفتح نافذة Chrome عادية مرة واحدة لتسجيل دخول موثوق. ستُغلق تلقائياً بعد التحقق من الجلسة النشطة، ثم سيواصل ChatGPT العمل داخل AI Free.", - "provider.chatgptEmbedLogin": "أكمل تسجيل الدخول في نافذة Chrome. لن تُغلق تلقائياً إلا بعد التحقق من الجلسة النشطة.", - "provider.chatgptEmbedLoginTimeout": "انتهت مهلة تسجيل الدخول إلى {label}. اضغط «تسجيل الدخول عبر Chrome» وحاول مرة أخرى.", - "provider.connectedAlert": "تم توصيل {label}.", - "provider.tokenMissing": "اكتمل تسجيل الدخول، لكن لم يتم العثور على token. حاول مرة أخرى أو شغّل: npm run login-{id}", - "provider.connectFailed": "تعذر توصيل {label}: {message}", - "provider.deepseekFast": "محادثة عادية سريعة", - "provider.deepseekExpert": "استدلال / R1", - "provider.deepseekVision": "تعرف على الصور", - "provider.qwenDefault": "اختر النموذج من رأس المحادثة", - "role.assistantDescription": "مساعد عادي", - "role.assistant": "المساعد", - "role.assistant.label": "المساعد", - "role.assistant.description": "مساعد عادي للمحادثة والإجابات السريعة.", - "role.prompt_builder.label": "منشئ المطالبات", - "role.prompt_builder.description": "يوضح المهمة ويحوّلها إلى prompt عملي للخطوات التالية.", - "role.architect.label": "المعماري", - "role.architect.description": "يصمم الحل وحدود الوحدات والبيانات والمخاطر.", - "role.developer.label": "المطور", - "role.developer.description": "يقترح التنفيذ والملفات والخطوات والتفاصيل التقنية.", - "role.tester.label": "المختبر", - "role.tester.description": "يبحث عن الفحوصات والحالات الحدية والانحدارات وسيناريوهات الاختبار.", - "role.reviewer.label": "المراجع", - "role.reviewer.description": "يفحص الخطة/النتيجة نقديًا ويبحث عن نقاط الضعف.", - "role.synthesizer.label": "المُلخّص", - "role.synthesizer.description": "يجمع مخرجات pipeline في ملخص قصير وخطوات تالية.", - "topbar.model": "النموذج", - "topbar.role": "دور هذه المحادثة في pipeline", - "topbar.coderTitle": "تفعيل وضع الوكيل: يمكن للنموذج إنشاء الملفات وتعديلها", - "topbar.coder": "🛠 المبرمج", - "topbar.coderOn": "🛠 المبرمج ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "التدفق", - "topbar.pipelineOn": "التدفق ON", - "topbar.hardwareTitle": "ESP / firmware للوحات: يفعّل ملف وكيل العتاد", - "topbar.pipelineTitle": "تمرير الرسائل عبر روابط pipeline", - "topbar.flow": "التدفق", - "topbar.flowTitle": "تدفق pipeline", - "topbar.theme": "تغيير السمة", - "topbar.settings": "الإعدادات / الأوامر المسموحة", - "topbar.quit": "خروج — إيقاف التطبيق وإغلاق Chrome", - "pipeline.title": "تدفق pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "عيّن دورًا لكل محادثة واختر الخطوة التالية.", - "pipeline.empty": "أنشئ عدة محادثات ثم اربطها هنا.", - "pipeline.end": "النهاية", - "pipeline.user": "المستخدم", - "pipeline.model": "النموذج", - "composer.chooseChat": "اختر محادثة من اليسار...", - "composer.message": "رسالة إلى {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ تفكير عميق", - "composer.thinkingTitle": "تفكير عميق: يعرض النموذج سلسلة التفكير", - "composer.thinkingRequired": "التفكير العميق مطلوب لهذا النموذج", - "composer.search": "🌐 بحث ذكي", - "composer.searchTitle": "بحث ذكي: يستخدم النموذج بحث الويب للمعلومات الحديثة", - "composer.attach": "📎 ملف", - "composer.attachTitle": "إرفاق ملف نصي للقراءة", - "composer.voice": "🎙 صوت", - "composer.voiceTitle": "تسجيل الصوت وإدراج التفريغ في الرسالة", - "composer.voiceStop": "■ إيقاف", - "composer.stop": "■", - "composer.stopTitle": "إيقاف التنفيذ", - "composer.voiceInstalling": "جارٍ تثبيت Parakeet V3. قد يستغرق ذلك بضع دقائق...", - "composer.voiceRecording": "جارٍ تسجيل الصوت...", - "composer.voiceTranscribing": "جارٍ تفريغ الصوت...", - "composer.voiceMissing": "مساعد الصوت غير مثبت. ضع ai-free-stt في {path} أو عيّن AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "نافذة المتصفح هذه لا تدعم تسجيل الميكروفون.", - "composer.voiceNoSpeech": "لم يتم التعرف على كلام.", - "composer.defaultImageQuestion": "ماذا يوجد في هذه الصورة؟ صفها بالتفصيل.", - "composer.imageQuestionLabel": "(سؤال عن الصورة)", - "composer.uploadingImage": "جارٍ رفع ومعالجة الصورة{num}: {name}...", - "composer.thinkingStatus": "جارٍ التفكير...", - "composer.writingStatus": "يكتب الرد…", - "composer.backgroundTask": "⚙️ المهمة تعمل في الخلفية؛ يمكنك الانتقال إلى محادثة أخرى", - "file.svgUnsupported": "SVG (\"{name}\") غير مدعوم للتعرف. احفظه كـ PNG أو JPG.", - "file.imageTooLarge": "الصورة \"{name}\" كبيرة جدًا ({mb} MB). الحد: 10 MB.", - "file.largeImageConfirm": "\"{name}\" بحجم {mb} MB. الملفات الكبيرة غالبًا ترجع CONTENT_EMPTY في DeepSeek.\n\nهل تريد الرفع على أي حال؟", - "file.readFailed": "تعذرت قراءة \"{name}\": {message}", - "file.uploadMissingId": "عاد الرفع بدون fileId", - "file.qwenImageUnsupported": "لا يستطيع AI Free حالياً إرسال الصور عبر ناقل Qwen على الويب. اختر DeepSeek V4 Vision أو ChatGPT لمعالجة الصورة بالكامل.", - "file.binaryUnsupported": "الملف \"{name}\" ثنائي ({ext}). المدعوم حاليًا ملفات النص والصور (PNG/JPG/GIF/WEBP).\n\nPDF ومستندات Office لا تعمل بعد وتحتاج مرحلة منفصلة.", - "file.textTooLarge": "الملف \"{name}\" كبير جدًا ({kb} KB). حد النص: {limitKb} KB.", - "file.looksBinary": "الملف \"{name}\" يبدو ثنائيًا. إذا كان نصًا، أعد تسميته إلى .txt.", - "file.remove": "إزالة", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "أرفقت ملف{plural}. اقرأه وخذه في الاعتبار في إجابتك:", - "file.promptHeader": "الملف: {name} ({kb} KB)", - "file.promptQuestion": "سؤالي:", - "chat.delete": "حذف المحادثة", - "chat.running": "مهمة /code قيد التنفيذ", - "chat.messages": "{count} رسالة", - "chat.deleteConfirm": "حذف المحادثة؟", - "chat.history": "السجل: {file}", - "chat.you": "أنت", - "chat.assistant": "المساعد", - "chat.reasoningProcess": "عملية التفكير", - "chat.reasoningThinking": "يفكر…", - "chat.question": "السؤال", - "chat.system": "النظام", - "install.title": "تثبيت أداة", - "install.approve": "تثبيت", - "install.reject": "إلغاء", - "install.running": "التثبيت جارٍ...", - "install.failed": "فشل التثبيت.", - "settings.title": "الإعدادات", - "settings.interface": "الواجهة", - "settings.tabLanguage": "اللغة", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "الأذونات", - "settings.language": "اللغة", - "settings.webSearchDefault": "تفعيل البحث الذكي افتراضيًا", - "settings.voiceTitle": "إدخال صوتي", - "settings.voiceProvider": "النموذج", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "جاهز", - "settings.voiceMissing": "غير مثبت", - "settings.voiceInstallHint": "النموذج وruntime غير مرفقين مع plugin. ثبّت ai-free-stt بشكل منفصل أو عيّن AI_FREE_STT_BIN.", - "settings.languageSaved": "تم حفظ اللغة. جارٍ إعادة تحميل الواجهة...", - "settings.loadFailed": "تعذر تحميل الإعدادات: {message}", - "settings.low": "خطر منخفض", - "settings.medium": "خطر متوسط", - "settings.high": "خطر عال", - "settings.apiTitle": "API متوافقة مع OpenAI", - "settings.baseUrl": "Base URL", - "settings.apiNote": "في عميل متوافق مع OpenAI، استخدم Base URL ومفتاح Bearer API للمزوّد المطلوب. النماذج: {models}", - "settings.anthropicApiTitle": "API متوافقة مع Anthropic", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "ترويسة المصادقة", - "settings.anthropicNote": "في عميل متوافق مع Anthropic، استخدم Base URL بدون /v1 ونفس مفتاح المزوّد. POST /v1/messages مدعوم. النماذج: {models}", - "settings.noKey": "لم يتم إنشاء المفتاح", - "settings.keyCreated": "تم إنشاء المفتاح", - "settings.createKey": "إنشاء", - "settings.keyReady": "مفتاح API لـ {label} جاهز", - "settings.keyCreateFailed": "تعذر إنشاء مفتاح API لـ {label}: {message}", - "settings.saveFailed": "تعذر الحفظ: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "داكن", - "theme.light": "فاتح", - "theme.contrast": "تباين", - "theme.title": "السمة: {label}", - "shutdown.title": "توقف CLI", - "shutdown.sub": "الخادم لا يستجيب. ستغلق النافذة تلقائيا.", - "shutdown.gracefulTitle": "جارٍ إيقاف ai-free…", - "shutdown.stoppingTasks": "إيقاف المهام في الخلفية…", - "shutdown.closingBrowsers": "إغلاق Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "إيقاف الخادم…", - "shutdown.stopped": "تم الإيقاف", - "shutdown.stoppedSub": "ستغلق النافذة تلقائيا.", - "welcome.title": "مرحبا بك في AI Free", - "welcome.chooseProviders": "اختر مزودي الذكاء الاصطناعي الذين تريد ربطهم.", - "welcome.multi": "اختر واحدًا أو أكثر. يمكنك إضافة المزيد لاحقًا من الإعدادات.", - "welcome.prompt1": "أدخل أرقامًا مفصولة بفواصل (مثل \"1\" أو \"1,2\"),", - "welcome.prompt2": "أو اضغط Enter لاستخدام DeepSeek افتراضيًا:", - "welcome.invalid": "⚠️ تعذر فهم الاختيار. سيتم استخدام DeepSeek افتراضيًا.", - "welcome.connecting": "جارٍ التوصيل: {providers}", - "welcome.loginFailed": "❌ تعذر توصيل {provider}: {message}", - "welcome.retryLater": "يمكنك المحاولة لاحقًا من الإعدادات في نافذة المحادثة.", - "welcome.done": "✅ تم. جار تشغيل نافذة المحادثة...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/ar.mjs"; diff --git a/src/i18n/languages/de.mjs b/src/i18n/languages/de.mjs index cc4edd7..a73847b 100644 --- a/src/i18n/languages/de.mjs +++ b/src/i18n/languages/de.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "de", - name: "Deutsch", - dir: "ltr", - messages: { - "app.workspace": "Arbeitsbereich", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Aktualisieren", - "app.newChat": "+ Neuer Chat", - "app.noChat": "Kein Chat ausgewählt", - "app.createChatHint": "Erstelle links einen Chat. Jeder Chat kann ein eigenes Projekt oder ein eigener Arbeitskontext sein.", - "app.firstMessage": "Schreibe die erste Nachricht für dieses Projekt.", - "app.close": "Schließen", - "app.loading": "Laden...", - "app.loadingShort": "Lade...", - "app.error": "Fehler: {message}", - "app.requestFailed": "Anfrage fehlgeschlagen", - "app.resizeChats": "Chatliste verbreitern/verkleinern", - "app.resizeComposer": "Eingabebereich in der Höhe ändern", - "newChat.title": "Neuer Chat", - "newChat.provider": "Anbieter", - "newChat.mode": "Modus (Modell)", - "newChat.modeHint": "Der Modus wird beim Erstellen des Chats festgelegt. Zum späteren Wechsel einen neuen Chat im gewünschten Modus erstellen.", - "newChat.chatTitle": "Chat-Titel (optional)", - "newChat.chatTitlePlaceholder": "Beispiel: Auth-Refactoring", - "newChat.workspace": "Projektordner", - "newChat.workspacePlaceholder": "/Users/.../project oder ~/Projects/new-thing", - "newChat.browse": "📁 Durchsuchen", - "newChat.up": "↑ Nach oben", - "newChat.home": "🏠 Start", - "newChat.newFolder": "➕ Neuer Ordner", - "newChat.hidden": "Versteckte", - "newChat.pickFolder": "Diesen Ordner auswählen", - "newChat.newFolderPlaceholder": "Name des neuen Ordners", - "newChat.create": "Erstellen", - "newChat.cancel": "Abbrechen", - "newChat.createFolder": "Ordner erstellen, falls er nicht existiert (nur unter Ihrem $HOME)", - "newChat.submit": "Chat erstellen", - "newChat.emptyFolderName": "Geben Sie einen Namen ein.", - "newChat.defaultProject": "Standard", - "newChat.truncated": "Nicht alle Ordner werden angezeigt. Aktivieren Sie \"Versteckt\" oder öffnen Sie den übergeordneten Ordner.", - "newChat.folderCount": "Ordner: {total}{suffix}", - "newChat.hiddenSuffix": " (versteckte .Ordner - Checkbox \"Versteckt\")", - "newChat.folderShown": "Zeige {shown} von {total} Ordnern", - "newChat.tooManyFolders": "(zu viele Ordner - Pfad eingrenzen oder \"Versteckt\" aktivieren)", - "newChat.noSubfolders": "(keine Unterordner - dieser Ordner kann mit \"Auswählen\" gewählt werden)", - "newChat.truncatedInline": "Zeige die ersten {shown} von {total}. Pfad eingrenzen oder \"Versteckt\" aktivieren.", - "newChat.creating": "Chat wird erstellt...", - "provider.connected": "✓ Verbunden", - "provider.connectedTitle": "Sie sind angemeldet. Klicken, um ein anderes Konto zu verwenden", - "provider.authorize": "🔑 Autorisieren", - "provider.authorizeTitle": "Anmeldung erforderlich. Klicken zum Anmelden", - "provider.connectConfirm": "{label} verbinden?\n\nEin Browserfenster wird geöffnet. Melden Sie sich auf der Website an; das Fenster schließt danach.", - "provider.chatgptConnectConfirm": "{label} verbinden?\n\nFür eine zuverlässige Anmeldung wird einmalig ein normales Chrome-Fenster geöffnet. Nach Prüfung der aktiven Sitzung wird es automatisch geschlossen und ChatGPT läuft in AI Free weiter.", - "provider.chatgptEmbedLogin": "Schließen Sie die Anmeldung im Chrome-Fenster ab. Es wird erst nach Prüfung der aktiven Sitzung automatisch geschlossen.", - "provider.chatgptEmbedLoginTimeout": "Zeitüberschreitung bei der Anmeldung bei {label}. Klicken Sie auf „Mit Chrome anmelden“ und versuchen Sie es erneut.", - "provider.connectedAlert": "{label} verbunden.", - "provider.tokenMissing": "Anmeldung abgeschlossen, aber kein Token gefunden. Erneut versuchen oder ausführen: npm run login-{id}", - "provider.connectFailed": "{label} konnte nicht verbunden werden: {message}", - "provider.deepseekFast": "schneller normaler Chat", - "provider.deepseekExpert": "Reasoning / R1", - "provider.deepseekVision": "Bilderkennung", - "provider.qwenDefault": "Modell im Chat-Kopf wählen", - "role.assistantDescription": "Normaler Assistent", - "role.assistant": "Assistent", - "role.assistant.label": "Assistent", - "role.assistant.description": "Normaler Assistent für Chat und schnelle Antworten.", - "role.prompt_builder.label": "Prompt-Ersteller", - "role.prompt_builder.description": "Klärt die Aufgabe und macht daraus einen Arbeits-Prompt für die nächsten Schritte.", - "role.architect.label": "Architekt", - "role.architect.description": "Entwirft Lösung, Modulgrenzen, Daten und Risiken.", - "role.developer.label": "Entwickler", - "role.developer.description": "Schlägt Implementierung, Dateien, Schritte und technische Details vor.", - "role.tester.label": "Tester", - "role.tester.description": "Findet Prüfungen, Grenzfälle, Regressionen und Testszenarien.", - "role.reviewer.label": "Prüfer", - "role.reviewer.description": "Prüft Plan/Ergebnis kritisch und sucht Schwachstellen.", - "role.synthesizer.label": "Synthesizer", - "role.synthesizer.description": "Fasst Pipeline-Ausgaben in eine kurze Zusammenfassung und nächste Schritte zusammen.", - "topbar.model": "Modell", - "topbar.role": "Rolle dieses Chats in der Pipeline", - "topbar.coderTitle": "Agentenmodus aktivieren: Das Modell kann Dateien erstellen und bearbeiten", - "topbar.coder": "🛠 Coder", - "topbar.coderOn": "🛠 Coder EIN", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP EIN", - "topbar.pipeline": "Ablauf", - "topbar.pipelineOn": "Ablauf EIN", - "topbar.hardwareTitle": "ESP / Board-Firmware: aktiviert das Hardware-Agentenprofil", - "topbar.pipelineTitle": "Nachrichten entlang der Pipeline-Verbindungen weitergeben", - "topbar.flow": "Ablauf", - "topbar.flowTitle": "Pipeline-Ablauf", - "topbar.theme": "Theme wechseln", - "topbar.settings": "Einstellungen / erlaubte Befehle", - "topbar.quit": "Beenden — App stoppen und Chrome schließen", - "pipeline.title": "Pipeline-Ablauf", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Jedem Chat eine Rolle zuweisen und den nächsten Schritt wählen.", - "pipeline.empty": "Erstellen Sie mehrere Chats und verbinden Sie sie hier.", - "pipeline.end": "Ende", - "pipeline.user": "Benutzer", - "pipeline.model": "Modell", - "composer.chooseChat": "Wähle links einen Chat...", - "composer.message": "Nachricht an {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Tiefes Denken", - "composer.thinkingTitle": "Tiefes Denken: Das Modell zeigt die Gedankenkette", - "composer.thinkingRequired": "Tiefes Denken ist für dieses Modell erforderlich", - "composer.search": "🌐 Intelligente Suche", - "composer.searchTitle": "Intelligente Suche: Das Modell nutzt Websuche für aktuelle Informationen", - "composer.attach": "📎 Datei", - "composer.attachTitle": "Textdatei zum Lesen anhängen", - "composer.voice": "🎙 Sprache", - "composer.voiceTitle": "Sprache aufnehmen und Transkript in die Nachricht einfügen", - "composer.voiceStop": "■ Stopp", - "composer.stop": "■", - "composer.stopTitle": "Ausführung stoppen", - "composer.voiceInstalling": "Parakeet V3 wird installiert. Das kann einige Minuten dauern...", - "composer.voiceRecording": "Sprachaufnahme läuft...", - "composer.voiceTranscribing": "Sprache wird transkribiert...", - "composer.voiceMissing": "Voice-Helper ist nicht installiert. Legen Sie ai-free-stt unter {path} ab oder setzen Sie AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Dieses Browserfenster unterstützt keine Mikrofonaufnahme.", - "composer.voiceNoSpeech": "Keine Sprache erkannt.", - "composer.defaultImageQuestion": "Was ist auf diesem Bild? Beschreiben Sie es ausführlich.", - "composer.imageQuestionLabel": "(Bildfrage)", - "composer.uploadingImage": "Bild{num} wird hochgeladen und verarbeitet: {name}...", - "composer.thinkingStatus": "Denke...", - "composer.writingStatus": "Schreibt Antwort…", - "composer.backgroundTask": "⚙️ Aufgabe läuft im Hintergrund; Sie können zu einem anderen Chat wechseln", - "file.svgUnsupported": "SVG (\"{name}\") wird für Erkennung nicht unterstützt. Als PNG oder JPG speichern.", - "file.imageTooLarge": "Bild \"{name}\" ist zu groß ({mb} MB). Limit: 10 MB.", - "file.largeImageConfirm": "\"{name}\" ist {mb} MB groß. Große Dateien liefern bei DeepSeek oft CONTENT_EMPTY.\n\nTrotzdem hochladen?", - "file.readFailed": "\"{name}\" konnte nicht gelesen werden: {message}", - "file.uploadMissingId": "Upload kam ohne fileId zurück", - "file.qwenImageUnsupported": "AI Free kann Bilder noch nicht über den Qwen-Webtransport senden. Wählen Sie DeepSeek V4 Vision oder ChatGPT, damit das Bild verarbeitet wird.", - "file.binaryUnsupported": "Datei \"{name}\" ist binär ({ext}). Unterstützt werden derzeit Textdateien und Bilder (PNG/JPG/GIF/WEBP).\n\nPDF- und Office-Dokumente funktionieren noch nicht; dafür ist eine separate Phase nötig.", - "file.textTooLarge": "Datei \"{name}\" ist zu groß ({kb} KB). Textlimit: {limitKb} KB.", - "file.looksBinary": "Datei \"{name}\" sieht binär aus. Wenn sie Text ist, in .txt umbenennen.", - "file.remove": "Entfernen", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "Ich habe Datei{plural} angehängt. Bitte lesen und in der Antwort berücksichtigen:", - "file.promptHeader": "Datei: {name} ({kb} KB)", - "file.promptQuestion": "Meine Frage:", - "chat.delete": "Chat löschen", - "chat.running": "/code-Aufgabe läuft", - "chat.messages": "{count} Nachrichten", - "chat.deleteConfirm": "Chat löschen?", - "chat.history": "Verlauf: {file}", - "chat.you": "Sie", - "chat.assistant": "Assistent", - "chat.reasoningProcess": "Denkprozess", - "chat.reasoningThinking": "Denkt nach…", - "chat.question": "Frage", - "chat.system": "System", - "install.title": "Werkzeug installieren", - "install.approve": "Installieren", - "install.reject": "Abbrechen", - "install.running": "Installation läuft...", - "install.failed": "Installation fehlgeschlagen.", - "settings.title": "Einstellungen", - "settings.interface": "Oberfläche", - "settings.tabLanguage": "Sprache", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Berechtigungen", - "settings.language": "Sprache", - "settings.webSearchDefault": "Intelligente Suche standardmäßig aktivieren", - "settings.voiceTitle": "Spracheingabe", - "settings.voiceProvider": "Modell", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Bereit", - "settings.voiceMissing": "Nicht installiert", - "settings.voiceInstallHint": "Modell und Runtime sind nicht im Plugin enthalten. Installieren Sie ai-free-stt separat oder setzen Sie AI_FREE_STT_BIN.", - "settings.languageSaved": "Sprache gespeichert. Oberfläche wird neu geladen...", - "settings.loadFailed": "Einstellungen konnten nicht geladen werden: {message}", - "settings.low": "Niedriges Risiko", - "settings.medium": "Mittleres Risiko", - "settings.high": "Hohes Risiko", - "settings.apiTitle": "OpenAI-kompatible API", - "settings.baseUrl": "Basis-URL", - "settings.apiNote": "In einem OpenAI-kompatiblen Client die Basis-URL und den Bearer API-Key des gewünschten Anbieters verwenden. Modelle: {models}", - "settings.anthropicApiTitle": "Anthropic-kompatible API", - "settings.anthropicBaseUrl": "Basis-URL", - "settings.anthropicEndpoint": "Messages-Endpunkt", - "settings.anthropicAuth": "Auth-Header", - "settings.anthropicNote": "In einem Anthropic-kompatiblen Client die Basis-URL ohne /v1 und denselben Anbieter-Key verwenden. POST /v1/messages wird unterstützt. Modelle: {models}", - "settings.noKey": "Schlüssel nicht erstellt", - "settings.keyCreated": "Schlüssel erstellt", - "settings.createKey": "Erstellen", - "settings.keyReady": "{label} API-Key ist bereit", - "settings.keyCreateFailed": "{label} API-Key konnte nicht erstellt werden: {message}", - "settings.saveFailed": "Konnte nicht speichern: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Dunkel", - "theme.light": "Hell", - "theme.contrast": "Kontrast", - "theme.title": "Theme: {label}", - "shutdown.title": "CLI gestoppt", - "shutdown.sub": "Der Server antwortet nicht mehr. Das Fenster wird automatisch geschlossen.", - "shutdown.gracefulTitle": "ai-free wird beendet…", - "shutdown.stoppingTasks": "Hintergrundaufgaben werden gestoppt…", - "shutdown.closingBrowsers": "Chrome wird geschlossen (ChatGPT / Qwen)…", - "shutdown.closingServer": "Server wird gestoppt…", - "shutdown.stopped": "Gestoppt", - "shutdown.stoppedSub": "Das Fenster wird automatisch geschlossen.", - "welcome.title": "Willkommen bei AI Free", - "welcome.chooseProviders": "Wähle die KI-Anbieter aus, die du verbinden möchtest.", - "welcome.multi": "Wählen Sie einen oder mehrere. Weitere können später in den Einstellungen hinzugefügt werden.", - "welcome.prompt1": "Nummern durch Kommas getrennt eingeben (z. B. \"1\" oder \"1,2\"),", - "welcome.prompt2": "oder Enter für DeepSeek als Standard drücken:", - "welcome.invalid": "⚠️ Auswahl nicht verstanden. DeepSeek wird standardmäßig verwendet.", - "welcome.connecting": "Verbinde: {providers}", - "welcome.loginFailed": "❌ {provider} konnte nicht verbunden werden: {message}", - "welcome.retryLater": "Sie können es später über Einstellungen im Chatfenster erneut versuchen.", - "welcome.done": "✅ Fertig. Chat-Fenster wird gestartet...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/de.mjs"; diff --git a/src/i18n/languages/en.mjs b/src/i18n/languages/en.mjs index 2e19e77..ea2f5b2 100644 --- a/src/i18n/languages/en.mjs +++ b/src/i18n/languages/en.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "en", - name: "English", - dir: "ltr", - messages: { - "app.workspace": "Workspace", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Refresh", - "app.newChat": "+ New chat", - "app.noChat": "No chat selected", - "app.createChatHint": "Create a chat on the left. Each chat can be a separate project or work context.", - "app.firstMessage": "Write the first message for this project.", - "app.close": "Close", - "app.loading": "Loading...", - "app.loadingShort": "Loading...", - "app.error": "Error: {message}", - "app.requestFailed": "Request failed", - "app.resizeChats": "Resize chat list", - "app.resizeComposer": "Resize input area", - "newChat.title": "New chat", - "newChat.provider": "Provider", - "newChat.mode": "Mode (model)", - "newChat.modeHint": "The mode is fixed when the chat is created. To switch later, create a new chat with the mode you need.", - "newChat.chatTitle": "Chat title (optional)", - "newChat.chatTitlePlaceholder": "Example: auth refactor", - "newChat.workspace": "Project folder", - "newChat.workspacePlaceholder": "/Users/.../project or ~/Projects/new-thing", - "newChat.browse": "📁 Browse", - "newChat.up": "↑ Up", - "newChat.home": "🏠 Home", - "newChat.newFolder": "➕ New folder", - "newChat.hidden": "Hidden", - "newChat.pickFolder": "Select this folder", - "newChat.newFolderPlaceholder": "New folder name", - "newChat.create": "Create", - "newChat.cancel": "Cancel", - "newChat.createFolder": "Create the folder if it does not exist (only under your $HOME)", - "newChat.submit": "Create chat", - "newChat.emptyFolderName": "Enter a name.", - "newChat.defaultProject": "default", - "newChat.truncated": "Not all folders are shown. Enable \"Hidden\" or open the parent folder.", - "newChat.folderCount": "Folders: {total}{suffix}", - "newChat.hiddenSuffix": " (hidden .folders - \"Hidden\" checkbox)", - "newChat.folderShown": "Showing {shown} of {total} folders", - "newChat.tooManyFolders": "(too many folders - narrow the path or enable \"Hidden\")", - "newChat.noSubfolders": "(no subfolders - you can select this folder with \"Select\")", - "newChat.truncatedInline": "Showing the first {shown} of {total}. Narrow the path or enable \"Hidden\".", - "newChat.creating": "Creating chat...", - "provider.connected": "✓ Connected", - "provider.connectedTitle": "You are signed in. Click to use another account", - "provider.authorize": "🔑 Sign in", - "provider.authorizeTitle": "Sign-in required. Click to sign in", - "provider.connectConfirm": "Connect {label}?\n\nA browser window will open. Sign in on the site; the window will close after login.", - "provider.chatgptConnectConfirm": "Connect {label}?\n\nA regular Chrome window will open once for reliable sign-in. It closes automatically after the active session is verified, then ChatGPT continues inside AI Free.", - "provider.chatgptEmbedLogin": "Complete sign-in in the Chrome window. It closes automatically only after the active session is verified.", - "provider.chatgptEmbedLoginTimeout": "Sign-in timed out for {label}. Click ‘Sign in with Chrome’ and try again.", - "provider.connectedAlert": "{label} connected.", - "provider.tokenMissing": "Login finished, but no token was found. Try again or run: npm run login-{id}", - "provider.connectFailed": "Could not connect {label}: {message}", - "provider.deepseekFast": "fast regular chat", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "image recognition", - "provider.qwenDefault": "choose the model in the chat header", - "role.assistantDescription": "Regular assistant", - "role.assistant": "Assistant", - "role.assistant.label": "Assistant", - "role.assistant.description": "Regular assistant for chat and quick answers.", - "role.prompt_builder.label": "Prompt Builder", - "role.prompt_builder.description": "Clarifies the task and turns it into a working prompt for the next steps.", - "role.architect.label": "Architect", - "role.architect.description": "Designs the solution, module boundaries, data, and risks.", - "role.developer.label": "Developer", - "role.developer.description": "Proposes implementation, files, steps, and technical details.", - "role.tester.label": "Tester", - "role.tester.description": "Finds checks, edge cases, regressions, and test scenarios.", - "role.reviewer.label": "Reviewer", - "role.reviewer.description": "Critically checks the plan/result and looks for weak spots.", - "role.synthesizer.label": "Synthesizer", - "role.synthesizer.description": "Combines pipeline outputs into a short summary and next steps.", - "topbar.model": "Model", - "topbar.role": "This chat role in the pipeline", - "topbar.coderTitle": "Enable agent mode: the model can create and edit files", - "topbar.coder": "🛠 Coder", - "topbar.coderOn": "🛠 Coder ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "Pipeline", - "topbar.pipelineOn": "Pipeline ON", - "topbar.hardwareTitle": "ESP / board firmware: enable the hardware agent profile", - "topbar.pipelineTitle": "Pass messages along pipeline links", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "topbar.flow": "Flow", - "topbar.flowTitle": "Pipeline flow", - "topbar.theme": "Change theme", - "topbar.settings": "Settings / allowed commands", - "topbar.quit": "Quit — stop the app and close Chrome", - "pipeline.title": "Pipeline flow", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — separate Chrome.", - "pipeline.sub": "Assign each chat a role and choose the next step.", - "pipeline.empty": "Create several chats, then connect them here.", - "pipeline.end": "End", - "pipeline.user": "User", - "pipeline.model": "model", - "composer.chooseChat": "Select a chat on the left...", - "composer.message": "Message {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Deep thinking", - "composer.thinkingTitle": "Deep thinking - the model shows chain-of-thought", - "composer.thinkingRequired": "Deep thinking is required for this model", - "composer.search": "🌐 Smart search", - "composer.searchTitle": "Smart search - the model uses web search for current information", - "composer.attach": "📎 File", - "composer.attachTitle": "Attach a text file to read", - "composer.voice": "🎙 Voice", - "composer.voiceTitle": "Record voice and insert the transcript into the message", - "composer.voiceStop": "■ Stop", - "composer.stop": "■", - "composer.stopTitle": "Stop execution", - "composer.voiceInstalling": "Installing Parakeet V3. This can take a few minutes...", - "composer.voiceRecording": "Recording voice...", - "composer.voiceTranscribing": "Transcribing voice...", - "composer.voiceMissing": "Voice helper is not installed. Put ai-free-stt at {path} or set AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "This browser window does not support microphone recording.", - "composer.voiceNoSpeech": "No speech was recognized.", - "composer.defaultImageQuestion": "What is in this image? Describe it in detail.", - "composer.imageQuestionLabel": "(image question)", - "composer.uploadingImage": "Uploading and processing image{num}: {name}...", - "composer.thinkingStatus": "Thinking...", - "composer.writingStatus": "Writing response…", - "composer.backgroundTask": "⚙️ Task is running in the background - you can switch to another chat", - "file.svgUnsupported": "SVG (\"{name}\") is not supported for recognition. Save it as PNG or JPG.", - "file.imageTooLarge": "Image \"{name}\" is too large ({mb} MB). Limit: 10 MB.", - "file.largeImageConfirm": "\"{name}\" is {mb} MB. Large files often return CONTENT_EMPTY on DeepSeek.\n\nUpload anyway?", - "file.readFailed": "Could not read \"{name}\": {message}", - "file.uploadMissingId": "Upload returned without fileId", - "file.qwenImageUnsupported": "AI Free cannot yet pass images through the Qwen web transport. Select DeepSeek V4 Vision or ChatGPT so the image is fully processed.", - "file.binaryUnsupported": "File \"{name}\" is binary ({ext}). Text files and images (PNG/JPG/GIF/WEBP) are currently supported.\n\nPDF and Office documents do not work yet - they need a separate phase.", - "file.textTooLarge": "File \"{name}\" is too large ({kb} KB). Text limit: {limitKb} KB.", - "file.looksBinary": "File \"{name}\" looks binary. If it is text, rename it to .txt.", - "file.remove": "Remove", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "I attached file{plural}. Read and consider it in your answer:", - "file.promptHeader": "File: {name} ({kb} KB)", - "file.promptQuestion": "My question:", - "chat.delete": "Delete chat", - "chat.running": "/code task is running", - "chat.messages": "{count} messages", - "chat.deleteConfirm": "Delete chat?", - "chat.history": "History: {file}", - "chat.you": "You", - "chat.assistant": "Assistant", - "chat.reasoningProcess": "Thought process", - "chat.reasoningThinking": "Thinking…", - "chat.question": "Question", - "chat.system": "System", - "install.title": "Install tool", - "install.approve": "Install", - "install.reject": "Cancel", - "install.running": "Installation is running...", - "install.failed": "Installation failed.", - "settings.title": "Settings", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.interface": "Interface", - "settings.tabLanguage": "Language", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter only the bot token. Chat ID is optional: it will be bound automatically after /start in Telegram.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID (optional)", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permissions", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "settings.language": "Language", - "settings.webSearchDefault": "Enable smart search by default", - "settings.voiceTitle": "Voice input", - "settings.voiceProvider": "Model", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Ready", - "settings.voiceMissing": "Not installed", - "settings.voiceInstallHint": "The model and runtime are not bundled with the plugin. Install ai-free-stt separately or set AI_FREE_STT_BIN.", - "settings.languageSaved": "Language saved. Reloading the interface...", - "settings.loadFailed": "Could not load settings: {message}", - "settings.low": "Low risk", - "settings.medium": "Medium risk", - "settings.high": "High risk", - "settings.apiTitle": "OpenAI-compatible API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "In an OpenAI-compatible client, use the Base URL and Bearer API key for the provider you need. Models: {models}", - "settings.anthropicApiTitle": "Anthropic-compatible API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "Auth header", - "settings.anthropicNote": "In an Anthropic-compatible client, use the Base URL without /v1 and the same provider API key. POST /v1/messages is supported. Models: {models}", - "settings.noKey": "Key not created", - "settings.keyCreated": "Key created", - "settings.createKey": "Create", - "settings.keyReady": "{label} API key is ready", - "settings.keyCreateFailed": "Could not create {label} API key: {message}", - "settings.saveFailed": "Could not save: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Dark", - "theme.light": "Light", - "theme.contrast": "Contrast", - "theme.title": "Theme: {label}", - "shutdown.title": "CLI stopped", - "shutdown.sub": "The server is no longer responding. This window will close automatically.", - "shutdown.gracefulTitle": "Stopping ai-free…", - "shutdown.stoppingTasks": "Stopping background tasks…", - "shutdown.closingBrowsers": "Closing Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Stopping server…", - "shutdown.stopped": "Stopped", - "shutdown.stoppedSub": "This window will close automatically.", - "welcome.title": "Welcome to AI Free", - "welcome.chooseProviders": "Choose the AI providers you want to connect.", - "welcome.multi": "Choose one or several. You can add more later in Settings.", - "welcome.prompt1": "Enter numbers separated by commas (for example \"1\" or \"1,2\"),", - "welcome.prompt2": "or press Enter for DeepSeek by default:", - "welcome.invalid": "⚠️ Could not understand the choice. Using DeepSeek by default.", - "welcome.connecting": "Connecting: {providers}", - "welcome.loginFailed": "❌ Could not connect {provider}: {message}", - "welcome.retryLater": "You can try again later from Settings in the chat window.", - "welcome.done": "✅ Done. Starting the chat window...", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/en.mjs"; diff --git a/src/i18n/languages/es.mjs b/src/i18n/languages/es.mjs index 7d9cadb..446ee8f 100644 --- a/src/i18n/languages/es.mjs +++ b/src/i18n/languages/es.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "es", - name: "Español", - dir: "ltr", - messages: { - "app.workspace": "Área de trabajo", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Actualizar", - "app.newChat": "+ Nuevo chat", - "app.noChat": "Ningún chat seleccionado", - "app.createChatHint": "Crea un chat a la izquierda. Cada chat puede ser un proyecto o contexto de trabajo independiente.", - "app.firstMessage": "Escribe el primer mensaje para este proyecto.", - "app.close": "Cerrar", - "app.loading": "Cargando...", - "app.loadingShort": "Cargando...", - "app.error": "Error: {message}", - "app.requestFailed": "La solicitud falló", - "app.resizeChats": "Cambiar el ancho de la lista de chats", - "app.resizeComposer": "Cambiar la altura del área de entrada", - "newChat.title": "Nuevo chat", - "newChat.provider": "Proveedor", - "newChat.mode": "Modo (modelo)", - "newChat.modeHint": "El modo queda fijado al crear el chat. Para cambiarlo después, crea un chat nuevo con el modo que necesitas.", - "newChat.chatTitle": "Título del chat (opcional)", - "newChat.chatTitlePlaceholder": "Ejemplo: refactorización de auth", - "newChat.workspace": "Carpeta del proyecto", - "newChat.workspacePlaceholder": "/Users/.../project o ~/Projects/new-thing", - "newChat.browse": "📁 Explorar", - "newChat.up": "↑ Arriba", - "newChat.home": "🏠 Inicio", - "newChat.newFolder": "➕ Nueva carpeta", - "newChat.hidden": "Ocultos", - "newChat.pickFolder": "Seleccionar esta carpeta", - "newChat.newFolderPlaceholder": "Nombre de la nueva carpeta", - "newChat.create": "Crear", - "newChat.cancel": "Cancelar", - "newChat.createFolder": "Crear la carpeta si no existe (solo dentro de tu $HOME)", - "newChat.submit": "Crear chat", - "newChat.emptyFolderName": "Introduce un nombre.", - "newChat.defaultProject": "predeterminado", - "newChat.truncated": "No se muestran todas las carpetas. Activa \"Ocultos\" o abre la carpeta superior.", - "newChat.folderCount": "Carpetas: {total}{suffix}", - "newChat.hiddenSuffix": " (carpetas . ocultas - casilla \"Ocultos\")", - "newChat.folderShown": "Mostrando {shown} de {total} carpetas", - "newChat.tooManyFolders": "(demasiadas carpetas - acota la ruta o activa \"Ocultos\")", - "newChat.noSubfolders": "(no hay subcarpetas - puedes seleccionar esta carpeta con \"Seleccionar\")", - "newChat.truncatedInline": "Se muestran las primeras {shown} de {total}. Acota la ruta o activa \"Ocultos\".", - "newChat.creating": "Creando chat...", - "provider.connected": "✓ Conectado", - "provider.connectedTitle": "Has iniciado sesión. Pulsa para usar otra cuenta", - "provider.authorize": "🔑 Autorizar", - "provider.authorizeTitle": "Se requiere iniciar sesión. Pulsa para entrar", - "provider.connectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana del navegador. Inicia sesión en el sitio; la ventana se cerrará después.", - "provider.chatgptConnectConfirm": "¿Conectar {label}?\n\nSe abrirá una ventana normal de Chrome una sola vez para iniciar sesión de forma fiable. Se cerrará automáticamente después de verificar la sesión activa y ChatGPT continuará dentro de AI Free.", - "provider.chatgptEmbedLogin": "Completa el inicio de sesión en la ventana de Chrome. Se cerrará automáticamente solo después de verificar la sesión activa.", - "provider.chatgptEmbedLoginTimeout": "Se agotó el tiempo para iniciar sesión en {label}. Pulsa «Iniciar sesión con Chrome» e inténtalo de nuevo.", - "provider.connectedAlert": "{label} conectado.", - "provider.tokenMissing": "El inicio de sesión terminó, pero no se encontró ningún token. Inténtalo de nuevo o ejecuta: npm run login-{id}", - "provider.connectFailed": "No se pudo conectar {label}: {message}", - "provider.deepseekFast": "chat normal rápido", - "provider.deepseekExpert": "razonamiento / R1", - "provider.deepseekVision": "reconocimiento de imágenes", - "provider.qwenDefault": "elige el modelo en la cabecera del chat", - "role.assistantDescription": "Asistente normal", - "role.assistant": "Asistente", - "role.assistant.label": "Asistente", - "role.assistant.description": "Asistente normal para chat y respuestas rápidas.", - "role.prompt_builder.label": "Constructor de prompts", - "role.prompt_builder.description": "Aclara la tarea y la convierte en un prompt útil para los siguientes pasos.", - "role.architect.label": "Arquitecto", - "role.architect.description": "Diseña la solución, los límites de módulos, los datos y los riesgos.", - "role.developer.label": "Desarrollador", - "role.developer.description": "Propone implementación, archivos, pasos y detalles técnicos.", - "role.tester.label": "Tester", - "role.tester.description": "Busca verificaciones, casos límite, regresiones y escenarios de prueba.", - "role.reviewer.label": "Revisor", - "role.reviewer.description": "Revisa críticamente el plan/resultado y busca puntos débiles.", - "role.synthesizer.label": "Sintetizador", - "role.synthesizer.description": "Combina las salidas del pipeline en un resumen breve y próximos pasos.", - "topbar.model": "Modelo", - "topbar.role": "Rol de este chat en el pipeline", - "topbar.coderTitle": "Activar modo agente: el modelo puede crear y editar archivos", - "topbar.coder": "🛠 Programador", - "topbar.coderOn": "🛠 Programador ACTIVADO", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ACTIVADO", - "topbar.pipeline": "Flujo", - "topbar.pipelineOn": "Flujo ON", - "topbar.hardwareTitle": "ESP / firmware de placas: activa el perfil de agente de hardware", - "topbar.pipelineTitle": "Pasar mensajes por los enlaces del pipeline", - "topbar.flow": "Flujo", - "topbar.flowTitle": "Flujo del pipeline", - "topbar.theme": "Cambiar tema", - "topbar.settings": "Configuración / comandos permitidos", - "topbar.quit": "Salir — detener la app y cerrar Chrome", - "pipeline.title": "Flujo del pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Asigna un rol a cada chat y elige el siguiente paso.", - "pipeline.empty": "Crea varios chats y conéctalos aquí.", - "pipeline.end": "Fin", - "pipeline.user": "Usuario", - "pipeline.model": "modelo", - "composer.chooseChat": "Elige un chat a la izquierda...", - "composer.message": "Mensaje para {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Pensamiento profundo", - "composer.thinkingTitle": "Pensamiento profundo: el modelo muestra la cadena de razonamiento", - "composer.thinkingRequired": "El pensamiento profundo es obligatorio para este modelo", - "composer.search": "🌐 Búsqueda inteligente", - "composer.searchTitle": "Búsqueda inteligente: el modelo usa búsqueda web para información actual", - "composer.attach": "📎 Archivo", - "composer.attachTitle": "Adjuntar un archivo de texto para leer", - "composer.voice": "🎙 Voz", - "composer.voiceTitle": "Grabar voz e insertar la transcripción en el mensaje", - "composer.voiceStop": "■ Parar", - "composer.stop": "■", - "composer.stopTitle": "Detener ejecución", - "composer.voiceInstalling": "Instalando Parakeet V3. Puede tardar unos minutos...", - "composer.voiceRecording": "Grabando voz...", - "composer.voiceTranscribing": "Transcribiendo voz...", - "composer.voiceMissing": "El helper de voz no está instalado. Coloca ai-free-stt en {path} o define AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Esta ventana del navegador no admite grabación de micrófono.", - "composer.voiceNoSpeech": "No se reconoció voz.", - "composer.defaultImageQuestion": "¿Qué hay en esta imagen? Descríbelo con detalle.", - "composer.imageQuestionLabel": "(pregunta sobre imagen)", - "composer.uploadingImage": "Subiendo y procesando imagen{num}: {name}...", - "composer.thinkingStatus": "Pensando...", - "composer.writingStatus": "Escribiendo respuesta…", - "composer.backgroundTask": "⚙️ La tarea se ejecuta en segundo plano; puedes cambiar a otro chat", - "file.svgUnsupported": "SVG (\"{name}\") no se admite para reconocimiento. Guárdalo como PNG o JPG.", - "file.imageTooLarge": "La imagen \"{name}\" es demasiado grande ({mb} MB). Límite: 10 MB.", - "file.largeImageConfirm": "\"{name}\" pesa {mb} MB. Los archivos grandes suelen devolver CONTENT_EMPTY en DeepSeek.\n\n¿Subir de todos modos?", - "file.readFailed": "No se pudo leer \"{name}\": {message}", - "file.uploadMissingId": "La subida volvió sin fileId", - "file.qwenImageUnsupported": "AI Free todavía no puede enviar imágenes mediante el transporte web de Qwen. Selecciona DeepSeek V4 Vision o ChatGPT para procesar la imagen.", - "file.binaryUnsupported": "El archivo \"{name}\" es binario ({ext}). Ahora se admiten archivos de texto e imágenes (PNG/JPG/GIF/WEBP).\n\nLos PDF y documentos Office aún no funcionan: necesitan una fase separada.", - "file.textTooLarge": "El archivo \"{name}\" es demasiado grande ({kb} KB). Límite de texto: {limitKb} KB.", - "file.looksBinary": "El archivo \"{name}\" parece binario. Si es texto, cámbiale el nombre a .txt.", - "file.remove": "Quitar", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "He adjuntado archivo{plural}. Léelo y tenlo en cuenta en tu respuesta:", - "file.promptHeader": "Archivo: {name} ({kb} KB)", - "file.promptQuestion": "Mi pregunta:", - "chat.delete": "Eliminar chat", - "chat.running": "La tarea /code se está ejecutando", - "chat.messages": "{count} mensajes", - "chat.deleteConfirm": "¿Eliminar chat?", - "chat.history": "Historial: {file}", - "chat.you": "Tú", - "chat.assistant": "Asistente", - "chat.reasoningProcess": "Proceso de razonamiento", - "chat.reasoningThinking": "Pensando…", - "chat.question": "Pregunta", - "chat.system": "Sistema", - "install.title": "Instalar herramienta", - "install.approve": "Instalar", - "install.reject": "Cancelar", - "install.running": "La instalación está en curso...", - "install.failed": "La instalación falló.", - "settings.title": "Configuración", - "settings.interface": "Interfaz", - "settings.tabLanguage": "Idioma", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permisos", - "settings.language": "Idioma", - "settings.webSearchDefault": "Activar búsqueda inteligente por defecto", - "settings.voiceTitle": "Entrada de voz", - "settings.voiceProvider": "Modelo", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Listo", - "settings.voiceMissing": "No instalado", - "settings.voiceInstallHint": "El modelo y el runtime no se incluyen con el plugin. Instala ai-free-stt por separado o define AI_FREE_STT_BIN.", - "settings.languageSaved": "Idioma guardado. Recargando la interfaz...", - "settings.loadFailed": "No se pudo cargar la configuración: {message}", - "settings.low": "Riesgo bajo", - "settings.medium": "Riesgo medio", - "settings.high": "Riesgo alto", - "settings.apiTitle": "API compatible con OpenAI", - "settings.baseUrl": "URL base", - "settings.apiNote": "En un cliente compatible con OpenAI, usa la URL base y la clave Bearer del proveedor necesario. Modelos: {models}", - "settings.anthropicApiTitle": "API compatible con Anthropic", - "settings.anthropicBaseUrl": "URL base", - "settings.anthropicEndpoint": "Endpoint de Messages", - "settings.anthropicAuth": "Cabecera de autenticación", - "settings.anthropicNote": "En un cliente compatible con Anthropic, usa la URL base sin /v1 y la misma clave del proveedor. Se admite POST /v1/messages. Modelos: {models}", - "settings.noKey": "Clave no creada", - "settings.keyCreated": "Clave creada", - "settings.createKey": "Crear", - "settings.keyReady": "Clave API de {label} lista", - "settings.keyCreateFailed": "No se pudo crear la clave API de {label}: {message}", - "settings.saveFailed": "No se pudo guardar: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Oscuro", - "theme.light": "Claro", - "theme.contrast": "Contraste", - "theme.title": "Tema: {label}", - "shutdown.title": "CLI detenido", - "shutdown.sub": "El servidor ya no responde. La ventana se cerrará automáticamente.", - "shutdown.gracefulTitle": "Deteniendo ai-free…", - "shutdown.stoppingTasks": "Deteniendo tareas en segundo plano…", - "shutdown.closingBrowsers": "Cerrando Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Deteniendo el servidor…", - "shutdown.stopped": "Detenido", - "shutdown.stoppedSub": "La ventana se cerrará automáticamente.", - "welcome.title": "Bienvenido a AI Free", - "welcome.chooseProviders": "Elige los proveedores de IA que quieres conectar.", - "welcome.multi": "Elige uno o varios. Puedes añadir más después en Configuración.", - "welcome.prompt1": "Introduce números separados por comas (por ejemplo \"1\" o \"1,2\"),", - "welcome.prompt2": "o pulsa Enter para usar DeepSeek por defecto:", - "welcome.invalid": "⚠️ No se pudo entender la elección. Usando DeepSeek por defecto.", - "welcome.connecting": "Conectando: {providers}", - "welcome.loginFailed": "❌ No se pudo conectar {provider}: {message}", - "welcome.retryLater": "Puedes intentarlo de nuevo más tarde desde Configuración en la ventana de chat.", - "welcome.done": "✅ Listo. Iniciando la ventana de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/es.mjs"; diff --git a/src/i18n/languages/fr.mjs b/src/i18n/languages/fr.mjs index 2094ead..21d206c 100644 --- a/src/i18n/languages/fr.mjs +++ b/src/i18n/languages/fr.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "fr", - name: "Français", - dir: "ltr", - messages: { - "app.workspace": "Espace de travail", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Actualiser", - "app.newChat": "+ Nouveau chat", - "app.noChat": "Aucun chat sélectionné", - "app.createChatHint": "Crée un chat à gauche. Chaque chat peut être un projet ou un contexte de travail séparé.", - "app.firstMessage": "Écris le premier message pour ce projet.", - "app.close": "Fermer", - "app.loading": "Chargement...", - "app.loadingShort": "Chargement...", - "app.error": "Erreur : {message}", - "app.requestFailed": "La requête a échoué", - "app.resizeChats": "Redimensionner la liste des chats", - "app.resizeComposer": "Redimensionner la zone de saisie", - "newChat.title": "Nouveau chat", - "newChat.provider": "Fournisseur", - "newChat.mode": "Mode (modèle)", - "newChat.modeHint": "Le mode est fixé à la création du chat. Pour le changer ensuite, créez un nouveau chat avec le mode voulu.", - "newChat.chatTitle": "Titre du chat (facultatif)", - "newChat.chatTitlePlaceholder": "Exemple : refactorisation auth", - "newChat.workspace": "Dossier du projet", - "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", - "newChat.browse": "📁 Parcourir", - "newChat.up": "↑ Haut", - "newChat.home": "🏠 Accueil", - "newChat.newFolder": "➕ Nouveau dossier", - "newChat.hidden": "Masqués", - "newChat.pickFolder": "Sélectionner ce dossier", - "newChat.newFolderPlaceholder": "Nom du nouveau dossier", - "newChat.create": "Créer", - "newChat.cancel": "Annuler", - "newChat.createFolder": "Créer le dossier s’il n’existe pas (uniquement sous votre $HOME)", - "newChat.submit": "Créer le chat", - "newChat.emptyFolderName": "Saisissez un nom.", - "newChat.defaultProject": "par défaut", - "newChat.truncated": "Tous les dossiers ne sont pas affichés. Activez \"Masqués\" ou ouvrez le dossier parent.", - "newChat.folderCount": "Dossiers : {total}{suffix}", - "newChat.hiddenSuffix": " (dossiers . masqués - case \"Masqués\")", - "newChat.folderShown": "Affichage de {shown} sur {total} dossiers", - "newChat.tooManyFolders": "(trop de dossiers - précisez le chemin ou activez \"Masqués\")", - "newChat.noSubfolders": "(aucun sous-dossier - vous pouvez sélectionner ce dossier avec \"Sélectionner\")", - "newChat.truncatedInline": "Affichage des {shown} premiers sur {total}. Précisez le chemin ou activez \"Masqués\".", - "newChat.creating": "Création du chat...", - "provider.connected": "✓ Connecté", - "provider.connectedTitle": "Vous êtes connecté. Cliquez pour utiliser un autre compte", - "provider.authorize": "🔑 Autoriser", - "provider.authorizeTitle": "Connexion requise. Cliquez pour vous connecter", - "provider.connectConfirm": "Connecter {label} ?\n\nUne fenêtre de navigateur va s’ouvrir. Connectez-vous sur le site ; elle se fermera après la connexion.", - "provider.chatgptConnectConfirm": "Connecter {label} ?\n\nUne fenêtre Chrome normale s’ouvrira une seule fois pour une connexion fiable. Elle se fermera automatiquement après vérification de la session active, puis ChatGPT continuera dans AI Free.", - "provider.chatgptEmbedLogin": "Terminez la connexion dans la fenêtre Chrome. Elle se fermera automatiquement uniquement après vérification de la session active.", - "provider.chatgptEmbedLoginTimeout": "Le délai de connexion à {label} a expiré. Cliquez sur « Se connecter avec Chrome » et réessayez.", - "provider.connectedAlert": "{label} connecté.", - "provider.tokenMissing": "Connexion terminée, mais aucun jeton trouvé. Réessayez ou lancez : npm run login-{id}", - "provider.connectFailed": "Impossible de connecter {label} : {message}", - "provider.deepseekFast": "chat normal rapide", - "provider.deepseekExpert": "raisonnement / R1", - "provider.deepseekVision": "reconnaissance d’images", - "provider.qwenDefault": "choisissez le modèle dans l’en-tête du chat", - "role.assistantDescription": "Assistant standard", - "role.assistant": "Assistant", - "role.assistant.label": "Assistant", - "role.assistant.description": "Assistant standard pour le chat et les réponses rapides.", - "role.prompt_builder.label": "Constructeur de prompts", - "role.prompt_builder.description": "Clarifie la tâche et la transforme en prompt exploitable pour les étapes suivantes.", - "role.architect.label": "Architecte", - "role.architect.description": "Conçoit la solution, les limites des modules, les données et les risques.", - "role.developer.label": "Développeur", - "role.developer.description": "Propose l’implémentation, les fichiers, les étapes et les détails techniques.", - "role.tester.label": "Testeur", - "role.tester.description": "Cherche les vérifications, cas limites, régressions et scénarios de test.", - "role.reviewer.label": "Relecteur", - "role.reviewer.description": "Vérifie de façon critique le plan/résultat et cherche les points faibles.", - "role.synthesizer.label": "Synthétiseur", - "role.synthesizer.description": "Combine les sorties du pipeline en un bref résumé et prochaines étapes.", - "topbar.model": "Modèle", - "topbar.role": "Rôle de ce chat dans le pipeline", - "topbar.coderTitle": "Activer le mode agent : le modèle peut créer et modifier des fichiers", - "topbar.coder": "🛠 Codeur", - "topbar.coderOn": "🛠 Codeur ACTIF", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ACTIF", - "topbar.pipeline": "Flux", - "topbar.pipelineOn": "Flux ON", - "topbar.hardwareTitle": "ESP / firmware de cartes : active le profil agent matériel", - "topbar.pipelineTitle": "Transmettre les messages via les liens du pipeline", - "topbar.flow": "Flux", - "topbar.flowTitle": "Flux du pipeline", - "topbar.theme": "Changer le thème", - "topbar.settings": "Paramètres / commandes autorisées", - "topbar.quit": "Quitter — arrêter l'app et fermer Chrome", - "pipeline.title": "Flux du pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Attribuez un rôle à chaque chat et choisissez l’étape suivante.", - "pipeline.empty": "Créez plusieurs chats, puis reliez-les ici.", - "pipeline.end": "Fin", - "pipeline.user": "Utilisateur", - "pipeline.model": "modèle", - "composer.chooseChat": "Choisis un chat à gauche...", - "composer.message": "Message pour {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Raisonnement approfondi", - "composer.thinkingTitle": "Réflexion approfondie : le modèle affiche la chaîne de raisonnement", - "composer.thinkingRequired": "La réflexion approfondie est obligatoire pour ce modèle", - "composer.search": "🌐 Recherche intelligente", - "composer.searchTitle": "Recherche intelligente : le modèle utilise le web pour les informations à jour", - "composer.attach": "📎 Fichier", - "composer.attachTitle": "Joindre un fichier texte à lire", - "composer.voice": "🎙 Voix", - "composer.voiceTitle": "Enregistrer la voix et insérer la transcription dans le message", - "composer.voiceStop": "■ Stop", - "composer.stop": "■", - "composer.stopTitle": "Arrêter l'exécution", - "composer.voiceInstalling": "Installation de Parakeet V3. Cela peut prendre quelques minutes...", - "composer.voiceRecording": "Enregistrement vocal...", - "composer.voiceTranscribing": "Transcription vocale...", - "composer.voiceMissing": "Le helper vocal n’est pas installé. Placez ai-free-stt dans {path} ou définissez AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Cette fenêtre de navigateur ne prend pas en charge l’enregistrement micro.", - "composer.voiceNoSpeech": "Aucune parole reconnue.", - "composer.defaultImageQuestion": "Que contient cette image ? Décrivez-la en détail.", - "composer.imageQuestionLabel": "(question sur l’image)", - "composer.uploadingImage": "Envoi et traitement de l’image{num} : {name}...", - "composer.thinkingStatus": "Réflexion...", - "composer.writingStatus": "Rédaction de la réponse…", - "composer.backgroundTask": "⚙️ La tâche s’exécute en arrière-plan ; vous pouvez passer à un autre chat", - "file.svgUnsupported": "SVG (\"{name}\") n’est pas pris en charge pour la reconnaissance. Enregistrez en PNG ou JPG.", - "file.imageTooLarge": "L’image \"{name}\" est trop grande ({mb} Mo). Limite : 10 Mo.", - "file.largeImageConfirm": "\"{name}\" fait {mb} Mo. Les gros fichiers renvoient souvent CONTENT_EMPTY sur DeepSeek.\n\nEnvoyer quand même ?", - "file.readFailed": "Impossible de lire \"{name}\" : {message}", - "file.uploadMissingId": "L’envoi est revenu sans fileId", - "file.qwenImageUnsupported": "AI Free ne peut pas encore transmettre les images via le transport web Qwen. Sélectionnez DeepSeek V4 Vision ou ChatGPT pour traiter l’image.", - "file.binaryUnsupported": "Le fichier \"{name}\" est binaire ({ext}). Les fichiers texte et images (PNG/JPG/GIF/WEBP) sont pris en charge.\n\nLes PDF et documents Office ne fonctionnent pas encore : il faut une phase séparée.", - "file.textTooLarge": "Le fichier \"{name}\" est trop grand ({kb} Ko). Limite texte : {limitKb} Ko.", - "file.looksBinary": "Le fichier \"{name}\" semble binaire. Si c’est du texte, renommez-le en .txt.", - "file.remove": "Retirer", - "file.sizeKb": "{kb} Ko", - "file.promptPrefix": "J’ai joint fichier{plural}. Lisez-le et tenez-en compte dans votre réponse :", - "file.promptHeader": "Fichier : {name} ({kb} Ko)", - "file.promptQuestion": "Ma question :", - "chat.delete": "Supprimer le chat", - "chat.running": "La tâche /code est en cours", - "chat.messages": "{count} messages", - "chat.deleteConfirm": "Supprimer le chat ?", - "chat.history": "Historique : {file}", - "chat.you": "Vous", - "chat.assistant": "Assistant", - "chat.reasoningProcess": "Processus de réflexion", - "chat.reasoningThinking": "En train de réfléchir…", - "chat.question": "Question", - "chat.system": "Système", - "install.title": "Installer un outil", - "install.approve": "Installer", - "install.reject": "Annuler", - "install.running": "Installation en cours...", - "install.failed": "L’installation a échoué.", - "settings.title": "Paramètres", - "settings.interface": "Interface", - "settings.tabLanguage": "Langue", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Autorisations", - "settings.language": "Langue", - "settings.webSearchDefault": "Activer la recherche intelligente par défaut", - "settings.voiceTitle": "Saisie vocale", - "settings.voiceProvider": "Modèle", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Prêt", - "settings.voiceMissing": "Non installé", - "settings.voiceInstallHint": "Le modèle et le runtime ne sont pas inclus dans le plugin. Installez ai-free-stt séparément ou définissez AI_FREE_STT_BIN.", - "settings.languageSaved": "Langue enregistrée. Rechargement de l’interface...", - "settings.loadFailed": "Impossible de charger les paramètres : {message}", - "settings.low": "Risque faible", - "settings.medium": "Risque moyen", - "settings.high": "Risque élevé", - "settings.apiTitle": "API compatible OpenAI", - "settings.baseUrl": "URL de base", - "settings.apiNote": "Dans un client compatible OpenAI, utilisez l’URL de base et la clé Bearer du fournisseur voulu. Modèles : {models}", - "settings.anthropicApiTitle": "API compatible Anthropic", - "settings.anthropicBaseUrl": "URL de base", - "settings.anthropicEndpoint": "Endpoint Messages", - "settings.anthropicAuth": "En-tête d’authentification", - "settings.anthropicNote": "Dans un client compatible Anthropic, utilisez l’URL de base sans /v1 et la même clé fournisseur. POST /v1/messages est pris en charge. Modèles : {models}", - "settings.noKey": "Clé non créée", - "settings.keyCreated": "Clé créée", - "settings.createKey": "Créer", - "settings.keyReady": "Clé API {label} prête", - "settings.keyCreateFailed": "Impossible de créer la clé API {label} : {message}", - "settings.saveFailed": "Impossible d’enregistrer : {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Sombre", - "theme.light": "Clair", - "theme.contrast": "Contraste", - "theme.title": "Thème : {label}", - "shutdown.title": "CLI arrêté", - "shutdown.sub": "Le serveur ne répond plus. La fenêtre va se fermer automatiquement.", - "shutdown.gracefulTitle": "Arrêt de ai-free…", - "shutdown.stoppingTasks": "Arrêt des tâches en arrière-plan…", - "shutdown.closingBrowsers": "Fermeture de Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Arrêt du serveur…", - "shutdown.stopped": "Arrêté", - "shutdown.stoppedSub": "La fenêtre va se fermer automatiquement.", - "welcome.title": "Bienvenue dans AI Free", - "welcome.chooseProviders": "Choisis les fournisseurs d'IA à connecter.", - "welcome.multi": "Choisissez-en un ou plusieurs. Vous pourrez en ajouter ensuite dans Paramètres.", - "welcome.prompt1": "Saisissez des numéros séparés par des virgules (par exemple \"1\" ou \"1,2\"),", - "welcome.prompt2": "ou appuyez sur Entrée pour DeepSeek par défaut :", - "welcome.invalid": "⚠️ Choix incompris. DeepSeek sera utilisé par défaut.", - "welcome.connecting": "Connexion : {providers}", - "welcome.loginFailed": "❌ Impossible de connecter {provider} : {message}", - "welcome.retryLater": "Vous pourrez réessayer plus tard depuis Paramètres dans la fenêtre de chat.", - "welcome.done": "✅ Terminé. Lancement de la fenêtre de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/fr.mjs"; diff --git a/src/i18n/languages/hi.mjs b/src/i18n/languages/hi.mjs index c771b56..da58808 100644 --- a/src/i18n/languages/hi.mjs +++ b/src/i18n/languages/hi.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "hi", - name: "हिन्दी", - dir: "ltr", - messages: { - "app.workspace": "वर्कस्पेस", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "रीफ्रेश", - "app.newChat": "+ नया चैट", - "app.noChat": "कोई चैट चयनित नहीं", - "app.createChatHint": "बाईं ओर चैट बनाएं। हर चैट अलग प्रोजेक्ट या काम का संदर्भ हो सकती है।", - "app.firstMessage": "इस प्रोजेक्ट के लिए पहला संदेश लिखें।", - "app.close": "बंद करें", - "app.loading": "लोड हो रहा है...", - "app.loadingShort": "लोड हो रहा है...", - "app.error": "त्रुटि: {message}", - "app.requestFailed": "अनुरोध विफल हुआ", - "app.resizeChats": "चैट सूची की चौड़ाई बदलें", - "app.resizeComposer": "इनपुट क्षेत्र की ऊँचाई बदलें", - "newChat.title": "नया चैट", - "newChat.provider": "प्रदाता", - "newChat.mode": "मोड (मॉडल)", - "newChat.modeHint": "चैट बनाते समय मोड तय हो जाता है। बाद में बदलने के लिए ज़रूरी मोड के साथ नया चैट बनाएं।", - "newChat.chatTitle": "चैट शीर्षक (वैकल्पिक)", - "newChat.chatTitlePlaceholder": "उदाहरण: auth refactor", - "newChat.workspace": "प्रोजेक्ट फ़ोल्डर", - "newChat.workspacePlaceholder": "/Users/.../project या ~/Projects/new-thing", - "newChat.browse": "📁 ब्राउज़", - "newChat.up": "↑ ऊपर", - "newChat.home": "🏠 होम", - "newChat.newFolder": "➕ नया फ़ोल्डर", - "newChat.hidden": "छिपे हुए", - "newChat.pickFolder": "यह फ़ोल्डर चुनें", - "newChat.newFolderPlaceholder": "नए फ़ोल्डर का नाम", - "newChat.create": "बनाएं", - "newChat.cancel": "रद्द करें", - "newChat.createFolder": "अगर फ़ोल्डर मौजूद नहीं है तो बनाएं (केवल आपके $HOME के अंदर)", - "newChat.submit": "चैट बनाएं", - "newChat.emptyFolderName": "नाम दर्ज करें।", - "newChat.defaultProject": "डिफ़ॉल्ट", - "newChat.truncated": "सभी फ़ोल्डर नहीं दिखाए गए। \"छिपे हुए\" चालू करें या ऊपर वाला फ़ोल्डर खोलें।", - "newChat.folderCount": "फ़ोल्डर: {total}{suffix}", - "newChat.hiddenSuffix": " (छिपे हुए .फ़ोल्डर - \"छिपे हुए\" चेकबॉक्स)", - "newChat.folderShown": "{total} में से {shown} फ़ोल्डर दिख रहे हैं", - "newChat.tooManyFolders": "(बहुत अधिक फ़ोल्डर - पथ छोटा करें या \"छिपे हुए\" चालू करें)", - "newChat.noSubfolders": "(कोई सबफ़ोल्डर नहीं - इस फ़ोल्डर को \"चुनें\" से चुना जा सकता है)", - "newChat.truncatedInline": "{total} में से पहले {shown} दिख रहे हैं। पथ छोटा करें या \"छिपे हुए\" चालू करें।", - "newChat.creating": "चैट बनाई जा रही है...", - "provider.connected": "✓ कनेक्टेड", - "provider.connectedTitle": "आप साइन इन हैं। दूसरा खाता उपयोग करने के लिए क्लिक करें", - "provider.authorize": "🔑 अधिकृत करें", - "provider.authorizeTitle": "साइन इन आवश्यक है। साइन इन करने के लिए क्लिक करें", - "provider.connectConfirm": "{label} कनेक्ट करें?\n\nब्राउज़र विंडो खुलेगी। साइट पर साइन इन करें; लॉगिन के बाद विंडो बंद हो जाएगी।", - "provider.chatgptConnectConfirm": "{label} को कनेक्ट करें?\n\nविश्वसनीय साइन-इन के लिए सामान्य Chrome विंडो एक बार खुलेगी। सक्रिय सत्र सत्यापित होने के बाद यह अपने आप बंद हो जाएगी और ChatGPT AI Free के अंदर चलता रहेगा।", - "provider.chatgptEmbedLogin": "Chrome विंडो में साइन-इन पूरा करें। सक्रिय सत्र सत्यापित होने के बाद ही यह अपने आप बंद होगी।", - "provider.chatgptEmbedLoginTimeout": "{label} में साइन-इन का समय समाप्त हो गया। «Chrome से साइन इन करें» दबाकर फिर कोशिश करें।", - "provider.connectedAlert": "{label} कनेक्ट हो गया।", - "provider.tokenMissing": "लॉगिन पूरा हुआ, लेकिन token नहीं मिला। फिर कोशिश करें या चलाएँ: npm run login-{id}", - "provider.connectFailed": "{label} कनेक्ट नहीं हो सका: {message}", - "provider.deepseekFast": "तेज़ सामान्य चैट", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "छवि पहचान", - "provider.qwenDefault": "चैट हेडर में मॉडल चुनें", - "role.assistantDescription": "सामान्य सहायक", - "role.assistant": "सहायक", - "role.assistant.label": "सहायक", - "role.assistant.description": "चैट और तेज़ उत्तरों के लिए सामान्य सहायक।", - "role.prompt_builder.label": "प्रॉम्प्ट बिल्डर", - "role.prompt_builder.description": "कार्य स्पष्ट करता है और अगले चरणों के लिए उपयोगी prompt बनाता है।", - "role.architect.label": "आर्किटेक्ट", - "role.architect.description": "समाधान, मॉड्यूल सीमाएँ, डेटा और जोखिम डिज़ाइन करता है।", - "role.developer.label": "डेवलपर", - "role.developer.description": "implementation, files, steps और technical details सुझाता है।", - "role.tester.label": "टेस्टर", - "role.tester.description": "checks, edge cases, regressions और test scenarios खोजता है।", - "role.reviewer.label": "रिव्यूअर", - "role.reviewer.description": "plan/result को आलोचनात्मक रूप से जाँचता है और कमजोरियाँ ढूँढता है।", - "role.synthesizer.label": "सिंथेसाइज़र", - "role.synthesizer.description": "pipeline outputs को छोटे summary और next steps में जोड़ता है।", - "topbar.model": "मॉडल", - "topbar.role": "pipeline में इस चैट की भूमिका", - "topbar.coderTitle": "एजेंट मोड चालू करें: मॉडल फ़ाइलें बना और संपादित कर सकता है", - "topbar.coder": "🛠 कोडर", - "topbar.coderOn": "🛠 कोडर ON", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ON", - "topbar.pipeline": "फ़्लो", - "topbar.pipelineOn": "फ़्लो ON", - "topbar.hardwareTitle": "ESP / बोर्ड firmware: hardware agent profile चालू करता है", - "topbar.pipelineTitle": "pipeline links के जरिए संदेश भेजें", - "topbar.flow": "फ़्लो", - "topbar.flowTitle": "Pipeline फ़्लो", - "topbar.theme": "थीम बदलें", - "topbar.settings": "सेटिंग्स / अनुमत कमांड", - "topbar.quit": "बाहर — ऐप बंद करें और Chrome बंद करें", - "pipeline.title": "Pipeline फ़्लो", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "हर चैट को भूमिका दें और अगला कदम चुनें।", - "pipeline.empty": "कई चैट बनाएं, फिर उन्हें यहाँ जोड़ें।", - "pipeline.end": "अंत", - "pipeline.user": "उपयोगकर्ता", - "pipeline.model": "मॉडल", - "composer.chooseChat": "बाईं ओर चैट चुनें...", - "composer.message": "{label} को संदेश...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ गहरी सोच", - "composer.thinkingTitle": "गहरी सोच: मॉडल chain-of-thought दिखाता है", - "composer.thinkingRequired": "इस मॉडल के लिए गहरी सोच आवश्यक है", - "composer.search": "🌐 स्मार्ट खोज", - "composer.searchTitle": "स्मार्ट खोज: मॉडल ताज़ा जानकारी के लिए वेब खोज उपयोग करता है", - "composer.attach": "📎 फ़ाइल", - "composer.attachTitle": "पढ़ने के लिए टेक्स्ट फ़ाइल जोड़ें", - "composer.voice": "🎙 आवाज़", - "composer.voiceTitle": "आवाज़ रिकॉर्ड करें और transcript को संदेश में डालें", - "composer.voiceStop": "■ रोकें", - "composer.stop": "■", - "composer.stopTitle": "निष्पादन रोकें", - "composer.voiceInstalling": "Parakeet V3 install हो रहा है। इसमें कुछ मिनट लग सकते हैं...", - "composer.voiceRecording": "आवाज़ रिकॉर्ड हो रही है...", - "composer.voiceTranscribing": "आवाज़ transcribe हो रही है...", - "composer.voiceMissing": "Voice helper installed नहीं है। ai-free-stt को {path} में रखें या AI_FREE_STT_BIN set करें।", - "composer.voiceUnsupported": "यह browser window microphone recording support नहीं करती।", - "composer.voiceNoSpeech": "कोई speech पहचानी नहीं गई।", - "composer.defaultImageQuestion": "इस छवि में क्या है? विस्तार से बताएं।", - "composer.imageQuestionLabel": "(छवि प्रश्न)", - "composer.uploadingImage": "छवि{num} अपलोड और प्रोसेस हो रही है: {name}...", - "composer.thinkingStatus": "सोच रहा है...", - "composer.writingStatus": "जवाब लिख रहा है…", - "composer.backgroundTask": "⚙️ कार्य पृष्ठभूमि में चल रहा है; आप दूसरे चैट पर जा सकते हैं", - "file.svgUnsupported": "SVG (\"{name}\") पहचान के लिए समर्थित नहीं है। इसे PNG या JPG के रूप में सहेजें।", - "file.imageTooLarge": "छवि \"{name}\" बहुत बड़ी है ({mb} MB)। सीमा: 10 MB।", - "file.largeImageConfirm": "\"{name}\" {mb} MB है। बड़ी फ़ाइलें DeepSeek पर अक्सर CONTENT_EMPTY लौटाती हैं।\n\nफिर भी अपलोड करें?", - "file.readFailed": "\"{name}\" पढ़ा नहीं जा सका: {message}", - "file.uploadMissingId": "Upload ने fileId नहीं लौटाया", - "file.qwenImageUnsupported": "AI Free अभी Qwen वेब ट्रांसपोर्ट के माध्यम से चित्र नहीं भेज सकता। चित्र को पूरी तरह संसाधित करने के लिए DeepSeek V4 Vision या ChatGPT चुनें।", - "file.binaryUnsupported": "फ़ाइल \"{name}\" binary है ({ext})। अभी text files और images (PNG/JPG/GIF/WEBP) समर्थित हैं।\n\nPDF और Office documents अभी काम नहीं करते - इनके लिए अलग चरण चाहिए।", - "file.textTooLarge": "फ़ाइल \"{name}\" बहुत बड़ी है ({kb} KB)। text सीमा: {limitKb} KB।", - "file.looksBinary": "फ़ाइल \"{name}\" binary लगती है। अगर यह text है, तो इसे .txt नाम दें।", - "file.remove": "हटाएँ", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "मैंने file{plural} जोड़ी है। इसे पढ़ें और उत्तर में ध्यान रखें:", - "file.promptHeader": "फ़ाइल: {name} ({kb} KB)", - "file.promptQuestion": "मेरा प्रश्न:", - "chat.delete": "चैट हटाएं", - "chat.running": "/code कार्य चल रहा है", - "chat.messages": "{count} संदेश", - "chat.deleteConfirm": "चैट हटाएं?", - "chat.history": "इतिहास: {file}", - "chat.you": "आप", - "chat.assistant": "सहायक", - "chat.reasoningProcess": "विचार प्रक्रिया", - "chat.reasoningThinking": "सोच रहा है…", - "chat.question": "प्रश्न", - "chat.system": "सिस्टम", - "install.title": "टूल इंस्टॉल करें", - "install.approve": "इंस्टॉल", - "install.reject": "रद्द करें", - "install.running": "इंस्टॉलेशन चल रहा है...", - "install.failed": "इंस्टॉलेशन विफल हुआ।", - "settings.title": "सेटिंग्स", - "settings.interface": "इंटरफ़ेस", - "settings.tabLanguage": "भाषा", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "अनुमतियाँ", - "settings.language": "भाषा", - "settings.webSearchDefault": "स्मार्ट खोज को डिफ़ॉल्ट रूप से चालू करें", - "settings.voiceTitle": "Voice input", - "settings.voiceProvider": "Model", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "तैयार", - "settings.voiceMissing": "Installed नहीं", - "settings.voiceInstallHint": "Model और runtime plugin में bundled नहीं हैं। ai-free-stt अलग से install करें या AI_FREE_STT_BIN set करें।", - "settings.languageSaved": "भाषा सहेजी गई। इंटरफ़ेस फिर से लोड हो रहा है...", - "settings.loadFailed": "सेटिंग्स लोड नहीं हो सकीं: {message}", - "settings.low": "कम जोखिम", - "settings.medium": "मध्यम जोखिम", - "settings.high": "उच्च जोखिम", - "settings.apiTitle": "OpenAI-compatible API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "OpenAI-compatible client में Base URL और ज़रूरी provider की Bearer API key डालें। Models: {models}", - "settings.anthropicApiTitle": "Anthropic-compatible API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "Auth header", - "settings.anthropicNote": "Anthropic-compatible client में /v1 के बिना Base URL और वही provider API key डालें। POST /v1/messages समर्थित है। Models: {models}", - "settings.noKey": "Key नहीं बनी", - "settings.keyCreated": "Key बन गई", - "settings.createKey": "बनाएं", - "settings.keyReady": "{label} API key तैयार है", - "settings.keyCreateFailed": "{label} API key नहीं बन सकी: {message}", - "settings.saveFailed": "सहेजा नहीं जा सका: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "डार्क", - "theme.light": "लाइट", - "theme.contrast": "कॉन्ट्रास्ट", - "theme.title": "थीम: {label}", - "shutdown.title": "CLI बंद हो गया", - "shutdown.sub": "सर्वर जवाब नहीं दे रहा। विंडो अपने आप बंद हो जाएगी।", - "shutdown.gracefulTitle": "ai-free बंद हो रहा है…", - "shutdown.stoppingTasks": "पृष्ठभूमि कार्य रोक रहे हैं…", - "shutdown.closingBrowsers": "Chrome बंद कर रहे हैं (ChatGPT / Qwen)…", - "shutdown.closingServer": "सर्वर बंद कर रहे हैं…", - "shutdown.stopped": "बंद हो गया", - "shutdown.stoppedSub": "विंडो अपने आप बंद हो जाएगी।", - "welcome.title": "AI Free में आपका स्वागत है", - "welcome.chooseProviders": "वे AI प्रदाता चुनें जिन्हें आप कनेक्ट करना चाहते हैं।", - "welcome.multi": "एक या कई चुनें। बाद में Settings में और जोड़ सकते हैं।", - "welcome.prompt1": "कॉमा से अलग नंबर दर्ज करें (जैसे \"1\" या \"1,2\"),", - "welcome.prompt2": "या DeepSeek को डिफ़ॉल्ट रखने के लिए Enter दबाएँ:", - "welcome.invalid": "⚠️ चुनाव समझ नहीं आया। DeepSeek डिफ़ॉल्ट रूप से उपयोग हो रहा है।", - "welcome.connecting": "कनेक्ट हो रहा है: {providers}", - "welcome.loginFailed": "❌ {provider} कनेक्ट नहीं हो सका: {message}", - "welcome.retryLater": "आप बाद में चैट विंडो की Settings से फिर कोशिश कर सकते हैं।", - "welcome.done": "✅ हो गया। चैट विंडो शुरू हो रही है...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/hi.mjs"; diff --git a/src/i18n/languages/pt.mjs b/src/i18n/languages/pt.mjs index ff9cf0f..9da178e 100644 --- a/src/i18n/languages/pt.mjs +++ b/src/i18n/languages/pt.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "pt", - name: "Português", - dir: "ltr", - messages: { - "app.workspace": "Área de trabalho", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "Atualizar", - "app.newChat": "+ Novo chat", - "app.noChat": "Nenhum chat selecionado", - "app.createChatHint": "Crie um chat à esquerda. Cada chat pode ser um projeto ou contexto de trabalho separado.", - "app.firstMessage": "Escreva a primeira mensagem para este projeto.", - "app.close": "Fechar", - "app.loading": "Carregando...", - "app.loadingShort": "Carregando...", - "app.error": "Erro: {message}", - "app.requestFailed": "A solicitação falhou", - "app.resizeChats": "Redimensionar lista de chats", - "app.resizeComposer": "Redimensionar área de entrada", - "newChat.title": "Novo chat", - "newChat.provider": "Provedor", - "newChat.mode": "Modo (modelo)", - "newChat.modeHint": "O modo fica fixo ao criar o chat. Para trocar depois, crie um novo chat com o modo desejado.", - "newChat.chatTitle": "Título do chat (opcional)", - "newChat.chatTitlePlaceholder": "Exemplo: refatoração auth", - "newChat.workspace": "Pasta do projeto", - "newChat.workspacePlaceholder": "/Users/.../project ou ~/Projects/new-thing", - "newChat.browse": "📁 Procurar", - "newChat.up": "↑ Acima", - "newChat.home": "🏠 Início", - "newChat.newFolder": "➕ Nova pasta", - "newChat.hidden": "Ocultos", - "newChat.pickFolder": "Selecionar esta pasta", - "newChat.newFolderPlaceholder": "Nome da nova pasta", - "newChat.create": "Criar", - "newChat.cancel": "Cancelar", - "newChat.createFolder": "Criar a pasta se ela não existir (somente dentro do seu $HOME)", - "newChat.submit": "Criar chat", - "newChat.emptyFolderName": "Digite um nome.", - "newChat.defaultProject": "padrão", - "newChat.truncated": "Nem todas as pastas são exibidas. Ative \"Ocultas\" ou abra a pasta superior.", - "newChat.folderCount": "Pastas: {total}{suffix}", - "newChat.hiddenSuffix": " (pastas . ocultas - caixa \"Ocultas\")", - "newChat.folderShown": "Mostrando {shown} de {total} pastas", - "newChat.tooManyFolders": "(pastas demais - refine o caminho ou ative \"Ocultas\")", - "newChat.noSubfolders": "(sem subpastas - você pode selecionar esta pasta com \"Selecionar\")", - "newChat.truncatedInline": "Mostrando as primeiras {shown} de {total}. Refine o caminho ou ative \"Ocultas\".", - "newChat.creating": "Criando chat...", - "provider.connected": "✓ Conectado", - "provider.connectedTitle": "Você está conectado. Clique para usar outra conta", - "provider.authorize": "🔑 Autorizar", - "provider.authorizeTitle": "Login necessário. Clique para entrar", - "provider.connectConfirm": "Conectar {label}?\n\nUma janela do navegador será aberta. Faça login no site; a janela fechará depois.", - "provider.chatgptConnectConfirm": "Conectar {label}?\n\nUma janela normal do Chrome será aberta uma vez para um login confiável. Ela será fechada automaticamente após a verificação da sessão ativa, e o ChatGPT continuará dentro do AI Free.", - "provider.chatgptEmbedLogin": "Conclua o login na janela do Chrome. Ela será fechada automaticamente somente após a verificação da sessão ativa.", - "provider.chatgptEmbedLoginTimeout": "O tempo de login em {label} expirou. Clique em «Entrar com o Chrome» e tente novamente.", - "provider.connectedAlert": "{label} conectado.", - "provider.tokenMissing": "O login terminou, mas nenhum token foi encontrado. Tente novamente ou execute: npm run login-{id}", - "provider.connectFailed": "Não foi possível conectar {label}: {message}", - "provider.deepseekFast": "chat normal rápido", - "provider.deepseekExpert": "raciocínio / R1", - "provider.deepseekVision": "reconhecimento de imagens", - "provider.qwenDefault": "escolha o modelo no cabeçalho do chat", - "role.assistantDescription": "Assistente normal", - "role.assistant": "Assistente", - "role.assistant.label": "Assistente", - "role.assistant.description": "Assistente normal para chat e respostas rápidas.", - "role.prompt_builder.label": "Construtor de prompts", - "role.prompt_builder.description": "Esclarece a tarefa e a transforma em um prompt de trabalho para os próximos passos.", - "role.architect.label": "Arquiteto", - "role.architect.description": "Projeta a solução, limites dos módulos, dados e riscos.", - "role.developer.label": "Desenvolvedor", - "role.developer.description": "Propõe implementação, arquivos, passos e detalhes técnicos.", - "role.tester.label": "Testador", - "role.tester.description": "Encontra verificações, casos extremos, regressões e cenários de teste.", - "role.reviewer.label": "Revisor", - "role.reviewer.description": "Verifica criticamente o plano/resultado e procura pontos fracos.", - "role.synthesizer.label": "Sintetizador", - "role.synthesizer.description": "Combina as saídas do pipeline em um resumo curto e próximos passos.", - "topbar.model": "Modelo", - "topbar.role": "Função deste chat no pipeline", - "topbar.coderTitle": "Ativar modo agente: o modelo pode criar e editar arquivos", - "topbar.coder": "🛠 Programador", - "topbar.coderOn": "🛠 Programador ATIVO", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ATIVO", - "topbar.pipeline": "Fluxo", - "topbar.pipelineOn": "Fluxo ON", - "topbar.hardwareTitle": "ESP / firmware de placas: ativa o perfil de agente de hardware", - "topbar.pipelineTitle": "Passar mensagens pelos links do pipeline", - "topbar.flow": "Fluxo", - "topbar.flowTitle": "Fluxo do pipeline", - "topbar.theme": "Alterar tema", - "topbar.settings": "Configurações / comandos permitidos", - "topbar.quit": "Sair — parar o app e fechar o Chrome", - "pipeline.title": "Fluxo do pipeline", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "Atribua uma função a cada chat e escolha o próximo passo.", - "pipeline.empty": "Crie vários chats e conecte-os aqui.", - "pipeline.end": "Fim", - "pipeline.user": "Usuário", - "pipeline.model": "modelo", - "composer.chooseChat": "Escolha um chat à esquerda...", - "composer.message": "Mensagem para {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ Pensamento profundo", - "composer.thinkingTitle": "Pensamento profundo: o modelo mostra a cadeia de raciocínio", - "composer.thinkingRequired": "Pensamento profundo é obrigatório para este modelo", - "composer.search": "🌐 Busca inteligente", - "composer.searchTitle": "Busca inteligente: o modelo usa busca na web para informações atuais", - "composer.attach": "📎 Arquivo", - "composer.attachTitle": "Anexar um arquivo de texto para leitura", - "composer.voice": "🎙 Voz", - "composer.voiceTitle": "Gravar voz e inserir a transcrição na mensagem", - "composer.voiceStop": "■ Parar", - "composer.stop": "■", - "composer.stopTitle": "Parar execução", - "composer.voiceInstalling": "Instalando Parakeet V3. Isso pode levar alguns minutos...", - "composer.voiceRecording": "Gravando voz...", - "composer.voiceTranscribing": "Transcrevendo voz...", - "composer.voiceMissing": "O helper de voz não está instalado. Coloque ai-free-stt em {path} ou defina AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Esta janela do navegador não suporta gravação de microfone.", - "composer.voiceNoSpeech": "Nenhuma fala foi reconhecida.", - "composer.defaultImageQuestion": "O que há nesta imagem? Descreva em detalhes.", - "composer.imageQuestionLabel": "(pergunta sobre imagem)", - "composer.uploadingImage": "Enviando e processando imagem{num}: {name}...", - "composer.thinkingStatus": "Pensando...", - "composer.writingStatus": "Escrevendo resposta…", - "composer.backgroundTask": "⚙️ A tarefa está rodando em segundo plano; você pode mudar para outro chat", - "file.svgUnsupported": "SVG (\"{name}\") não é suportado para reconhecimento. Salve como PNG ou JPG.", - "file.imageTooLarge": "A imagem \"{name}\" é grande demais ({mb} MB). Limite: 10 MB.", - "file.largeImageConfirm": "\"{name}\" tem {mb} MB. Arquivos grandes frequentemente retornam CONTENT_EMPTY no DeepSeek.\n\nEnviar mesmo assim?", - "file.readFailed": "Não foi possível ler \"{name}\": {message}", - "file.uploadMissingId": "O upload retornou sem fileId", - "file.qwenImageUnsupported": "O AI Free ainda não pode enviar imagens pelo transporte web do Qwen. Selecione DeepSeek V4 Vision ou ChatGPT para processar a imagem.", - "file.binaryUnsupported": "O arquivo \"{name}\" é binário ({ext}). Atualmente há suporte a arquivos de texto e imagens (PNG/JPG/GIF/WEBP).\n\nPDFs e documentos Office ainda não funcionam: precisam de uma fase separada.", - "file.textTooLarge": "O arquivo \"{name}\" é grande demais ({kb} KB). Limite para texto: {limitKb} KB.", - "file.looksBinary": "O arquivo \"{name}\" parece binário. Se for texto, renomeie para .txt.", - "file.remove": "Remover", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "Anexei arquivo{plural}. Leia e considere na sua resposta:", - "file.promptHeader": "Arquivo: {name} ({kb} KB)", - "file.promptQuestion": "Minha pergunta:", - "chat.delete": "Excluir chat", - "chat.running": "A tarefa /code está em execução", - "chat.messages": "{count} mensagens", - "chat.deleteConfirm": "Excluir chat?", - "chat.history": "Histórico: {file}", - "chat.you": "Você", - "chat.assistant": "Assistente", - "chat.reasoningProcess": "Processo de raciocínio", - "chat.reasoningThinking": "Pensando…", - "chat.question": "Pergunta", - "chat.system": "Sistema", - "install.title": "Instalar ferramenta", - "install.approve": "Instalar", - "install.reject": "Cancelar", - "install.running": "Instalação em andamento...", - "install.failed": "A instalação falhou.", - "settings.title": "Configurações", - "settings.interface": "Interface", - "settings.tabLanguage": "Idioma", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "Permissões", - "settings.language": "Idioma", - "settings.webSearchDefault": "Ativar busca inteligente por padrão", - "settings.voiceTitle": "Entrada de voz", - "settings.voiceProvider": "Modelo", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Pronto", - "settings.voiceMissing": "Não instalado", - "settings.voiceInstallHint": "O modelo e o runtime não vêm no plugin. Instale ai-free-stt separadamente ou defina AI_FREE_STT_BIN.", - "settings.languageSaved": "Idioma salvo. Recarregando a interface...", - "settings.loadFailed": "Não foi possível carregar as configurações: {message}", - "settings.low": "Baixo risco", - "settings.medium": "Risco médio", - "settings.high": "Alto risco", - "settings.apiTitle": "API compatível com OpenAI", - "settings.baseUrl": "URL base", - "settings.apiNote": "Em um cliente compatível com OpenAI, use a URL base e a chave Bearer do provedor necessário. Modelos: {models}", - "settings.anthropicApiTitle": "API compatível com Anthropic", - "settings.anthropicBaseUrl": "URL base", - "settings.anthropicEndpoint": "Endpoint de Messages", - "settings.anthropicAuth": "Cabeçalho de autenticação", - "settings.anthropicNote": "Em um cliente compatível com Anthropic, use a URL base sem /v1 e a mesma chave do provedor. POST /v1/messages é suportado. Modelos: {models}", - "settings.noKey": "Chave não criada", - "settings.keyCreated": "Chave criada", - "settings.createKey": "Criar", - "settings.keyReady": "Chave API de {label} pronta", - "settings.keyCreateFailed": "Não foi possível criar a chave API de {label}: {message}", - "settings.saveFailed": "Não foi possível salvar: {message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "Escuro", - "theme.light": "Claro", - "theme.contrast": "Contraste", - "theme.title": "Tema: {label}", - "shutdown.title": "CLI parado", - "shutdown.sub": "O servidor não responde mais. A janela será fechada automaticamente.", - "shutdown.gracefulTitle": "Parando ai-free…", - "shutdown.stoppingTasks": "Parando tarefas em segundo plano…", - "shutdown.closingBrowsers": "Fechando Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Parando o servidor…", - "shutdown.stopped": "Parado", - "shutdown.stoppedSub": "A janela será fechada automaticamente.", - "welcome.title": "Bem-vindo ao AI Free", - "welcome.chooseProviders": "Escolha os provedores de IA que deseja conectar.", - "welcome.multi": "Escolha um ou vários. Você pode adicionar mais depois em Configurações.", - "welcome.prompt1": "Digite números separados por vírgulas (por exemplo \"1\" ou \"1,2\"),", - "welcome.prompt2": "ou pressione Enter para usar DeepSeek por padrão:", - "welcome.invalid": "⚠️ Não foi possível entender a escolha. Usando DeepSeek por padrão.", - "welcome.connecting": "Conectando: {providers}", - "welcome.loginFailed": "❌ Não foi possível conectar {provider}: {message}", - "welcome.retryLater": "Você pode tentar novamente mais tarde em Configurações na janela de chat.", - "welcome.done": "✅ Pronto. Iniciando a janela de chat...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/pt.mjs"; diff --git a/src/i18n/languages/ru.mjs b/src/i18n/languages/ru.mjs index 61346a6..78d7a6f 100644 --- a/src/i18n/languages/ru.mjs +++ b/src/i18n/languages/ru.mjs @@ -1,315 +1,2 @@ -export const language = { - code: "ru", - name: "Русский", - dir: "ltr", - messages: { - "app.workspace": "Рабочая область", - "sidebar.menu": "Меню", - "sidebar.plugins": "Плагины", - "sidebar.telegram": "Telegram", - "app.refresh": "Обновить", - "app.newChat": "+ Новый чат", - "app.noChat": "Чат не выбран", - "app.createChatHint": "Создай чат слева. Каждый чат можно использовать как отдельный проект или рабочий контекст.", - "app.firstMessage": "Напиши первое сообщение для этого проекта.", - "app.close": "Закрыть", - "app.loading": "Загрузка...", - "app.loadingShort": "Загружаю...", - "app.error": "Ошибка: {message}", - "app.requestFailed": "Запрос не удался", - "app.resizeChats": "Изменить ширину списка чатов", - "app.resizeComposer": "Изменить высоту формы ввода", - "newChat.title": "Новый чат", - "newChat.provider": "Провайдер", - "newChat.mode": "Режим (модель)", - "newChat.modeHint": "Режим зафиксируется при создании чата. Переключить потом нельзя - создавай новый чат в нужном режиме.", - "newChat.chatTitle": "Название чата (опционально)", - "newChat.chatTitlePlaceholder": "Например: рефакторинг auth", - "newChat.workspace": "Папка проекта", - "newChat.workspacePlaceholder": "/Users/.../project или ~/Projects/new-thing", - "newChat.browse": "📁 Обзор", - "newChat.up": "↑ Вверх", - "newChat.home": "🏠 Домой", - "newChat.newFolder": "➕ Новая папка", - "newChat.hidden": "Скрытые", - "newChat.pickFolder": "Выбрать эту папку", - "newChat.newFolderPlaceholder": "Имя новой папки", - "newChat.create": "Создать", - "newChat.cancel": "Отмена", - "newChat.createFolder": "Создать папку, если её ещё нет (только под твоим $HOME)", - "newChat.submit": "Создать чат", - "newChat.emptyFolderName": "Введи имя.", - "newChat.defaultProject": "по умолчанию", - "newChat.truncated": "Показаны не все папки - включи \"Скрытые\" или открой родительскую папку выше.", - "newChat.folderCount": "Папок: {total}{suffix}", - "newChat.hiddenSuffix": " (скрытые .папки - чекбокс \"Скрытые\")", - "newChat.folderShown": "Показано {shown} из {total} папок", - "newChat.tooManyFolders": "(слишком много папок - уточни путь или включи \"Скрытые\")", - "newChat.noSubfolders": "(нет подпапок - можно выбрать эту папку кнопкой \"Выбрать\")", - "newChat.truncatedInline": "Показаны первые {shown} из {total} - сузь путь или включи \"Скрытые\".", - "newChat.creating": "Создаю чат...", - "provider.connected": "✓ Подключено", - "provider.connectedTitle": "Вы авторизованы. Нажмите, если хотите войти под другим аккаунтом", - "provider.authorize": "🔑 Авторизоваться", - "provider.authorizeTitle": "Требуется авторизация. Нажмите, чтобы войти в аккаунт", - "provider.connectConfirm": "Подключить {label}?\n\nОткроется окно браузера - залогинься на сайте. Окно закроется само после входа.", - "provider.chatgptConnectConfirm": "Подключить {label}?\n\nДля надёжного входа один раз откроется обычный Chrome. После проверки активной сессии окно закроется автоматически, а ChatGPT продолжит работать внутри AI Free.", - "provider.chatgptEmbedLogin": "Завершите вход в открывшемся окне Chrome. Оно закроется автоматически только после проверки активной сессии.", - "provider.chatgptEmbedLoginTimeout": "Время ожидания входа в {label} истекло. Нажмите «Войти через Chrome» и повторите вход.", - "provider.connectedAlert": "{label} подключён.", - "provider.tokenMissing": "Логин завершён, но токен не найден. Попробуй ещё раз или: npm run login-{id}", - "provider.connectFailed": "Не удалось подключить {label}: {message}", - "provider.deepseekFast": "быстрый обычный чат", - "provider.deepseekExpert": "reasoning / R1", - "provider.deepseekVision": "распознавание изображений", - "provider.qwenDefault": "выбор модели в шапке чата", - "role.assistantDescription": "Обычный помощник", - "role.assistant": "Ассистент", - "role.assistant.label": "Ассистент", - "role.assistant.description": "Обычный помощник для чата и быстрых ответов.", - "role.prompt_builder.label": "Конструктор промптов", - "role.prompt_builder.description": "Уточняет задачу и превращает её в рабочий промпт для следующих шагов.", - "role.architect.label": "Архитектор", - "role.architect.description": "Проектирует решение, границы модулей, данные и риски.", - "role.developer.label": "Разработчик", - "role.developer.description": "Предлагает реализацию, файлы, шаги и технические детали.", - "role.tester.label": "Тестировщик", - "role.tester.description": "Ищет проверки, edge cases, регрессии и сценарии тестирования.", - "role.reviewer.label": "Ревьюер", - "role.reviewer.description": "Критически проверяет план/результат и ищет слабые места.", - "role.synthesizer.label": "Синтезатор", - "role.synthesizer.description": "Собирает выводы цепочки в короткий итог и следующие шаги.", - "topbar.model": "Модель", - "topbar.role": "Роль этого чата в pipeline", - "topbar.coderTitle": "Включить режим агента - модель сама создаёт/редактирует файлы", - "topbar.coder": "🛠 Кодер", - "topbar.coderOn": "🛠 Кодер ВКЛ", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP ВКЛ", - "topbar.pipeline": "Цепочка", - "topbar.pipelineOn": "Цепочка ВКЛ", - "topbar.hardwareTitle": "ESP / прошивка плат - включает аппаратный профиль агента", - "topbar.pipelineTitle": "Передавать сообщения по связям pipeline", - "topbar.memoryTitle": "Долговременная память агента — прошлые ошибки и решения", - "topbar.memory": "🧠 Память", - "topbar.memoryOn": "🧠 Память ВКЛ", - "topbar.autoSkillTitle": "Автоматически подбирать skill по задаче", - "topbar.autoSkill": "Skill авто", - "topbar.autoSkillOn": "Skill авто ВКЛ", - "topbar.skillTitle": "Skill для code-agent в этом чате", - "topbar.skillNone": "Skill: авто", - "topbar.flow": "Схема", - "topbar.flowTitle": "Схема цепочки", - "topbar.theme": "Сменить тему", - "topbar.settings": "Настройки / разрешённые команды", - "topbar.quit": "Выход — остановить приложение и закрыть Chrome", - "pipeline.title": "Схема цепочки", - "pipeline.makeLeader": "Сделать текущий чат главным", - "pipeline.addAgent": "+ Добавить подчинённого агента", - "pipeline.leaderSet": "Главный агент: {title}", - "pipeline.rolePrompt": "Роль нового агента: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Агент добавлен: {title}", - "agentDrawer.title": "Агент: память и skills", - "agentDrawer.sub": "Режимы, память, skills, браузер workspace", - "agentDrawer.tabAgent": "Агент", - "agentDrawer.tabBrowser": "Браузер", - "agentDrawer.modes": "Режимы", - "agentDrawer.memorySkills": "Память и skills", - "agentDrawer.hint": "🌐 Web — DeepSeek/Qwen (headless). /code: browser_navigate, browser_click. 📌 ChatGPT — отдельный Chrome.", - "pipeline.sub": "Задай роль каждому чату и выбери следующий шаг.", - "pipeline.empty": "Создай несколько чатов, затем свяжи их здесь.", - "pipeline.end": "Конец", - "pipeline.user": "Пользователь", - "pipeline.model": "модель", - "composer.chooseChat": "Выбери чат слева...", - "composer.message": "Сообщение {label}...", - "composer.coderActive": "Режим Coder: опишите задачу для code-agent…", - "composer.thinking": "⚛ Глубокое мышление", - "composer.thinkingTitle": "Глубокое мышление - модель показывает chain-of-thought", - "composer.thinkingRequired": "Глубокое мышление обязательно для этой модели", - "composer.search": "🌐 Умный поиск", - "composer.searchTitle": "Умный поиск - модель использует веб-поиск для актуальной инфы", - "composer.attach": "📎 Файл", - "composer.attachTitle": "Прикрепить текстовый файл для чтения", - "composer.voice": "🎙 Голос", - "composer.voiceTitle": "Записать голос и вставить расшифровку в сообщение", - "composer.voiceStop": "■ Стоп", - "composer.stop": "■", - "composer.stopTitle": "Остановить выполнение", - "composer.voiceInstalling": "Устанавливаю Parakeet V3. Это может занять несколько минут...", - "composer.voiceRecording": "Идёт запись голоса...", - "composer.voiceTranscribing": "Расшифровываю голос...", - "composer.voiceMissing": "Голосовой helper не установлен. Поставь ai-free-stt в {path} или укажи AI_FREE_STT_BIN.", - "composer.voiceUnsupported": "Браузерное окно не поддерживает запись микрофона.", - "composer.voiceNoSpeech": "Не получилось распознать речь.", - "composer.defaultImageQuestion": "Что на этом изображении? Опиши подробно.", - "composer.imageQuestionLabel": "(вопрос по изображению)", - "composer.uploadingImage": "Заливаю и обрабатываю изображение{num}: {name}...", - "composer.thinkingStatus": "Думаю...", - "composer.writingStatus": "Пишет ответ…", - "composer.backgroundTask": "⚙️ Задача выполняется в фоне - можно перейти в другой чат", - "file.svgUnsupported": "SVG (\"{name}\") не поддерживается для распознавания. Сохрани как PNG или JPG.", - "file.imageTooLarge": "Картинка \"{name}\" слишком большая ({mb} МБ). Лимит 10 МБ.", - "file.largeImageConfirm": "\"{name}\" - {mb} МБ. Большие файлы часто получают CONTENT_EMPTY на DeepSeek.\n\nЗагрузить всё равно?", - "file.readFailed": "Не удалось прочитать \"{name}\": {message}", - "file.uploadMissingId": "Загрузка вернулась без fileId", - "file.qwenImageUnsupported": "AI Free пока не может передать изображение в веб-транспорт Qwen. Выберите DeepSeek V4 Vision или ChatGPT — там картинка будет обработана полностью.", - "file.binaryUnsupported": "Файл \"{name}\" - бинарный ({ext}). Сейчас поддерживаются текстовые файлы и изображения (PNG/JPG/GIF/WEBP).\n\nPDF и Office-документы пока не работают - для них нужна отдельная фаза.", - "file.textTooLarge": "Файл \"{name}\" слишком большой ({kb} КБ). Лимит {limitKb} КБ для текстовых.", - "file.looksBinary": "Файл \"{name}\" похож на бинарный. Если уверен, что текстовый - переименуй в .txt.", - "file.remove": "Удалить", - "file.sizeKb": "{kb} КБ", - "file.promptPrefix": "Я прикрепил файл{plural} - прочитай и учитывай при ответе:", - "file.promptHeader": "Файл: {name} ({kb} КБ)", - "file.promptQuestion": "Мой вопрос:", - "chat.delete": "Удалить чат", - "chat.running": "Выполняется /code-задача", - "chat.messages": "{count} сообщений", - "chat.deleteConfirm": "Удалить чат?", - "chat.history": "История: {file}", - "chat.you": "Вы", - "chat.assistant": "Ассистент", - "chat.reasoningProcess": "Процесс размышления", - "chat.reasoningThinking": "Размышляет…", - "chat.question": "Вопрос", - "chat.system": "Система", - "install.title": "Установить инструмент", - "install.approve": "Установить", - "install.reject": "Отмена", - "install.running": "Установка выполняется...", - "install.failed": "Установка завершилась ошибкой.", - "settings.title": "Настройки", - "settings.agentTitle": "Память и skills", - "settings.memoryDefault": "Память включена для новых чатов", - "settings.memoryDefaultDesc": "Агент ищет прошлые ошибки и решения перед /code-задачей.", - "settings.autoSkillDefault": "Auto-skill для новых чатов", - "settings.autoSkillDefaultDesc": "Подбирает skill по ключевым словам (review, fix, bug…).", - "settings.installedSkills": "Установленные skills", - "settings.noSkills": "Skills не найдены. Встроенные: code-review, bug-fix.", - "settings.installedPlugins": "Плагины (Codex / Claude Code)", - "settings.noPlugins": "Плагины не установлены.", - "settings.installPlugin": "Установить", - "settings.installPluginHint": "Поддержка .codex-plugin/plugin.json и .claude-plugin/plugin.json со skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo или URL GitHub", - "settings.pluginInstalled": "Плагин установлен", - "settings.pluginRemoved": "Плагин удалён", - "settings.uninstallPlugin": "Удалить плагин", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Настройки агента сохранены", - "settings.recentMemory": "Недавняя память", - "settings.recentMemoryHint": "Записи агента для текущего workspace. Можно удалить устаревшие.", - "settings.memoryEmpty": "Память пуста для этого проекта.", - "settings.memoryNoWorkspace": "без workspace", - "settings.deleteMemory": "Удалить запись", - "settings.memoryDeleted": "Запись памяти удалена", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS или JSON fallback)", - "agent.memoryUsed": "Память: использовано {count}", - "agent.graphUsed": "граф: {count}", - "agent.memoryPending": "память сохраняется…", - "agent.memorySaved": "сохранено {count}", - "agent.skillUsed": "skill: {skill}", - "settings.interface": "Интерфейс", - "settings.tabLanguage": "Язык", - "settings.tabAgent": "Агент", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Подключение Telegram", - "settings.telegramHint": "Укажите только токен бота. Chat ID можно оставить пустым: он привяжется автоматически после команды /start в Telegram.", - "settings.telegramEnabled": "Включить Telegram", - "settings.telegramEnabledDesc": "Сохранить настройки подключения.", - "settings.telegramBotToken": "Токен бота", - "settings.telegramChatId": "Chat ID (необязательно)", - "settings.telegramSave": "Сохранить", - "settings.telegramSaved": "Настройки Telegram сохранены", - "settings.tabUpdate": "Обновление", - "settings.tabApi": "API", - "settings.tabPermissions": "Разрешения", - "settings.tabStatus": "Статус", - "health.title": "Статус системы", - "health.refresh": "Обновить", - "health.copyReport": "Скопировать отчёт", - "health.ready": "Готов", - "health.needsLogin": "Нужен вход", - "health.copied": "Диагностический отчёт скопирован", - "health.copyManual": "Выделил отчёт, скопируй вручную", - "settings.language": "Язык", - "settings.webSearchDefault": "Включать умный поиск по умолчанию", - "settings.voiceTitle": "Голосовой ввод", - "settings.voiceProvider": "Модель", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "Готово", - "settings.voiceMissing": "Не установлен", - "settings.voiceInstallHint": "Модель и runtime не входят в плагин. Установи ai-free-stt отдельно или укажи AI_FREE_STT_BIN.", - "settings.languageSaved": "Язык сохранён. Перезагружаю интерфейс...", - "settings.loadFailed": "Не удалось загрузить настройки: {message}", - "settings.low": "Низкий риск", - "settings.medium": "Средний риск", - "settings.high": "Высокий риск", - "settings.apiTitle": "API, совместимое с OpenAI", - "settings.baseUrl": "Базовый URL", - "settings.apiNote": "В OpenAI-compatible клиенте укажи Base URL и Bearer API key нужного провайдера. Модели: {models}", - "settings.anthropicApiTitle": "API, совместимое с Anthropic", - "settings.anthropicBaseUrl": "Базовый URL", - "settings.anthropicEndpoint": "Эндпоинт Messages", - "settings.anthropicAuth": "Заголовок авторизации", - "settings.anthropicNote": "В Anthropic-compatible клиенте укажи Base URL без /v1 и API key того же провайдера. Поддерживается POST /v1/messages. Модели: {models}", - "settings.noKey": "Ключ не создан", - "settings.keyCreated": "Ключ создан", - "settings.createKey": "Создать", - "settings.keyReady": "{label} API key готов", - "settings.keyCreateFailed": "Не удалось создать {label} API key: {message}", - "settings.saveFailed": "Не удалось сохранить: {message}", - "settings.agentPermissions": "Разрешения агентов", - "settings.allowPythonModuleAndEval": "Разрешить python -m и python -c", - "settings.allowPythonModuleAndEvalDesc": "Позволяет агенту запускать Python-модули и inline-код. Включай только для доверенных проектов.", - "settings.allowShell": "Разрешить shell-команды (run_shell)", - "settings.allowShellDesc": "Пайпы, &&, перенаправления: grep -r foo . | head, find … | xargs и т.д.", - "permission.title": "Нужно разрешение", - "permission.description": "Агент запросил действие, которое отключено в настройках безопасности.", - "permission.settingsHint": "Можно включить это сейчас или позже в Settings → Разрешения.", - "permission.approve": "Включить", - "permission.reject": "Не включать", - "permission.enabled": "Разрешение включено. Повтори задачу.", - - "update.title": "Обновление десктопной версии", - "update.notChecked": "Проверка ещё не выполнялась.", - "update.check": "Проверить", - "update.install": "Обновить", - "update.checking": "Проверяю GitHub...", - "update.available": "Доступна новая версия.", - "update.upToDate": "Установлена актуальная версия.", - "update.gitRequired": "Новая версия есть, но автообновление доступно только для git-установки.", - "update.checkFailed": "Не удалось проверить обновление: {message}", - "update.installing": "Обновляю через git. Если npm доступен, зависимости установятся автоматически...", - "update.installed": "Обновление установлено. Перезапусти AI Free.", - "update.installFailed": "Не удалось обновить: {message}", - "update.confirm": "Запустить обновление AI Free?\n\nБудет выполнено: git pull --ff-only и npm install. Чаты в ~/.deepseek-cli/state.json не удаляются.", - "update.note": "Обновляется только код приложения в папке проекта. Чаты, настройки и авторизация хранятся отдельно в ~/.deepseek-cli и ~/.qwen-cli.", - "update.currentVersion": "Текущая", - "update.latestVersion": "Последняя", - "update.projectRoot": "Папка", - - "theme.dark": "Тёмная", - "theme.light": "Светлая", - "theme.contrast": "Контраст", - "theme.title": "Тема: {label}", - "shutdown.title": "CLI остановлен", - "shutdown.sub": "Сервер больше не отвечает. Окно закроется автоматически.", - "shutdown.gracefulTitle": "Останавливаем ai-free…", - "shutdown.stoppingTasks": "Останавливаем фоновые задачи…", - "shutdown.closingBrowsers": "Закрываем Chrome (ChatGPT / Qwen)…", - "shutdown.closingServer": "Останавливаем сервер…", - "shutdown.stopped": "Остановлено", - "shutdown.stoppedSub": "Окно закроется автоматически.", - "welcome.title": "Добро пожаловать в AI Free", - "welcome.chooseProviders": "Выбери AI-провайдеров, которых хочешь подключить.", - "welcome.multi": "Можно один, можно несколько - позже добавишь ещё через Settings.", - "welcome.prompt1": "Введи номера через запятую (например \"1\" или \"1,2\"),", - "welcome.prompt2": "или нажми Enter для DeepSeek по умолчанию:", - "welcome.invalid": "⚠️ Не понял выбор. Использую DeepSeek по умолчанию.", - "welcome.connecting": "Подключаю: {providers}", - "welcome.loginFailed": "❌ Не удалось подключить {provider}: {message}", - "welcome.retryLater": "Можно повторить позже через Settings в окне чатов.", - "welcome.done": "✅ Готово. Запускаю окно чатов...", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/ru.mjs"; diff --git a/src/i18n/languages/zh.mjs b/src/i18n/languages/zh.mjs index adaee8a..c4672ff 100644 --- a/src/i18n/languages/zh.mjs +++ b/src/i18n/languages/zh.mjs @@ -1,313 +1,2 @@ -export const language = { - code: "zh", - name: "中文", - dir: "ltr", - messages: { - "app.workspace": "工作区", - "sidebar.menu": "Menu", - "sidebar.plugins": "Plugins", - "sidebar.telegram": "Telegram", - "app.refresh": "刷新", - "app.newChat": "+ 新聊天", - "app.noChat": "未选择聊天", - "app.createChatHint": "在左侧创建聊天。每个聊天都可以作为单独的项目或工作上下文。", - "app.firstMessage": "为这个项目写第一条消息。", - "app.close": "关闭", - "app.loading": "加载中...", - "app.loadingShort": "正在加载...", - "app.error": "错误:{message}", - "app.requestFailed": "请求失败", - "app.resizeChats": "调整聊天列表宽度", - "app.resizeComposer": "调整输入区域高度", - "newChat.title": "新聊天", - "newChat.provider": "提供商", - "newChat.mode": "模式(模型)", - "newChat.modeHint": "模式在创建聊天时固定。之后如需切换,请用所需模式创建新聊天。", - "newChat.chatTitle": "聊天标题(可选)", - "newChat.chatTitlePlaceholder": "例如:auth 重构", - "newChat.workspace": "项目文件夹", - "newChat.workspacePlaceholder": "/Users/.../project 或 ~/Projects/new-thing", - "newChat.browse": "📁 浏览", - "newChat.up": "↑ 上级", - "newChat.home": "🏠 主页", - "newChat.newFolder": "➕ 新建文件夹", - "newChat.hidden": "隐藏", - "newChat.pickFolder": "选择此文件夹", - "newChat.newFolderPlaceholder": "新文件夹名称", - "newChat.create": "创建", - "newChat.cancel": "取消", - "newChat.createFolder": "如果文件夹不存在则创建(仅限你的 $HOME 下)", - "newChat.submit": "创建聊天", - "newChat.emptyFolderName": "请输入名称。", - "newChat.defaultProject": "默认", - "newChat.truncated": "未显示所有文件夹。启用“隐藏”或打开上级文件夹。", - "newChat.folderCount": "文件夹:{total}{suffix}", - "newChat.hiddenSuffix": "(隐藏的 .文件夹 - “隐藏”复选框)", - "newChat.folderShown": "显示 {shown} / {total} 个文件夹", - "newChat.tooManyFolders": "(文件夹太多 - 缩小路径或启用“隐藏”)", - "newChat.noSubfolders": "(没有子文件夹 - 可用“选择”按钮选择此文件夹)", - "newChat.truncatedInline": "显示前 {shown} / {total} 个。缩小路径或启用“隐藏”。", - "newChat.creating": "正在创建聊天...", - "provider.connected": "✓ 已连接", - "provider.connectedTitle": "你已登录。点击可使用其他账号", - "provider.authorize": "🔑 授权", - "provider.authorizeTitle": "需要登录。点击登录", - "provider.connectConfirm": "连接 {label}?\n\n将打开浏览器窗口。请在网站登录;登录后窗口会关闭。", - "provider.chatgptConnectConfirm": "连接 {label}?\n\n首次可靠登录会打开普通 Chrome 窗口。验证有效会话后窗口将自动关闭,ChatGPT 随后会继续在 AI Free 内运行。", - "provider.chatgptEmbedLogin": "请在 Chrome 窗口中完成登录。只有验证有效会话后,该窗口才会自动关闭。", - "provider.chatgptEmbedLoginTimeout": "登录 {label} 超时。请点击“使用 Chrome 登录”后重试。", - "provider.connectedAlert": "{label} 已连接。", - "provider.tokenMissing": "登录完成,但未找到令牌。请重试或运行:npm run login-{id}", - "provider.connectFailed": "无法连接 {label}:{message}", - "provider.deepseekFast": "快速普通聊天", - "provider.deepseekExpert": "推理 / R1", - "provider.deepseekVision": "图像识别", - "provider.qwenDefault": "在聊天顶部选择模型", - "role.assistantDescription": "普通助手", - "role.assistant": "助手", - "role.assistant.label": "助手", - "role.assistant.description": "用于聊天和快速回答的普通助手。", - "role.prompt_builder.label": "提示词构建器", - "role.prompt_builder.description": "澄清任务并将其转成后续步骤可执行的提示词。", - "role.architect.label": "架构师", - "role.architect.description": "设计方案、模块边界、数据和风险。", - "role.developer.label": "开发者", - "role.developer.description": "提出实现、文件、步骤和技术细节。", - "role.tester.label": "测试者", - "role.tester.description": "寻找检查项、边界情况、回归风险和测试场景。", - "role.reviewer.label": "审查者", - "role.reviewer.description": "批判性检查计划/结果并寻找薄弱点。", - "role.synthesizer.label": "汇总者", - "role.synthesizer.description": "将 pipeline 输出合并为简短总结和下一步。", - "topbar.model": "模型", - "topbar.role": "此聊天在 pipeline 中的角色", - "topbar.coderTitle": "启用代理模式:模型可创建和编辑文件", - "topbar.coder": "🛠 编码器", - "topbar.coderOn": "🛠 编码器开", - "topbar.hardware": "ESP", - "topbar.hardwareOn": "ESP 开", - "topbar.pipeline": "流程", - "topbar.pipelineOn": "流程开", - "topbar.hardwareTitle": "ESP / 板卡固件:启用硬件代理配置", - "topbar.pipelineTitle": "沿 pipeline 连接传递消息", - "topbar.flow": "流程", - "topbar.flowTitle": "Pipeline 流程", - "topbar.theme": "切换主题", - "topbar.settings": "设置 / 允许的命令", - "topbar.quit": "退出 — 停止应用并关闭 Chrome", - "pipeline.title": "Pipeline 流程", - "pipeline.makeLeader": "Make current chat the leader", - "pipeline.addAgent": "+ Add subordinate agent", - "pipeline.leaderSet": "Team leader: {title}", - "pipeline.rolePrompt": "New agent role: assistant, architect, developer, reviewer, tester, researcher", - "pipeline.agentAdded": "Agent added: {title}", - "agentDrawer.title": "Agent: memory & skills", - "agentDrawer.sub": "Modes, memory, skills, workspace browser", - "agentDrawer.tabAgent": "Agent", - "agentDrawer.tabBrowser": "Browser", - "agentDrawer.modes": "Modes", - "agentDrawer.memorySkills": "Memory & skills", - "agentDrawer.hint": "Plugins and full memory list — in Settings → Agent.", - "pipeline.sub": "为每个聊天分配角色并选择下一步。", - "pipeline.empty": "创建多个聊天,然后在这里连接它们。", - "pipeline.end": "结束", - "pipeline.user": "用户", - "pipeline.model": "模型", - "composer.chooseChat": "在左侧选择聊天...", - "composer.message": "发送给 {label}...", - "composer.coderActive": "Coder mode: describe a code-agent task…", - "composer.thinking": "⚛ 深度思考", - "composer.thinkingTitle": "深度思考:模型显示思维链", - "composer.thinkingRequired": "此模型必须启用深度思考", - "composer.search": "🌐 智能搜索", - "composer.searchTitle": "智能搜索:模型使用网页搜索获取最新信息", - "composer.attach": "📎 文件", - "composer.attachTitle": "附加要读取的文本文件", - "composer.voice": "🎙 语音", - "composer.voiceTitle": "录音并把转写插入消息", - "composer.voiceStop": "■ 停止", - "composer.stop": "■", - "composer.stopTitle": "停止执行", - "composer.voiceInstalling": "正在安装 Parakeet V3。这可能需要几分钟...", - "composer.voiceRecording": "正在录音...", - "composer.voiceTranscribing": "正在转写语音...", - "composer.voiceMissing": "未安装语音 helper。请把 ai-free-stt 放到 {path},或设置 AI_FREE_STT_BIN。", - "composer.voiceUnsupported": "此浏览器窗口不支持麦克风录音。", - "composer.voiceNoSpeech": "未识别到语音。", - "composer.defaultImageQuestion": "这张图片里有什么?请详细描述。", - "composer.imageQuestionLabel": "(图片问题)", - "composer.uploadingImage": "正在上传并处理图片{num}:{name}...", - "composer.thinkingStatus": "正在思考...", - "composer.writingStatus": "正在撰写回复…", - "composer.backgroundTask": "⚙️ 任务正在后台运行;你可以切换到其他聊天", - "file.svgUnsupported": "不支持识别 SVG(\"{name}\")。请保存为 PNG 或 JPG。", - "file.imageTooLarge": "图片 \"{name}\" 太大({mb} MB)。限制:10 MB。", - "file.largeImageConfirm": "\"{name}\" 为 {mb} MB。大文件在 DeepSeek 上经常返回 CONTENT_EMPTY。\n\n仍要上传吗?", - "file.readFailed": "无法读取 \"{name}\":{message}", - "file.uploadMissingId": "上传返回时没有 fileId", - "file.qwenImageUnsupported": "AI Free 暂时无法通过 Qwen 网页传输发送图片。请选择 DeepSeek V4 Vision 或 ChatGPT 来完整处理图片。", - "file.binaryUnsupported": "文件 \"{name}\" 是二进制文件({ext})。当前支持文本文件和图片(PNG/JPG/GIF/WEBP)。\n\nPDF 和 Office 文档暂不支持,需要单独阶段。", - "file.textTooLarge": "文件 \"{name}\" 太大({kb} KB)。文本限制:{limitKb} KB。", - "file.looksBinary": "文件 \"{name}\" 看起来像二进制。如果确定是文本,请重命名为 .txt。", - "file.remove": "移除", - "file.sizeKb": "{kb} KB", - "file.promptPrefix": "我附加了文件{plural}。请阅读并在回答中考虑:", - "file.promptHeader": "文件:{name}({kb} KB)", - "file.promptQuestion": "我的问题:", - "chat.delete": "删除聊天", - "chat.running": "/code 任务正在运行", - "chat.messages": "{count} 条消息", - "chat.deleteConfirm": "删除聊天?", - "chat.history": "历史:{file}", - "chat.you": "你", - "chat.assistant": "助手", - "chat.reasoningProcess": "思考过程", - "chat.reasoningThinking": "思考中…", - "chat.question": "问题", - "chat.system": "系统", - "install.title": "安装工具", - "install.approve": "安装", - "install.reject": "取消", - "install.running": "正在安装...", - "install.failed": "安装失败。", - "settings.title": "设置", - "settings.interface": "界面", - "settings.tabLanguage": "语言", - "settings.tabUpdate": "Update", - "settings.tabApi": "API", - "settings.tabPermissions": "权限", - "settings.language": "语言", - "settings.webSearchDefault": "默认启用智能搜索", - "settings.voiceTitle": "语音输入", - "settings.voiceProvider": "模型", - "settings.voiceRuntime": "Runtime", - "settings.voiceReady": "已就绪", - "settings.voiceMissing": "未安装", - "settings.voiceInstallHint": "模型和 runtime 不随插件打包。请单独安装 ai-free-stt,或设置 AI_FREE_STT_BIN。", - "settings.languageSaved": "语言已保存。正在重新加载界面...", - "settings.loadFailed": "无法加载设置:{message}", - "settings.low": "低风险", - "settings.medium": "中等风险", - "settings.high": "高风险", - "settings.apiTitle": "OpenAI 兼容 API", - "settings.baseUrl": "Base URL", - "settings.apiNote": "在 OpenAI 兼容客户端中,填写 Base URL 和对应提供商的 Bearer API key。模型:{models}", - "settings.anthropicApiTitle": "Anthropic 兼容 API", - "settings.anthropicBaseUrl": "Base URL", - "settings.anthropicEndpoint": "Messages endpoint", - "settings.anthropicAuth": "认证 header", - "settings.anthropicNote": "在 Anthropic 兼容客户端中,使用不带 /v1 的 Base URL 和同一个提供商 API key。支持 POST /v1/messages。模型:{models}", - "settings.noKey": "尚未创建密钥", - "settings.keyCreated": "密钥已创建", - "settings.createKey": "创建", - "settings.keyReady": "{label} API key 已就绪", - "settings.keyCreateFailed": "无法创建 {label} API key:{message}", - "settings.saveFailed": "保存失败:{message}", - "settings.agentPermissions": "Agent permissions", - "settings.allowPythonModuleAndEval": "Allow python -m and python -c", - "settings.allowPythonModuleAndEvalDesc": "Lets the agent run Python modules and inline code. Enable only for trusted projects.", - "settings.allowShell": "Allow shell commands (run_shell)", - "settings.allowShellDesc": "Pipes, &&, redirects: grep -r foo . | head, find … | xargs, etc.", - "permission.title": "Permission required", - "permission.description": "The agent requested an action that is disabled by security settings.", - "permission.settingsHint": "You can enable this now or later in Settings → Permissions.", - "permission.approve": "Enable", - "permission.reject": "Do not enable", - "permission.enabled": "Permission enabled. Repeat the task.", - "settings.tabStatus": "Status", - "health.title": "System status", - "health.refresh": "Refresh", - "health.copyReport": "Copy report", - "health.ready": "Ready", - "health.needsLogin": "Needs login", - "health.copied": "Diagnostic report copied", - "health.copyManual": "Report selected, copy it manually", - "update.title": "Desktop version update", - "update.notChecked": "No update check has run yet.", - "update.check": "Check", - "update.install": "Update", - "update.checking": "Checking GitHub...", - "update.available": "A new version is available.", - "update.upToDate": "You are on the latest version.", - "update.gitRequired": "A new version is available, but auto-update requires a git installation.", - "update.checkFailed": "Could not check for updates: {message}", - "update.installing": "Updating with git. If npm is available, dependencies will be installed automatically...", - "update.installed": "Update installed. Restart AI Free.", - "update.installFailed": "Could not update: {message}", - "update.confirm": "Run AI Free update?\n\nThis will run: git pull --ff-only and npm install. Chats in ~/.deepseek-cli/state.json are not deleted.", - "update.note": "Only the app code in the project folder is updated. Chats, settings, and auth are stored separately in ~/.deepseek-cli and ~/.qwen-cli.", - "update.currentVersion": "Current", - "update.latestVersion": "Latest", - "update.projectRoot": "Folder", - "theme.dark": "深色", - "theme.light": "浅色", - "theme.contrast": "高对比", - "theme.title": "主题:{label}", - "shutdown.title": "CLI 已停止", - "shutdown.sub": "服务器不再响应。窗口将自动关闭。", - "shutdown.gracefulTitle": "正在停止 ai-free…", - "shutdown.stoppingTasks": "正在停止后台任务…", - "shutdown.closingBrowsers": "正在关闭 Chrome(ChatGPT / Qwen)…", - "shutdown.closingServer": "正在停止服务器…", - "shutdown.stopped": "已停止", - "shutdown.stoppedSub": "窗口将自动关闭。", - "welcome.title": "欢迎使用 AI Free", - "welcome.chooseProviders": "选择要连接的 AI 提供商。", - "welcome.multi": "可选择一个或多个。之后可在设置中继续添加。", - "welcome.prompt1": "输入用逗号分隔的编号(例如 \"1\" 或 \"1,2\"),", - "welcome.prompt2": "或按 Enter 默认使用 DeepSeek:", - "welcome.invalid": "⚠️ 无法理解选择。默认使用 DeepSeek。", - "welcome.connecting": "正在连接:{providers}", - "welcome.loginFailed": "❌ 无法连接 {provider}:{message}", - "welcome.retryLater": "你可以稍后在聊天窗口的设置中重试。", - "welcome.done": "✅ 完成。正在启动聊天窗口...", - "topbar.memoryTitle": "Agent long-term memory — past errors and fixes", - "topbar.memory": "🧠 Memory", - "topbar.memoryOn": "🧠 Memory ON", - "topbar.autoSkillTitle": "Auto-pick a skill from the task text", - "topbar.autoSkill": "Auto skill", - "topbar.autoSkillOn": "Auto skill ON", - "topbar.skillTitle": "Skill for the code agent in this chat", - "topbar.skillNone": "Skill: auto", - "settings.tabAgent": "Agent", - "settings.tabTelegram": "Telegram", - "settings.telegramTitle": "Telegram connection", - "settings.telegramHint": "Enter bot token and chat id. Outbound notifications from ai-free will be added in a future release.", - "settings.telegramEnabled": "Enable Telegram", - "settings.telegramEnabledDesc": "Save connection settings.", - "settings.telegramBotToken": "Bot token", - "settings.telegramChatId": "Chat ID", - "settings.telegramSave": "Save", - "settings.telegramSaved": "Telegram settings saved", - "settings.agentTitle": "Memory and skills", - "settings.memoryDefault": "Memory enabled for new chats", - "settings.memoryDefaultDesc": "The agent retrieves past errors and fixes before a /code task.", - "settings.autoSkillDefault": "Auto-skill for new chats", - "settings.autoSkillDefaultDesc": "Picks a skill from keywords (review, fix, bug…).", - "settings.installedSkills": "Installed skills", - "settings.noSkills": "No skills found. Built-ins: code-review, bug-fix.", - "settings.installedPlugins": "Plugins (Codex / Claude Code)", - "settings.noPlugins": "No plugins installed yet.", - "settings.installPlugin": "Install", - "settings.installPluginHint": "Supports .codex-plugin/plugin.json and .claude-plugin/plugin.json with skills/SKILL.md.", - "settings.pluginInstallGithub": "user/repo or GitHub URL", - "settings.pluginInstalled": "Plugin installed", - "settings.pluginRemoved": "Plugin removed", - "settings.uninstallPlugin": "Remove plugin", - "settings.pluginSkillCount": "{count} skill(s)", - "settings.skillCommands": "Tools: {commands}", - "settings.agentSaved": "Agent settings saved", - "settings.recentMemory": "Recent memory", - "settings.recentMemoryHint": "Agent notes for the current workspace. Delete stale entries here.", - "settings.memoryEmpty": "No memory entries for this project.", - "settings.memoryNoWorkspace": "no workspace", - "settings.deleteMemory": "Delete entry", - "settings.memoryDeleted": "Memory entry deleted", - "agent.memoryUsed": "Memory used: {count}", - "agent.graphUsed": "graph: {count}", - "agent.memoryPending": "memory saving…", - "agent.memorySaved": "saved {count}", - "agent.skillUsed": "skill: {skill}", - "settings.memoryBackend": "Backend: {backend} (SQLite FTS or JSON fallback)", - }, -}; +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/i18n/languages/zh.mjs"; diff --git a/src/memory/markdown.mjs b/src/memory/markdown.mjs index f634d40..f8df267 100644 --- a/src/memory/markdown.mjs +++ b/src/memory/markdown.mjs @@ -1,95 +1,2 @@ -// Markdown vault — человекочитаемые заметки с YAML frontmatter. - -import fs from "node:fs"; -import path from "node:path"; -import { MEMORY_VAULT } from "./paths.mjs"; - -export function serializeFrontmatter(fields = {}) { - const lines = []; - for (const [key, value] of Object.entries(fields)) { - if (value === undefined || value === null) continue; - if (Array.isArray(value)) { - lines.push(`${key}: [${value.map((v) => JSON.stringify(String(v))).join(", ")}]`); - continue; - } - if (typeof value === "object") { - lines.push(`${key}: ${JSON.stringify(value)}`); - continue; - } - lines.push(`${key}: ${String(value)}`); - } - return `${lines.join("\n")}\n`; -} - -export function parseFrontmatter(text) { - const raw = String(text || ""); - const match = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/); - if (!match) { - return { meta: {}, content: raw.trim() }; - } - - const meta = {}; - for (const line of match[1].split("\n")) { - const idx = line.indexOf(":"); - if (idx <= 0) continue; - const key = line.slice(0, idx).trim(); - let value = line.slice(idx + 1).trim(); - if (value.startsWith("[") && value.endsWith("]")) { - try { - meta[key] = JSON.parse(value.replace(/'/g, '"')); - } catch { - meta[key] = value.slice(1, -1).split(",").map((v) => v.trim().replace(/^"|"$/g, "")); - } - continue; - } - if ((value.startsWith("{") && value.endsWith("}")) || (value.startsWith("[") && value.endsWith("]"))) { - try { meta[key] = JSON.parse(value); continue; } catch {} - } - meta[key] = value; - } - - return { meta, content: match[2].trim() }; -} - -export function writeMemoryMarkdown(item) { - if (!item?.id) return null; - fs.mkdirSync(MEMORY_VAULT, { recursive: true }); - const filePath = path.join(MEMORY_VAULT, `${item.id}.md`); - const frontmatter = serializeFrontmatter({ - id: item.id, - type: item.type, - tags: item.tags || [], - workspace: item.workspace || "", - createdAt: item.createdAt, - updatedAt: item.updatedAt, - }); - fs.writeFileSync(filePath, `---\n${frontmatter}---\n\n${item.content || ""}\n`, "utf8"); - return filePath; -} - -export function readMemoryMarkdown(id) { - const filePath = path.join(MEMORY_VAULT, `${id}.md`); - if (!fs.existsSync(filePath)) return null; - const parsed = parseFrontmatter(fs.readFileSync(filePath, "utf8")); - return normalizeVaultItem(parsed.meta, parsed.content); -} - -export function deleteMemoryMarkdown(id) { - const filePath = path.join(MEMORY_VAULT, `${id}.md`); - if (!fs.existsSync(filePath)) return false; - fs.unlinkSync(filePath); - return true; -} - -function normalizeVaultItem(meta, content) { - return { - id: String(meta.id || ""), - type: String(meta.type || "note"), - content: String(content || ""), - tags: Array.isArray(meta.tags) ? meta.tags : [], - workspace: String(meta.workspace || ""), - meta: {}, - createdAt: String(meta.createdAt || new Date().toISOString()), - updatedAt: String(meta.updatedAt || meta.createdAt || new Date().toISOString()), - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../packages/core/src/memory/markdown.mjs"; diff --git a/src/memory/paths.mjs b/src/memory/paths.mjs index 4f93e16..5bfa411 100644 --- a/src/memory/paths.mjs +++ b/src/memory/paths.mjs @@ -1,19 +1,2 @@ -// Пути хранилища памяти (~/.ai-free/memory/). - -import fs from "node:fs"; -import os from "node:os"; -import path from "node:path"; - -export const MEMORY_BASE = process.env.AI_FREE_MEMORY_DIR - ? path.resolve(process.env.AI_FREE_MEMORY_DIR) - : path.join(os.homedir(), ".ai-free", "memory"); - -export const MEMORY_DB = path.join(MEMORY_BASE, "memory.db"); -export const MEMORY_VAULT = path.join(MEMORY_BASE, "vault"); -export const LEGACY_INDEX = path.join(MEMORY_BASE, "index.json"); -export const MIGRATION_FLAG = path.join(MEMORY_BASE, ".migrated-v2.json"); - -export function ensureMemoryDirs() { - fs.mkdirSync(MEMORY_BASE, { recursive: true }); - fs.mkdirSync(MEMORY_VAULT, { recursive: true }); -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../packages/core/src/memory/paths.mjs"; diff --git a/src/memory/search/fts-query.mjs b/src/memory/search/fts-query.mjs index 79307db..7a4c647 100644 --- a/src/memory/search/fts-query.mjs +++ b/src/memory/search/fts-query.mjs @@ -1,33 +1,2 @@ -// FTS query builder для SQLite FTS5. - -export function buildFtsMatchQuery(query = "") { - const tokens = String(query || "") - .trim() - .split(/\s+/) - .filter(Boolean) - .map((token) => token.replace(/["*]/g, "").trim()) - .filter(Boolean); - - if (!tokens.length) return ""; - - return tokens.map((token) => `"${token.replace(/"/g, '""')}"`).join(" OR "); -} - -export function rankFtsResults(rows, query = "") { - const q = String(query || "").toLowerCase(); - if (!q) return rows; - - return [...rows].sort((a, b) => scoreItem(b, q) - scoreItem(a, q)); -} - -function scoreItem(item, query) { - const content = String(item.content || "").toLowerCase(); - let score = 0; - if (content.includes(query)) score += 4; - for (const token of query.split(/\s+/).filter(Boolean)) { - if (content.includes(token)) score += 1; - if (item.type?.toLowerCase() === token) score += 2; - if (item.tags?.some((tag) => String(tag).toLowerCase() === token)) score += 2; - } - return score; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../../packages/core/src/memory/search/fts-query.mjs"; diff --git a/src/providers/model-catalog.mjs b/src/providers/model-catalog.mjs index d2d4d53..6089723 100644 --- a/src/providers/model-catalog.mjs +++ b/src/providers/model-catalog.mjs @@ -1,189 +1,2 @@ -// Единый каталог моделей для desktop и расширения VS Code. -// Здесь храним и OpenAI-compatible id, и UI-метаданные, чтобы API, ACP и webview -// не расходились между собой после очередного обновления списка моделей. - -export const PROVIDER_CATALOG = { - deepseek: { - id: "deepseek", - label: "DeepSeek", - icon: "DS", - sub: "chat.deepseek.com", - defaultMode: "fast", - defaultModel: "deepseek-v4-flash", - modes: [ - { - id: "fast", - title: "DeepSeek v4 Flash", - sub: "быстрый обычный чат", - model: "deepseek-v4-flash", - }, - { - id: "expert", - title: "DeepSeek v4 Pro", - sub: "reasoning / R1", - model: "deepseek-v4-pro", - reasoning: true, - }, - { - id: "vision", - title: "DeepSeek v4 Vision", - sub: "распознавание изображений", - model: "deepseek-v4-vision", - vision: true, - }, - ], - models: [ - { id: "deepseek-v4-flash", label: "DeepSeek v4 Flash", apiModel: null }, - { id: "deepseek-v4-pro", label: "DeepSeek v4 Pro", apiModel: "expert", reasoning: true }, - { id: "deepseek-v4-vision", label: "DeepSeek v4 Vision", apiModel: "vision", vision: true }, - { id: "deepseek-chat", label: "DeepSeek Chat", apiModel: null, legacy: true }, - { id: "deepseek-reasoner", label: "DeepSeek Reasoner", apiModel: "expert", reasoning: true, legacy: true }, - ], - }, - qwen: { - id: "qwen", - label: "Qwen", - icon: "QW", - sub: "chat.qwen.ai", - defaultMode: "default", - defaultModel: "qwen3.7-plus", - modes: [ - { - id: "default", - title: "Qwen Chat", - sub: "выбор модели в шапке чата", - model: "qwen3.7-plus", - }, - ], - models: [ - { id: "qwen3.8-max", label: "Qwen3.8 Max", sub: "актуальная флагманская модель", reasoning: true, vision: true, search: true }, - { id: "qwen3.7-plus", label: "Qwen3.7 Plus", sub: "default, актуальный web-default" }, - { id: "qwen3.7-max", label: "Qwen3.7 MAX", sub: "мощнее, может требовать доступ" }, - { id: "qwen-latest-series-invite-beta-v24", label: "Qwen3.7 Max Preview", sub: "актуальный preview max" }, - { id: "qwen-latest-series-invite-beta-v16", label: "Qwen3.7 Plus Preview", sub: "актуальный preview plus" }, - { id: "qwen3.6-plus", label: "Qwen3.6 Plus", sub: "стабильный быстрый чат" }, - { id: "qwen3.6-max-preview", label: "Qwen3.6 Max Preview", sub: "предыдущий preview max" }, - { id: "qwen3.6-27b", label: "Qwen3.6 27B", sub: "быстрая средняя модель" }, - { id: "qwen3.6-35b-a3b", label: "Qwen3.6 35B A3B", sub: "MoE-модель" }, - { id: "qwen3.5-plus", label: "Qwen3.5 Plus", sub: "стабильный fallback" }, - { id: "qwen3.5-27b", label: "Qwen3.5 27B", sub: "стабильный fallback" }, - { id: "qwen3.5-35b-a3b", label: "Qwen3.5 35B A3B", sub: "стабильный fallback MoE" }, - { id: "qwen3-max-2026-01-23", label: "Qwen3 Max", sub: "актуальный Qwen3 Max" }, - { id: "qwen3-coder-plus", label: "Qwen3 Coder", sub: "coding model" }, - ], - }, - chatgpt: { - id: "chatgpt", - label: "ChatGPT", - icon: "GP", - sub: "chatgpt.com", - defaultMode: "default", - defaultModel: "gpt-5.5-instant", - modes: [ - { - id: "default", - title: "ChatGPT Web", - sub: "модели chatgpt.com сессии", - model: "gpt-5.5-instant", - }, - ], - models: [ - { id: "gpt-5.5-instant", label: "GPT-5.5 Instant", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "Мгновенный", "ChatGPT", "Auto", "Авто", "Default", "GPT-4o", "GPT-4o mini"] }, - { id: "gpt-5.6-sol-medium", label: "GPT-5.6 Sol · Medium", apiModel: "gpt-5.6-sol-medium", webLabels: ["Medium", "Средний", "Thinking", "Reasoning", "Рассуждения"], reasoning: true }, - { id: "gpt-5.6-sol-high", label: "GPT-5.6 Sol · High", apiModel: "gpt-5.6-sol-high", webLabels: ["High", "Высокий"], reasoning: true }, - { id: "gpt-5.6-sol-extra-high", label: "GPT-5.6 Sol · Extra High", apiModel: "gpt-5.6-sol-extra-high", webLabels: ["Extra High", "Очень высокий"], reasoning: true }, - { id: "gpt-5.6-sol-pro-standard", label: "GPT-5.6 Sol Pro · Standard", apiModel: "gpt-5.6-sol-pro-standard", webLabels: ["Pro Standard", "Pro стандартный", "Pro"], reasoning: true }, - { id: "gpt-5.6-sol-pro-extended", label: "GPT-5.6 Sol Pro · Extended", apiModel: "gpt-5.6-sol-pro-extended", webLabels: ["Pro Extended", "Pro расширенный"], reasoning: true }, - { id: "gpt-5.5", label: "GPT-5.5", apiModel: "gpt-5.5-instant", webLabels: ["Instant", "ChatGPT", "GPT-4o", "Default"], legacy: true }, - { id: "gpt-4o", label: "GPT-4o", apiModel: "gpt-4o", webLabels: ["GPT-4o", "4o", "ChatGPT"], legacy: true }, - { id: "gpt-4o-mini", label: "GPT-4o mini", apiModel: "gpt-4o-mini", webLabels: ["GPT-4o mini", "4o mini", "ChatGPT"], legacy: true }, - { id: "o1-mini", label: "o1 mini", apiModel: "o1-mini", webLabels: ["o1-mini", "o1 mini", "o1"], reasoning: true, legacy: true }, - { id: "o3-mini", label: "o3 mini", apiModel: "o3-mini", webLabels: ["o3-mini", "o3 mini", "o3"], reasoning: true, legacy: true }, - ], - }, -}; - -export const OPENAI_COMPAT_MODELS = Object.values(PROVIDER_CATALOG).flatMap((provider) => - provider.models.map((model) => ({ - name: model.id, - provider: provider.id, - model: model.apiModel === undefined ? model.id : model.apiModel, - label: model.label, - reasoning: model.reasoning === true, - vision: model.vision === true, - legacy: model.legacy === true, - })), -); - -export function getProviderCatalog(providerId) { - return PROVIDER_CATALOG[providerId] || null; -} - -export function getProviderIds() { - return Object.keys(PROVIDER_CATALOG); -} - -export function getProviderDefaultModel(providerId, modeId = null) { - const provider = getProviderCatalog(providerId); - if (!provider) return null; - if (modeId) { - const mode = provider.modes.find((item) => item.id === modeId); - if (mode?.model) return mode.model; - } - return provider.defaultModel || provider.models[0]?.id || null; -} - -export function findProviderModel(providerId, modelId) { - const provider = getProviderCatalog(providerId); - if (!provider) return null; - return provider.models.find((model) => model.id === modelId) || null; -} - -export function findModel(name) { - return OPENAI_COMPAT_MODELS.find((model) => model.name === name); -} - -export function modelsList(overrides = {}) { - const models = Object.entries(PROVIDER_CATALOG).flatMap(([providerId, provider]) => { - const providerModels = overrides[providerId]?.models || provider.models; - return providerModels.map((model) => ({ - name: model.id, - provider: providerId, - })); - }); - return { - object: "list", - data: models.map((model) => ({ - id: model.name, - object: "model", - created: 1700000000, - owned_by: model.provider, - })), - }; -} - -export function uiModelCatalog(overrides = {}) { - return { - providers: Object.fromEntries( - Object.entries(PROVIDER_CATALOG).map(([providerId, provider]) => [ - providerId, - (() => { - const override = overrides[providerId] || {}; - const modes = override.modes || provider.modes; - const models = override.models || provider.models; - return { - label: provider.label, - icon: provider.icon, - sub: provider.sub, - defaultMode: provider.defaultMode, - defaultModel: override.defaultModel || provider.defaultModel, - modes: modes.map((mode) => ({ ...mode })), - models: models - .filter((model) => model.legacy !== true) - .map((model) => ({ ...model })), - }; - })(), - ]), - ), - }; -} +// Re-export from @ai-free/core for backward compatibility. +export * from "../../packages/core/src/providers/model-catalog.mjs"; diff --git a/test/architecture.test.mjs b/test/architecture.test.mjs index 709ccbd..9ce7209 100644 --- a/test/architecture.test.mjs +++ b/test/architecture.test.mjs @@ -43,13 +43,13 @@ describe("architecture invariants", () => { assert.equal(pluginSse, desktopSse, "providers/deepseek/sse.mjs"); }); - it("keeps root and VS Code model catalogs in sync", () => { - const rootCatalog = fs.readFileSync(new URL("../src/providers/model-catalog.mjs", import.meta.url), "utf8"); - const pluginCatalog = fs.readFileSync( - new URL("../plugin-for-vscode/src/providers/model-catalog.mjs", import.meta.url), - "utf8", - ); - assert.equal(pluginCatalog, rootCatalog); + it("keeps root and VS Code model catalogs in sync with core", async () => { + const desktop = await import("../src/providers/model-catalog.mjs"); + const plugin = await import("../plugin-for-vscode/src/providers/model-catalog.mjs"); + const core = await import("../packages/core/src/providers/model-catalog.mjs"); + assert.deepEqual(desktop.PROVIDER_CATALOG, core.PROVIDER_CATALOG); + assert.deepEqual(plugin.PROVIDER_CATALOG, core.PROVIDER_CATALOG); + assert.deepEqual(plugin.OPENAI_COMPAT_MODELS, desktop.OPENAI_COMPAT_MODELS); }); it("keeps desktop and VS Code diagnostics in sync", () => { diff --git a/test/core-package.test.mjs b/test/core-package.test.mjs new file mode 100644 index 0000000..ddef801 --- /dev/null +++ b/test/core-package.test.mjs @@ -0,0 +1,102 @@ +import { describe, it } from "node:test"; +import { strict as assert } from "node:assert"; + +import { + PROVIDER_CATALOG, + OPENAI_COMPAT_MODELS, + getProviderCatalog, + getProviderIds, + findModel, + findProviderModel, +} from "../packages/core/src/providers/model-catalog.mjs"; + +import { + LANGUAGES, + DEFAULT_LANGUAGE, + normalizeLanguage, + createTranslator, +} from "../packages/core/src/i18n/index.mjs"; + +import { parseToolCall, extractFirstJsonObject } from "../packages/core/src/code-agent/parser.mjs"; +import { parseFrontmatter, serializeFrontmatter } from "../packages/core/src/memory/markdown.mjs"; +import { buildFtsMatchQuery } from "../packages/core/src/memory/search/fts-query.mjs"; +import { MEMORY_DB, MEMORY_VAULT } from "../packages/core/src/memory/paths.mjs"; + +import * as desktopCatalog from "../src/providers/model-catalog.mjs"; +import * as vscodeCatalog from "../plugin-for-vscode/src/providers/model-catalog.mjs"; +import * as desktopI18n from "../src/i18n/index.mjs"; +import * as vscodeI18n from "../plugin-for-vscode/src/i18n/index.mjs"; +import * as desktopParser from "../src/code-agent/parser.mjs"; +import * as vscodeParser from "../plugin-for-vscode/src/code-agent/parser.mjs"; + +describe("@ai-free/core unified shared package", () => { + it("exports provider catalog and model resolution utilities", () => { + assert.ok(PROVIDER_CATALOG.deepseek, "Core must export deepseek catalog"); + assert.ok(PROVIDER_CATALOG.qwen, "Core must export qwen catalog"); + assert.ok(PROVIDER_CATALOG.chatgpt, "Core must export chatgpt catalog"); + assert.ok(OPENAI_COMPAT_MODELS.length > 10, "Core must export OpenAI-compatible model list"); + assert.equal(getProviderCatalog("deepseek").id, "deepseek"); + assert.deepEqual(getProviderIds(), ["deepseek", "qwen", "chatgpt"]); + assert.ok(findModel("deepseek-v4-pro"), "findModel should locate deepseek-v4-pro"); + assert.ok(findProviderModel("qwen", "qwen3.7-plus"), "findProviderModel should locate qwen3.7-plus"); + }); + + it("exports localization across all 9 languages and translator factory", () => { + const langCodes = Object.keys(LANGUAGES); + assert.deepEqual(langCodes.sort(), ["ar", "de", "en", "es", "fr", "hi", "pt", "ru", "zh"].sort()); + assert.equal(DEFAULT_LANGUAGE, "ru"); + assert.equal(normalizeLanguage("RU_ru.UTF-8"), "ru"); + assert.equal(normalizeLanguage("pt-BR"), "pt"); + assert.equal(normalizeLanguage("unknown"), "ru"); + + const ruTrans = createTranslator("ru"); + assert.equal(ruTrans.t("newChat.title"), "Новый чат"); + assert.equal(ruTrans.t("chat.reasoningProcess"), "Процесс размышления"); + + const enTrans = createTranslator("en"); + assert.equal(enTrans.t("newChat.title"), "New chat"); + assert.equal(enTrans.t("chat.reasoningProcess"), "Thought process"); + }); + + it("exports robust code-agent tool call parser", () => { + const text = 'Сейчас я выполню команду.\n```tool_calls\n[{"name": "execute_command", "arguments": {"cmd": "dir"}}]\n```'; + const parsed = parseToolCall(text); + assert.equal(parsed?.tool, "execute_command"); + assert.equal(parsed?.cmd, "dir"); + + const xmlText = '{"path": "test.txt"}'; + const parsedXml = parseToolCall(xmlText); + assert.equal(parsedXml?.tool, "read_file"); + assert.equal(parsedXml?.path, "test.txt"); + + const extracted = extractFirstJsonObject('prefix {"a": 1, "b": "hello"} suffix'); + assert.equal(extracted, '{"a": 1, "b": "hello"}'); + }); + + it("exports memory markdown frontmatter parser and FTS query builder", () => { + const parsed = parseFrontmatter("---\ntitle: Note\ntags: [\"ai\"]\n---\nBody text"); + assert.equal(parsed.meta.title, "Note"); + assert.deepEqual(parsed.meta.tags, ["ai"]); + assert.equal(parsed.content.trim(), "Body text"); + + const serialized = serializeFrontmatter({ title: "Note", tags: ["ai"] }); + assert.ok(serialized.includes("title: Note")); + + const fts = buildFtsMatchQuery("hello world"); + assert.ok(fts.length > 0); + assert.ok(typeof MEMORY_DB === "string"); + assert.ok(typeof MEMORY_VAULT === "string"); + }); + + it("desktop and VS Code re-export wrappers provide 100% parity with core", () => { + assert.deepEqual(desktopCatalog.PROVIDER_CATALOG, PROVIDER_CATALOG); + assert.deepEqual(vscodeCatalog.PROVIDER_CATALOG, PROVIDER_CATALOG); + + assert.equal(desktopI18n.createTranslator("ru").t("newChat.title"), "Новый чат"); + assert.equal(vscodeI18n.createTranslator("ru").t("newChat.title"), "Новый чат"); + + const parsedDesktop = desktopParser.parseToolCall('```json\n{"tool": "run", "arg": 1}\n```'); + const parsedVscode = vscodeParser.parseToolCall('```json\n{"tool": "run", "arg": 1}\n```'); + assert.deepEqual(parsedDesktop, parsedVscode); + }); +}); diff --git a/test/duplicate-inventory.test.mjs b/test/duplicate-inventory.test.mjs index af1e867..4f30116 100644 --- a/test/duplicate-inventory.test.mjs +++ b/test/duplicate-inventory.test.mjs @@ -14,7 +14,11 @@ describe("duplicate module inventory", () => { it("synchronizes all duplicate files with zero unexpected divergences", () => { const inventory = assertInventoryInvariants(); assert.equal(inventory.divergent.length, 0, "No divergent modules should exist"); - assert.ok(inventory.summary.identicalCount >= 150, "Should track at least 150 identical files"); + assert.ok( + inventory.summary.identicalCount + inventory.summary.coreSharedCount >= 150, + "Should track at least 150 synchronized or core-shared files", + ); + assert.ok(inventory.summary.coreSharedCount >= 10, "Should track at least 10 core-shared files"); assert.equal(inventory.summary.platformSpecificCount, KNOWN_PLATFORM_SPECIFIC.size); assert.equal(inventory.summary.desktopOnlyCount, KNOWN_DESKTOP_ONLY.size); assert.equal(inventory.summary.vscodeOnlyCount, KNOWN_VSCODE_ONLY.size);