diff --git a/.github/workflows/test-reusable.yml b/.github/workflows/test-reusable.yml index 8e08c14ae..2d3919380 100644 --- a/.github/workflows/test-reusable.yml +++ b/.github/workflows/test-reusable.yml @@ -12,8 +12,7 @@ on: workflow_call: inputs: ref: - description: - Git ref (tag or SHA) to test. Release workflows pass the + description: Git ref (tag or SHA) to test. Release workflows pass the freshly-pushed staging/production tag here so pretest validates the exact commit the build matrix will check out, not main HEAD at workflow_dispatch time. Defaults to empty (checkout uses its @@ -37,6 +36,30 @@ permissions: contents: read jobs: + i18n-coverage: + if: inputs.run_unit + name: i18n Coverage + runs-on: ubuntu-22.04 + container: + image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 + steps: + - name: Checkout code + uses: actions/checkout@v5 + with: + ref: ${{ inputs.ref }} + fetch-depth: 1 + - name: Cache pnpm store + uses: actions/cache@v5 + with: + path: ~/.local/share/pnpm/store + key: pnpm-store-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} + restore-keys: | + pnpm-store-${{ runner.os }}- + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Verify i18n coverage (missing / extra / drifted / en.ts ↔ chunks) + run: pnpm i18n:check + unit-tests: if: inputs.run_unit name: Frontend Unit Tests @@ -78,9 +101,9 @@ jobs: container: image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 env: - CARGO_INCREMENTAL: '0' + CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: sccache - SCCACHE_GHA_ENABLED: 'true' + SCCACHE_GHA_ENABLED: "true" steps: - name: Checkout code uses: actions/checkout@v5 @@ -136,9 +159,9 @@ jobs: container: image: ghcr.io/tinyhumansai/openhuman_ci:rust-1.93.0 env: - CARGO_INCREMENTAL: '0' + CARGO_INCREMENTAL: "0" RUSTC_WRAPPER: sccache - SCCACHE_GHA_ENABLED: 'true' + SCCACHE_GHA_ENABLED: "true" steps: - name: Checkout code uses: actions/checkout@v5 diff --git a/app/src/components/LanguageSelect.tsx b/app/src/components/LanguageSelect.tsx index 4dbc01609..9f1afffd8 100644 --- a/app/src/components/LanguageSelect.tsx +++ b/app/src/components/LanguageSelect.tsx @@ -16,6 +16,7 @@ const LOCALE_OPTIONS: Array<{ value: Locale; flag: string; label: string }> = [ { value: 'pt', flag: '🇵🇹', label: 'Português' }, { value: 'ru', flag: '🇷🇺', label: 'Русский' }, { value: 'id', flag: '🇮🇩', label: 'Bahasa Indonesia' }, + { value: 'it', flag: '🇮🇹', label: 'Italiano' }, ]; interface LanguageSelectProps { diff --git a/app/src/lib/i18n/I18nContext.tsx b/app/src/lib/i18n/I18nContext.tsx index 13640bebe..e40eaeac2 100644 --- a/app/src/lib/i18n/I18nContext.tsx +++ b/app/src/lib/i18n/I18nContext.tsx @@ -8,6 +8,7 @@ import es from './es'; import fr from './fr'; import hi from './hi'; import id from './id'; +import it from './it'; import pt from './pt'; import ru from './ru'; import type { Locale } from './types'; @@ -29,6 +30,7 @@ const translations: Record> = { pt, ru, id, + it, }; // Locales rendered right-to-left. diff --git a/app/src/lib/i18n/__tests__/I18nContext.test.tsx b/app/src/lib/i18n/__tests__/I18nContext.test.tsx index c240225a5..a81e9a697 100644 --- a/app/src/lib/i18n/__tests__/I18nContext.test.tsx +++ b/app/src/lib/i18n/__tests__/I18nContext.test.tsx @@ -28,6 +28,7 @@ function Probe() { {t('settings.language')} {t('clearData.title')} {t('bootCheck.quit')} + {t('this.key.does.not.exist')} ); } @@ -46,13 +47,15 @@ function renderWithLocale(locale: Locale) { } describe('I18nProvider', () => { - it('serves Indonesian translations with English fallback for missing keys', () => { + it('serves Indonesian translations and falls back to the raw key for unknown keys', () => { renderWithLocale('id'); expect(screen.getByTestId('locale')).toHaveTextContent('id'); expect(screen.getByText('Bahasa')).toBeInTheDocument(); expect(screen.getByText('Bersihkan Data Aplikasi')).toBeInTheDocument(); - expect(screen.getByText('Quit')).toBeInTheDocument(); + expect(screen.getByText('Keluar')).toBeInTheDocument(); + // Unknown keys fall through locale → English → raw key. + expect(screen.getByTestId('missing-key')).toHaveTextContent('this.key.does.not.exist'); }); it('keeps the Simplified Chinese locale complete against English keys', () => { diff --git a/app/src/lib/i18n/__tests__/coverage.test.ts b/app/src/lib/i18n/__tests__/coverage.test.ts new file mode 100644 index 000000000..2fd786912 --- /dev/null +++ b/app/src/lib/i18n/__tests__/coverage.test.ts @@ -0,0 +1,97 @@ +import { describe, expect, it } from 'vitest'; + +import enAggregate from '../en'; + +const CHUNK_COUNT = 5; +const LOCALES = ['zh-CN', 'hi', 'es', 'ar', 'fr', 'bn', 'pt', 'ru', 'id', 'it'] as const; + +interface ChunkModule { + default: Record; +} + +/** + * Eagerly imported chunk modules — Vite turns the glob into a static map at + * build time, so this works in both Vitest and production builds (no dynamic + * import() at runtime, which CLAUDE.md forbids in app/src code). + */ +const chunkModules = import.meta.glob('../chunks/*.ts', { eager: true }); + +function loadChunks(locale: string): Array | null> { + const out: Array | null> = []; + for (let n = 1; n <= CHUNK_COUNT; n++) { + const key = `../chunks/${locale}-${n}.ts`; + const mod = chunkModules[key]; + out.push(mod ? mod.default : null); + } + return out; +} + +function flatten(chunks: Array | null>): Record { + const out: Record = {}; + for (const c of chunks) { + if (!c) continue; + Object.assign(out, c); + } + return out; +} + +function keyToChunk(chunks: Array | null>): Map { + const out = new Map(); + chunks.forEach((c, i) => { + if (!c) return; + for (const k of Object.keys(c)) out.set(k, i + 1); + }); + return out; +} + +const enChunks = loadChunks('en'); +const enFlat = flatten(enChunks); +const enKeyChunk = keyToChunk(enChunks); + +describe('i18n coverage', () => { + it('English aggregate (en.ts) matches the en-N.ts chunks key-for-key', () => { + const enTsKeys = new Set(Object.keys(enAggregate as Record)); + const enChunkKeys = new Set(Object.keys(enFlat)); + const inAggregateOnly = [...enTsKeys].filter(k => !enChunkKeys.has(k)); + const inChunksOnly = [...enChunkKeys].filter(k => !enTsKeys.has(k)); + expect({ inAggregateOnly, inChunksOnly }).toEqual({ inAggregateOnly: [], inChunksOnly: [] }); + }); + + it('has no missing English chunk files', () => { + const missing = enChunks + .map((c, i) => (c == null ? i + 1 : null)) + .filter((n): n is number => n !== null); + expect(missing).toEqual([]); + }); + + it.each(LOCALES)('locale %s has no missing chunk files', locale => { + const missing = loadChunks(locale) + .map((c, i) => (c == null ? i + 1 : null)) + .filter((n): n is number => n !== null); + expect(missing).toEqual([]); + }); + + it.each(LOCALES)('locale %s defines every English key', locale => { + const flat = flatten(loadChunks(locale)); + const missing = Object.keys(enFlat).filter(k => !(k in flat)); + expect(missing).toEqual([]); + }); + + it.each(LOCALES)('locale %s defines no keys absent from English', locale => { + const flat = flatten(loadChunks(locale)); + const extra = Object.keys(flat).filter(k => !(k in enFlat)); + expect(extra).toEqual([]); + }); + + it.each(LOCALES)('locale %s places each key in the same chunk as English', locale => { + const localeKeyChunk = keyToChunk(loadChunks(locale)); + const drift: Array<{ key: string; en: number; locale: number }> = []; + for (const [k, actual] of localeKeyChunk) { + const expected = enKeyChunk.get(k); + if (expected !== undefined && expected !== actual) { + drift.push({ key: k, en: expected, locale: actual }); + } + } + expect(drift).toEqual([]); + }); +}); diff --git a/app/src/lib/i18n/chunks/ar-1.ts b/app/src/lib/i18n/chunks/ar-1.ts index e8aed7de2..f9b8abdef 100644 --- a/app/src/lib/i18n/chunks/ar-1.ts +++ b/app/src/lib/i18n/chunks/ar-1.ts @@ -17,7 +17,7 @@ const ar1: TranslationMap = { 'common.edit': 'تعديل', 'common.create': 'إنشاء', 'common.search': 'بحث', - 'common.loading': 'loading…', + 'common.loading': 'جارٍ التحميل…', 'common.error': 'خطأ', 'common.success': 'نجاح', 'common.back': 'رجوع', @@ -31,9 +31,9 @@ const ar1: TranslationMap = { 'common.yes': 'نعم', 'common.no': 'لا', 'common.ok': 'حسنًا', - 'common.retry': 'Try again', + 'common.retry': 'حاول مرة أخرى', 'common.copy': 'نسخ', - 'common.copied': 'Copied', + 'common.copied': 'تم النسخ', 'common.learnMore': 'معرفة المزيد', 'common.seeAll': 'عرض', 'common.dismiss': 'تجاهل', diff --git a/app/src/lib/i18n/chunks/ar-2.ts b/app/src/lib/i18n/chunks/ar-2.ts index 731ed4b8e..e7daf363a 100644 --- a/app/src/lib/i18n/chunks/ar-2.ts +++ b/app/src/lib/i18n/chunks/ar-2.ts @@ -223,7 +223,7 @@ const ar2: TranslationMap = { 'composio.disableAllTriage': 'تعطيل فرز الذكاء الاصطناعي لجميع المشغّلات', 'composio.triggersStillRecorded': 'تُسجَّل المشغّلات في السجل — لا تُشغَّل دورة LLM.', 'composio.disableSpecificIntegrations': 'تعطيل فرز الذكاء الاصطناعي لتكاملات محددة', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'تم حفظ الإعدادات', 'composio.saveFailed': 'فشل الحفظ. حاول مرة أخرى.', 'cron.title': 'مهام Cron', 'cron.scheduledJobs': 'المهام المجدولة', diff --git a/app/src/lib/i18n/chunks/ar-3.ts b/app/src/lib/i18n/chunks/ar-3.ts index 5c4ad08f8..44d689293 100644 --- a/app/src/lib/i18n/chunks/ar-3.ts +++ b/app/src/lib/i18n/chunks/ar-3.ts @@ -247,9 +247,11 @@ const ar3: TranslationMap = { 'accounts.addModal.allConnected': 'الكل متصل', 'accounts.addModal.title': 'إضافة حساب', 'accounts.respondQueue.empty': 'فارغ', + 'accounts.respondQueue.hide': 'إخفاء قائمة الردود', 'accounts.respondQueue.loadFailed': 'فشل تحميل قائمة الردود', 'accounts.respondQueue.loading': 'جارٍ تحميل القائمة…', 'accounts.respondQueue.pending': 'معلّق', + 'accounts.respondQueue.show': 'إظهار قائمة الردود', 'accounts.respondQueue.title': 'قائمة الردود', 'accounts.webviewHost.almostReady': 'على وشك الجهوزية...', 'accounts.webviewHost.loadTimeout': 'انتهت مهلة تحميل العرض', @@ -266,7 +268,7 @@ const ar3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'النواة غير متصلة', 'app.connectionIndicator.disconnected': 'غير متصل', 'app.connectionIndicator.offline': 'غير متصل بالإنترنت', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'إعادة الاتصال…', 'app.errorFallback.componentStack': 'مكدس المكوّنات', 'app.errorFallback.downloadLatest': 'تنزيل الأحدث', 'app.errorFallback.heading': 'العنوان', @@ -276,7 +278,7 @@ const ar3: TranslationMap = { 'app.errorFallback.tryRecover': 'محاولة الاسترداد', 'app.localAiDownload.installing': 'جارٍ التثبيت...', 'app.localAiDownload.preparing': 'جارٍ التحضير...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'متابعة باستخدام تسجيل الدخول عبر {label}', 'app.openhumanLink.accounts.done': 'تم', 'app.openhumanLink.accounts.intro': 'مقدمة', 'app.openhumanLink.accounts.webviewNote': 'ملاحظة العرض', @@ -304,9 +306,9 @@ const ar3: TranslationMap = { 'app.openhumanLink.notifications.promptHint': 'تلميح الطلب', 'app.openhumanLink.notifications.retry': 'إعادة إرسال إشعار اختبار', 'app.openhumanLink.notifications.send': 'إرسال إشعار اختبار', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'تعذّر الإرسال: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'تم إرسال إشعار اختباري. إذا لم تستلمه، انتقل إلى إعدادات النظام ← الإشعارات ← OpenHuman، فعّل "السماح بالإشعارات"، واضبط نمط الشعار على "مستمر".', 'app.openhumanLink.skipForNow': 'تخطي في الوقت الحالي', 'app.openhumanLink.telegramUnavailable': 'Telegram غير متاح', 'app.openhumanLink.title.accounts': 'ربط تطبيقاتك', @@ -318,7 +320,7 @@ const ar3: TranslationMap = { 'app.persistRehydration.heading': 'العنوان', 'app.persistRehydration.resetCta': 'جارٍ إعادة الضبط…', 'app.persistRehydration.resetting': 'جارٍ إعادة الضبط…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'جارٍ تهيئة OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'حدث خطأ أثناء التحديث.', 'app.update.header.default': 'تحديث', @@ -328,7 +330,7 @@ const ar3: TranslationMap = { 'app.update.header.restarting': 'جارٍ إعادة التشغيل…', 'app.update.later': 'لاحقًا', 'app.update.newVersionReady': 'إصدار جديد جاهز للتثبيت.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': 'تم تنزيل {amount}', 'app.update.progress.installing': 'جارٍ تثبيت الإصدار الجديد…', 'app.update.progress.restarting': 'جارٍ إعادة تشغيل التطبيق…', 'app.update.progress.working': '{percent}%', @@ -343,7 +345,7 @@ const ar3: TranslationMap = { 'channels.discord.linkTokenOnce': 'رمز الربط لمرة واحدة', 'channels.discord.picker.allPermissionsOk': 'البوت يمتلك جميع الأذونات المطلوبة في هذه القناة.', 'channels.discord.picker.botNotInServers': 'البوت ليس في أي خادم', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'الفئة', 'channels.discord.picker.channel': 'قناة', 'channels.discord.picker.checkingPermissions': 'جارٍ التحقق من الأذونات', 'channels.discord.picker.loadingChannels': 'جارٍ تحميل القنوات...', @@ -354,7 +356,7 @@ const ar3: TranslationMap = { 'channels.discord.picker.selectChannel': 'اختر قناة', 'channels.discord.picker.selectServer': 'اختر خادمًا', 'channels.discord.picker.server': 'خادم', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'اختيار الخادم والقناة', 'channels.discord.savedRestartRequired': 'تم حفظ القناة. أعد تشغيل التطبيق لتفعيلها.', 'channels.telegram.connect': 'توصيل', 'channels.telegram.managedDmConnecting': 'جارٍ اتصال الرسائل المباشرة المُدارة', diff --git a/app/src/lib/i18n/chunks/ar-4.ts b/app/src/lib/i18n/chunks/ar-4.ts index 9afd23b9b..d72f81ceb 100644 --- a/app/src/lib/i18n/chunks/ar-4.ts +++ b/app/src/lib/i18n/chunks/ar-4.ts @@ -2,68 +2,68 @@ import type { TranslationMap } from '../types'; // Arabic (العربية) chunk 4/5. Translated from chunks/en-4.ts. const ar4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'موافقة وإلغاء الاشتراك', + 'chat.unsubscribeApproval.approved': '✓ تم إلغاء الاشتراك بنجاح.', 'chat.unsubscribeApproval.denied': '✕ تم رفض الطلب.', 'chat.unsubscribeApproval.deny': 'رفض', 'chat.unsubscribeApproval.processing': 'جارٍ المعالجة...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'طلب إلغاء الاشتراك', 'commandPalette.ariaLabel': 'لوحة الأوامر', 'commandPalette.description': 'الوصف', 'commandPalette.label': 'الأوامر', 'commandPalette.noResults': 'لا توجد نتائج', 'commandPalette.placeholder': 'اكتب أمرًا أو ابحث…', 'commandPalette.searchAria': 'البحث في الأوامر', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'اضغط ؟ لعرض جميع الاختصارات', 'commandPalette.title': 'لوحة الأوامر', 'composio.connect.additionalConfigRequired': 'يلزم إعداد إضافي', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'تسمية النطاق الفرعي لـ Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'اتصال', + 'composio.connect.connectionFailed': 'فشل الاتصال (الحالة: {status}).', 'composio.connect.disconnectFailed': 'فشل قطع الاتصال: {msg}', 'composio.connect.disconnecting': 'جارٍ قطع الاتصال…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'اربط حساب', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'الخاص بك. سنفتح نافذة متصفح، توافق فيها على الوصول، وسيكتشف هذا التطبيق الاتصال تلقائيًا.', + 'composio.connect.isConnected': 'متصل.', + 'composio.connect.manage': 'إدارة', + 'composio.connect.needsSubdomain': 'للاتصال بـ', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'أدخل النطاق الفرعي لـ Atlassian (مثل acme لـ acme.atlassian.net) ثم أعد المحاولة.', + 'composio.connect.oauthComplete': 'بانتظار إكمال OAuth…', 'composio.connect.oauthTimeout': 'انتهت مهلة OAuth', 'composio.connect.permissions': 'الأذونات', 'composio.connect.permissionsDefault': 'القراءة والكتابة مفعّلتان افتراضيًا', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'قد يكشف', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'أذونات وكيل OpenHuman الخاصة يتم التحكم بها أدناه عبر مفاتيح القراءة والكتابة والإدارة.', 'composio.connect.reopenBrowser': 'إعادة فتح المتصفح', 'composio.connect.requestingUrl': 'جارٍ طلب عنوان URL للاتصال…', 'composio.connect.retryConnection': 'إعادة محاولة الاتصال', 'composio.connect.scopeLoadError': 'تعذّر تحميل تفضيلات النطاق: {msg}', 'composio.connect.scopeSaveError': 'تعذّر حفظ نطاق {key}: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'أدخل النطاق الفرعي القصير فقط (مثل "acme")، وليس الرابط الكامل. يجب أن يحتوي فقط على أحرف وأرقام وشُرَط.', 'composio.connect.subdomainRequired': 'يرجى إدخال نطاقك الفرعي في Atlassian للمتابعة.', 'composio.connect.wabaIdLabel': 'تسمية معرف WABA', 'composio.connect.wabaIdRequired': 'يرجى إدخال معرف حساب WhatsApp Business (WABA ID) للمتابعة.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'بانتظار', 'composio.connect.waitingHint': 'تلميح الانتظار', 'composio.triggers.heading': 'المشغّلات', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'الاستماع للأحداث من', + 'composio.triggers.loadError': 'تعذّر تحميل المشغّلات', 'composio.triggers.needsConfiguration': 'يحتاج إلى إعداد', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'لا توجد مشغّلات متاحة حاليًا لـ', 'conversations.taskKanban.moveLeft': 'نقل لليسار', 'conversations.taskKanban.moveRight': 'نقل لليمين', 'conversations.taskKanban.title': 'المهام', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'دور', 'conversations.toolTimeline.workerThread': 'محادثة عامل', 'daemon.serviceBlockingGate.body': 'المحتوى', 'daemon.serviceBlockingGate.downloadHint': 'تلميح التنزيل', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'تنزيل أحدث إصدار', + 'daemon.serviceBlockingGate.retryCore': 'إعادة محاولة Core', 'daemon.serviceBlockingGate.retryFailed': 'فشلت إعادة المحاولة. نزّل أحدث إصدار للتطبيق وحاول مرة أخرى.', 'daemon.serviceBlockingGate.retrying': 'جارٍ إعادة المحاولة...', @@ -71,11 +71,11 @@ const ar4: TranslationMap = { 'home.banners.discordSubtitle': 'وصف Discord', 'home.banners.discordTitle': 'انضم إلى Discord', 'home.banners.earlyBirdDismiss': 'إغلاق لافتة المبكر', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'أول اشتراك.', 'home.banners.earlyBirdOn': 'عرض المبكر نشط', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': 'أول 1,000 مستخدم يحصلون على خصم 60٪.', 'home.banners.earlyBirdUseCode': 'استخدم كود المبكر', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'احصل على اشتراك', 'home.banners.promoCreditsBody': 'وصف رصيد العرض', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'استخدام رصيد العرض', @@ -85,21 +85,21 @@ const ar4: TranslationMap = { 'intelligence.memoryChunk.detail.noEmbedding': 'لا يوجد تضمين', 'intelligence.memoryChunk.letterhead.from': 'من', 'intelligence.memoryChunk.letterhead.to': 'إلى', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOne': 'جزء واحد', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} أجزاء', 'intelligence.memoryChunk.mentioned.heading': 'م ذ ك و ر', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': 'نتيجة {name} {pct} بالمئة', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'عند {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'مُسقَط', 'intelligence.memoryChunk.scoreBars.heading': 'س ب ب ا ل ح ف ظ', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'محفوظ', + 'intelligence.memoryText.entityTypePrefix': 'نوع الكيان', 'intelligence.screenDebug.active': 'نشط', 'intelligence.screenDebug.app': 'التطبيق', 'intelligence.screenDebug.bounds': 'الحدود', 'intelligence.screenDebug.captureAlt': 'نتيجة اختبار التقاط', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'فشل', + 'intelligence.screenDebug.captureSuccess': 'نجاح', 'intelligence.screenDebug.captureTest': 'اختبار الالتقاط', 'intelligence.screenDebug.capturing': 'جارٍ الالتقاط', 'intelligence.screenDebug.frames': 'الإطارات', @@ -121,16 +121,16 @@ const ar4: TranslationMap = { 'intelligence.screenDebug.unknown': 'غير معروف', 'intelligence.screenDebug.visionQueue': 'قائمة انتظار الرؤية', 'intelligence.screenDebug.visionState': 'حالة الرؤية', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': 'لوحة نشطة واحدة عبر المحادثات', + 'intelligence.tasks.activeBoardOther': '{count} لوحات نشطة عبر المحادثات', 'intelligence.tasks.empty': 'لا توجد لوحات مهام للوكيل بعد', 'intelligence.tasks.emptyHint': 'تلميح الفراغ', 'intelligence.tasks.failedToLoad': 'فشل التحميل', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'مباشر', 'intelligence.tasks.loadingBoards': 'جارٍ تحميل لوحات المهام…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'المحادثة {thread}', 'notifications.card.dismiss': 'إغلاق الإشعار', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'الأهمية: {pct}%', 'notifications.center.empty': 'لا توجد إشعارات بعد', 'notifications.center.emptyHint': 'تلميح الفراغ', 'notifications.center.filterAll': 'تصفية الكل', @@ -142,7 +142,7 @@ const ar4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'جارٍ بناء ملفك الشخصي...', 'onboarding.contextGathering.continueToChat': 'المتابعة إلى المحادثة', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'تعذّر إنشاء ملفك الكامل الآن، لكن لا بأس — يمكنك المتابعة وسيُبنى ملفك مع الوقت.', 'onboarding.contextGathering.title': 'جمع السياق', 'openhuman.team_list_teams': 'قائمة الفرق', 'overlay.ariaAttention': 'رسالة انتباه', @@ -181,20 +181,20 @@ const ar4: TranslationMap = { 'privacy.dataKind.diagnostics': 'التشخيص', 'privacy.dataKind.metadata': 'البيانات الوصفية', 'privacy.dataKind.raw': 'خام', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'ما الذي يغادر جهازي؟', + 'rewards.community.achievementsUnlocked': 'تم فتح {unlocked} من {total} إنجازات', 'rewards.community.connectDiscord': 'ربط Discord', 'rewards.community.cumulativeTokens': 'الرموز التراكمية', 'rewards.community.currentStreak': 'السلسلة الحالية', 'rewards.community.discordLinkedNotInGuild': 'Discord مرتبط لكن ليس في السيرفر', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'انضممت إلى الخادم', 'rewards.community.discordNotLinked': 'Discord غير مرتبط', 'rewards.community.discordServer': 'سيرفر Discord', 'rewards.community.discordStatusUnavailable': 'حالة Discord غير متاحة', 'rewards.community.discordWaiting': 'في انتظار Discord', 'rewards.community.heroSubtitle': 'عنوان فرعي للبطل', 'rewards.community.heroTitle': 'عنوان البطل', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'انضم إلى Discord', 'rewards.community.loadingRewards': 'جارٍ تحميل المكافآت…', 'rewards.community.locked': 'مفتوح', 'rewards.community.retrying': 'جارٍ إعادة المحاولة…', @@ -212,20 +212,19 @@ const ar4: TranslationMap = { 'rewards.coupon.colReward': 'المكافأة', 'rewards.coupon.colStatus': 'الحالة', 'rewards.coupon.loadingHistory': 'جارٍ تحميل سجل المكافآت…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'لم يتم استبدال أي رموز مكافآت بعد.', 'rewards.coupon.pending': 'معلّق', 'rewards.coupon.placeholder': 'رمز القسيمة', 'rewards.coupon.promoCredits': 'رصيد عرض ترويجي', 'rewards.coupon.recentRedemptions': 'عمليات الاسترداد الأخيرة', - 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + 'rewards.coupon.redeemAccepted': 'تم قبول {code}. سيتم فتح {amount} بعد إكمال الإجراء المطلوب.', + 'rewards.coupon.redeemButton': 'استبدال الرمز', + 'rewards.coupon.redeemSuccess': 'تم استبدال {code}. تمت إضافة {amount} إلى رصيدك.', 'rewards.coupon.redeemedCodes': 'الرموز المستردة', 'rewards.coupon.redeeming': 'جارٍ الاسترداد...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': 'مُطبَّق', + 'rewards.coupon.statusPendingAction': 'بانتظار إجراء', + 'rewards.coupon.statusRedeemed': 'تم الاستبدال', 'rewards.coupon.subtitle': 'العنوان الفرعي', 'rewards.coupon.title': 'استرداد رمز قسيمة', 'rewards.referralSection.activity': 'نشاط الإحالة', @@ -241,7 +240,7 @@ const ar4: TranslationMap = { 'rewards.referralSection.haveCode': 'هل لديك رمز إحالة؟', 'rewards.referralSection.haveCodeDesc': 'وصف امتلاك الرمز', 'rewards.referralSection.linked': 'مرتبط', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(الرمز {code})', 'rewards.referralSection.loading': 'جارٍ تحميل برنامج الإحالة…', 'rewards.referralSection.noReferrals': 'لا توجد إحالات', 'rewards.referralSection.pendingReferrals': 'الإحالات المعلقة', @@ -254,18 +253,18 @@ const ar4: TranslationMap = { 'rewards.referralSection.title': 'ادعُ أصدقاء واكسب رصيدًا', 'rewards.referralSection.totalEarned': 'إجمالي المكتسب', 'rewards.referralSection.yourCode': 'رمزك', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'إضافة مزود سحابي', 'settings.ai.addProvider': 'جارٍ الحفظ…', 'settings.ai.apiKeyFieldLabel': 'تسمية حقل مفتاح API', 'settings.ai.apiKeyRequired': 'يرجى لصق مفتاح API للمتابعة.', 'settings.ai.apiKeyStoredEncrypted': 'مفتاح API محفوظ مشفّرًا', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'مسح المفتاح المحفوظ', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'ربط مزود', 'settings.ai.customRouting': 'توجيه مخصص', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'تجاهل', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'تعديل المزود', 'settings.ai.llmProviders': 'مزودو LLM', 'settings.ai.llmProvidersDesc': 'وصف مزودي LLM', 'settings.ai.localOllama': 'محلي (Ollama)', @@ -274,12 +273,12 @@ const ar4: TranslationMap = { 'settings.ai.providerLabel': 'المزود', 'settings.ai.routing': 'التوجيه', 'settings.ai.routingCustom': 'توجيه مخصص', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': 'افتراضي', 'settings.ai.routingDesc': 'وصف التوجيه', 'settings.ai.saveChanges': 'جارٍ الحفظ…', 'settings.ai.saving': 'جارٍ الحفظ…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'تغيير غير محفوظ', + 'settings.ai.unsavedChanges': 'تغييرات غير محفوظة', 'settings.ai.workloadGroupBackground': 'مجموعة عبء العمل الخلفي', 'settings.ai.workloadGroupChat': 'مجموعة عبء عمل المحادثة', 'settings.autocomplete.appFilter.acceptSuggestion': 'قبول الاقتراح', @@ -293,9 +292,9 @@ const ar4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'بيئة التشغيل', 'settings.autocomplete.appFilter.test': 'اختبار', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + 'تم تخزين {count} إكمال مقبول — يُستخدم لتخصيص الاقتراحات المستقبلية.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + 'تم تخزين {count} إكمالات مقبولة — تُستخدم لتخصيص الاقتراحات المستقبلية.', 'settings.autocomplete.completionStyle.clearHistory': 'جارٍ المسح…', 'settings.autocomplete.completionStyle.clearing': 'جارٍ المسح…', 'settings.autocomplete.completionStyle.debounce': 'تأخير (ms)', @@ -345,7 +344,7 @@ const ar4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'عنوان رصيد الائتمان', 'settings.billing.payAsYouGo.customAmount': 'مبلغ مخصص', 'settings.billing.payAsYouGo.enterAmount': 'أدخل المبلغ', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'جارٍ الفتح', 'settings.billing.payAsYouGo.promotionalCredits': 'رصيد ترويجي', 'settings.billing.payAsYouGo.topUpBalance': 'شحن الرصيد', 'settings.billing.payAsYouGo.topUpCredits': 'شحن الرصيد', diff --git a/app/src/lib/i18n/chunks/ar-5.ts b/app/src/lib/i18n/chunks/ar-5.ts index f270f1921..ddcda7aeb 100644 --- a/app/src/lib/i18n/chunks/ar-5.ts +++ b/app/src/lib/i18n/chunks/ar-5.ts @@ -6,49 +6,48 @@ const ar5: TranslationMap = { 'settings.billing.subscription.upgrade': 'ترقية', 'settings.billing.subscription.waiting': 'انتظار', 'settings.billing.subscription.waitingPayment': 'في انتظار الدفع', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': 'يتم حاليًا تخزين مفتاح Composio API على هذا الجهاز.', + 'settings.composio.apiKeyLabel': 'مفتاح Composio API', + 'settings.composio.apiKeyStored': 'تم تخزين مفتاح API', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'تم التبديل إلى وضع الخلفية', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', - 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'settings.composio.confirmItem1': 'حساب على app.composio.dev مع مفتاح API', + 'settings.composio.confirmItem2': 'لإعادة ربط كل تكامل عبر حساب Composio الشخصي الخاص بك', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'ملاحظة: مشغّلات Composio (الـ webhooks الفورية) لا تعمل في الوضع المباشر بعد — فقط استدعاءات الأدوات المتزامنة', + 'settings.composio.confirmNeedItems': 'ستحتاج إلى:', + 'settings.composio.confirmSwitch': 'أفهم، التبديل إلى المباشر', + 'settings.composio.confirmTitle': '⚠️ التبديل إلى الوضع المباشر', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'تكاملاتك الحالية (Gmail، Slack، GitHub، إلخ المرتبطة عبر OpenHuman) لن تكون مرئية — فهي موجودة في مستأجر Composio المُدار من OpenHuman.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'يُدمج Composio أكثر من 250 تطبيقًا خارجيًا كأدوات يمكن للوكيل استدعاؤها. اختر كيفية توجيه هذه الاستدعاءات.', 'settings.composio.modeDirect': 'مباشر (استخدم مفتاح API الخاص بك)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'تذهب الاستدعاءات إلى backend.composio.dev مباشرةً. سيادي / مناسب للعمل دون اتصال. تنفيذ الأدوات يعمل بشكل متزامن؛ مشغّلات الـ webhooks الفورية لم تُوجَّه بعد في الوضع المباشر (مشكلة متابعة).', 'settings.composio.modeManaged': 'مُدار (OpenHuman يتولى الأمر نيابةً عنك)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'يقوم OpenHuman بتمرير استدعاءات الأدوات عبر خادمنا الخلفي (موصى به). تتم وساطة المصادقة؛ لن تلصق مفتاح Composio API. الـ webhooks مُوجَّهة بالكامل.', 'settings.composio.routingMode': 'وضع التوجيه', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': 'فشل الحفظ. الوضع المباشر يتطلب مفتاح API غير فارغ.', 'settings.composio.saving': 'جارٍ الحفظ…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'جارٍ التبديل…', 'settings.cron.jobs.desc': 'الوصف', 'settings.cron.jobs.empty': 'لا توجد مهام cron أساسية.', 'settings.cron.jobs.lastStatus': 'آخر حالة', 'settings.cron.jobs.loading': 'جارٍ تحميل مهام cron...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'جارٍ تحميل عمليات التشغيل', 'settings.cron.jobs.nextRun': 'التشغيل التالي', 'settings.cron.jobs.pause': 'إيقاف مؤقت', 'settings.cron.jobs.paused': 'مفعّل', 'settings.cron.jobs.recentRuns': 'التشغيلات الأخيرة', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'جارٍ الإزالة', 'settings.cron.jobs.resume': 'استئناف', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'يعمل الآن', 'settings.cron.jobs.saving': 'جارٍ الحفظ…', 'settings.cron.jobs.schedule': 'الجدول', 'settings.cron.jobs.title': 'مهام Cron الأساسية', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'عرض عمليات التشغيل', 'settings.localModel.deviceCapability.active': 'نشط', 'settings.localModel.deviceCapability.appliedTier': 'المستوى المطبّق', 'settings.localModel.deviceCapability.applying': 'جارٍ التطبيق', @@ -67,10 +66,11 @@ const ar5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'فشل تثبيت Ollama', 'settings.localModel.deviceCapability.installFailedDesc': 'خرج المثبّت قبل أن يصبح Ollama قابلاً للاستخدام. انقر إعادة المحاولة، أو ثبّته يدويًا من ollama.com.', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'شغّل Ollama أولاً.', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'تعتمد المستويات المحلية على نقطة نهاية Ollama مُدارة خارجيًا. شغّلها بنفسك، وحمّل النماذج التي تريدها، واستمر في استخدام "معطّل (التراجع السحابي)" حتى يصبح وقت التشغيل قابلاً للوصول.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'شغّل Ollama أولاً لاستخدام هذا المستوى', 'settings.localModel.deviceCapability.installingOllama': 'جارٍ تثبيت Ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'جارٍ تحميل معلومات الجهاز', 'settings.localModel.deviceCapability.localAiDisabled': @@ -91,8 +91,8 @@ const ar5: TranslationMap = { 'settings.localModel.download.promptPlaceholder': 'اكتب أي طلب وشغّله على النموذج المحلي...', 'settings.localModel.download.quantizationPref': 'تفضيل التكميم', 'settings.localModel.download.runEmbeddingTest': 'جارٍ التشغيل...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'تشغيل اختبار المُوجِّه', + 'settings.localModel.download.runSummaryTest': 'تشغيل اختبار الملخص', 'settings.localModel.download.runTranscriptionTest': 'جارٍ التشغيل...', 'settings.localModel.download.runTtsTest': 'جارٍ التشغيل...', 'settings.localModel.download.runVisionTest': 'جارٍ التشغيل...', @@ -120,11 +120,11 @@ const ar5: TranslationMap = { 'settings.localModel.status.customLocation': 'موقع مخصص', 'settings.localModel.status.customLocationDesc': 'وصف الموقع المخصص', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'انقر "تشغيل التشخيصات" للتحقق من أن Ollama يعمل وأن النماذج مثبتة.', 'settings.localModel.status.downloadingUnknown': 'جارٍ التنزيل (الحجم غير معروف)', 'settings.localModel.status.eta': 'الوقت المتوقع', 'settings.localModel.status.expectedModels': 'النماذج المتوقعة', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'فرض إعادة التهيئة', 'settings.localModel.status.generationTps': 'سرعة التوليد TPS', 'settings.localModel.status.hideErrorDetails': 'إخفاء تفاصيل الخطأ', 'settings.localModel.status.installManually': 'تثبيت يدوي', @@ -134,16 +134,16 @@ const ar5: TranslationMap = { 'settings.localModel.status.installing': 'جارٍ التثبيت...', 'settings.localModel.status.installingOllama': 'جارٍ تثبيت بيئة Ollama...', 'settings.localModel.status.issues': 'المشكلات', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': 'تم العثور على {count} مشكلة', 'settings.localModel.status.lastLatency': 'آخر زمن استجابة', 'settings.localModel.status.model': 'النموذج', 'settings.localModel.status.notFound': 'غير موجود', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'غير قيد التشغيل', 'settings.localModel.status.ollamaBinaryPath': 'مسار ملف Ollama الثنائي', 'settings.localModel.status.ollamaDiagnostics': 'تشخيص Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'وقت تشغيل Ollama غير متاح', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'يعامل OpenHuman الآن Ollama كوقت تشغيل استدلال خارجي. شغّل خادم Ollama الخاص بك، وحمّل النماذج التي تريدها، ووجّه توجيه الأحمال إليه.', 'settings.localModel.status.progress': 'التقدم', 'settings.localModel.status.provider': 'المزود', 'settings.localModel.status.retryBootstrap': 'إعادة محاولة التمهيد', @@ -168,26 +168,26 @@ const ar5: TranslationMap = { 'settings.mascot.colorHeading': 'عنوان اللون', 'settings.mascot.loadingLibrary': 'جارٍ تحميل مكتبة OpenHuman…', 'settings.mascot.localDefault': 'OpenHuman المحلي (افتراضي)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'لا توجد شخصيات OpenHuman متاحة بعد', 'settings.mascot.noColorVariants': 'لا توجد ألوان متاحة', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'موصى به', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'افتراضي معقول — استمرارية جيدة دون استهلاك رموز إضافية في كل تشغيل.', + 'settings.memoryWindow.balanced.label': 'متوازن', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'مقدار السياق المحفوظ الذي يحقنه OpenHuman في كل تشغيل وكيل جديد. النوافذ الأكبر تشعر بإدراك أكثر للمحادثات السابقة لكنها تستخدم رموزًا أكثر — وتكلّف أكثر — في كل تشغيل.', + 'settings.memoryWindow.extended.badge': 'سياق أكثر', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'حقن ذاكرة طويلة المدى أكثر في كل تشغيل. تكلفة رموز أعلى لكل دور.', + 'settings.memoryWindow.extended.label': 'موسّع', + 'settings.memoryWindow.maximum.badge': 'الأعلى تكلفة', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'أكبر نافذة آمنة. أفضل استمرارية، مع فاتورة رموز أعلى بشكل ملحوظ في كل تشغيل.', + 'settings.memoryWindow.maximum.label': 'أقصى', + 'settings.memoryWindow.minimal.badge': 'الأرخص', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'أصغر نافذة ذاكرة. الأرخص والأسرع وأقل استمرارية بين عمليات التشغيل.', + 'settings.memoryWindow.minimal.label': 'الحد الأدنى', 'settings.memoryWindow.title': 'نافذة الذاكرة طويلة الأمد', 'settings.screenIntel.permissions.accessibility': 'إمكانية الوصول', 'settings.screenIntel.permissions.grantHint': 'تلميح المنح', @@ -204,17 +204,17 @@ const ar5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'تسجيل الشاشة', 'settings.screenIntel.permissions.title': 'الأذونات', 'skills.card.moreActions': 'مزيد من الإجراءات', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'الأدوات المسموح بها', + 'skills.create.author': 'المؤلف', 'skills.create.authorPlaceholder': 'اسمك', 'skills.create.commaSeparated': '(مفصولة بفاصلة)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'إنشاء مهارة', 'skills.create.createError': 'تعذّر إنشاء المهارة', 'skills.create.creating': 'جارٍ الإنشاء…', - 'skills.create.description': 'Description', + 'skills.create.description': 'الوصف', 'skills.create.descriptionPlaceholder': 'ما الذي تفعله هذه المهارة؟', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'الترخيص', + 'skills.create.name': 'الاسم', 'skills.create.namePlaceholder': 'مثال: يومية التداول', 'skills.create.scope': 'النطاق', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -222,8 +222,8 @@ const ar5: TranslationMap = { 'مكتوب في ~/.openhuman/skills//SKILL.md — متاح في جميع مساحات العمل.', 'skills.create.slugLabel': 'تسمية المعرف', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'الوسوم', + 'skills.create.title': 'مهارة جديدة', 'skills.detail.allowedTools': 'الأدوات المسموح بها', 'skills.detail.author': 'المؤلف', 'skills.detail.bundledResources': 'الموارد المجمّعة', @@ -240,13 +240,13 @@ const ar5: TranslationMap = { 'skills.install.rawError': 'خطأ خام', 'skills.install.timeoutHint': '(ثوانٍ، اختياري)', 'skills.install.timeoutLabel': 'تسمية المهلة', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'تثبيت مهارة من رابط', + 'skills.install.urlLabel': 'رابط المهارة', 'skills.meetingBots.bannerDesc': 'وصف اللافتة', 'skills.meetingBots.bannerTitle': 'عنوان اللافتة', 'skills.meetingBots.busyTitle': 'OpenHuman مشغول', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'قريبًا', + 'skills.meetingBots.couldNotStartTitle': 'تعذّر بدء OpenHuman', 'skills.meetingBots.displayName': 'الاسم المعروض', 'skills.meetingBots.failedToStart': 'فشل تشغيل OpenHuman.', 'skills.meetingBots.joiningMessage': 'يجب أن يظهر كمشارك في غضون ثوانٍ.', @@ -256,10 +256,10 @@ const ar5: TranslationMap = { 'skills.meetingBots.modalDesc': 'وصف النافذة', 'skills.meetingBots.modalTitle': 'إرسال OpenHuman إلى اجتماع', 'skills.meetingBots.newBadge': 'شارة جديدة', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'إرسال إلى', 'skills.meetingBots.starting': 'جارٍ البدء…', 'skills.resource.preview.closeAriaLabel': 'إغلاق المعاينة', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'فشلت المعاينة', 'skills.resource.preview.loading': 'جارٍ تحميل المعاينة…', 'skills.resource.tree.empty': 'لا توجد موارد مجمّعة.', 'skills.search.placeholder': 'بحث', @@ -327,32 +327,32 @@ const ar5: TranslationMap = { 'skills.setup.voice.sttReady': 'نموذج تحويل الكلام إلى نص جاهز', 'skills.setup.voice.sttReturnHint': 'تلميح العودة لـ STT', 'skills.setup.voice.title': 'ذكاء الصوت', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'تعذّر إلغاء التثبيت', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'هذا يحذف دليل المهارة نهائيًا وجميع موارده المرفقة. سيتوقف الوكيل عن رؤيتها في الدور التالي.', + 'skills.uninstall.title': 'إلغاء التثبيت', + 'skills.uninstall.uninstallBtn': 'إلغاء التثبيت', + 'skills.uninstall.uninstalling': 'جارٍ إلغاء التثبيت…', 'upsell.global.limitMessage': 'قم بترقية خطتك أو أضف رصيدًا للمتابعة', 'upsell.global.limitTitle': 'أنت', 'upsell.global.nearLimitMessage': 'لقد استخدمت {pct}% من حد الاستخدام. قم بالترقية للحصول على حدود أعلى.', 'upsell.global.nearLimitTitle': 'الاقتراب من حد الاستخدام', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'لقد وصلت إلى حدّك الأسبوعي.{reset} قم بترقية خطتك أو شحن الرصيد لتجنّب الحدود.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'لقد وصلت إلى حدّ معدّل الاستدلال لـ 10 ساعات.{reset} قم بالترقية للحصول على حدود أعلى.', 'upsell.usageLimit.heading': 'تم الوصول إلى حد الاستخدام', 'upsell.usageLimit.notNow': 'ليس الآن', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'يُعاد التعيين {time}.', 'upsell.usageLimit.upgradePlan': 'ترقية الخطة', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'هيا بنا!', + 'walkthrough.tooltip.next': 'التالي →', + 'walkthrough.tooltip.skip': 'تخطّي الجولة', + 'walkthrough.tooltip.stepCounter': '{n} من {total}', 'webhooks.activity.empty': 'فارغ', 'webhooks.activity.title': 'النشاط الأخير', 'webhooks.composioHistory.empty': 'فارغ', @@ -374,26 +374,27 @@ const ar5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'إزالة الصدى', 'webhooks.tunnels.title': 'أنفاق Webhook', 'webhooks.tunnels.toggleFailed': 'فشل تبديل الصدى', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'انتهت صلاحية المصادقة', + 'composio.reconnect': 'إعادة الاتصال', + 'composio.directModeRequiresKey': 'فشل الحفظ. الوضع المباشر يتطلب مفتاح API غير فارغ.', + 'composio.notYetRouted': 'لم يتم توجيهه بعد', + 'composio.triggers.loading': 'جارٍ التحميل…', + 'conversations.taskKanban.todo': 'للتنفيذ', + 'settings.composio.loading': 'جارٍ التحميل…', + 'settings.mascot.noCharactersAvailable': 'لا توجد شخصيات OpenHuman متاحة بعد', + 'skills.uninstall.confirmTitle': 'إلغاء تثبيت {name}؟', + 'conversations.taskKanban.blocked': 'محظور', + 'conversations.taskKanban.done': 'مكتمل', + 'conversations.taskKanban.inProgress': 'قيد التنفيذ', + 'intelligence.memoryChunk.detail.copiedHint': 'تم النسخ', + 'settings.composio.notYetRouted': 'لم يتم توجيهه بعد', + 'settings.localModel.download.manageExternal': + 'إدارة هذا النموذج في وقت التشغيل الخارجي الخاص بك.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'أدِر عملية Ollama وعمليات تحميل النماذج خارج OpenHuman، ثم أعد تشغيل التشخيصات.', + 'settings.localModel.status.ollamaDocs': 'وثائق Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'للحصول على تعليمات الإعداد، ثم أعد المحاولة عندما يصبح وقت التشغيل قابلاً للوصول.', }; export default ar5; diff --git a/app/src/lib/i18n/chunks/bn-1.ts b/app/src/lib/i18n/chunks/bn-1.ts index 798a148cd..cd680462d 100644 --- a/app/src/lib/i18n/chunks/bn-1.ts +++ b/app/src/lib/i18n/chunks/bn-1.ts @@ -17,7 +17,7 @@ const bn1: TranslationMap = { 'common.edit': 'সম্পাদনা', 'common.create': 'তৈরি করুন', 'common.search': 'খুঁজুন', - 'common.loading': 'loading…', + 'common.loading': 'লোড হচ্ছে…', 'common.error': 'ত্রুটি', 'common.success': 'সফল', 'common.back': 'পেছনে', @@ -31,9 +31,9 @@ const bn1: TranslationMap = { 'common.yes': 'হ্যাঁ', 'common.no': 'না', 'common.ok': 'বুঝলাম', - 'common.retry': 'Try again', + 'common.retry': 'আবার চেষ্টা করুন', 'common.copy': 'কপি', - 'common.copied': 'Copied', + 'common.copied': 'কপি হয়েছে', 'common.learnMore': 'আরও জানুন', 'common.seeAll': 'দেখুন', 'common.dismiss': 'বাদ দিন', diff --git a/app/src/lib/i18n/chunks/bn-2.ts b/app/src/lib/i18n/chunks/bn-2.ts index 4eaf34976..05c990310 100644 --- a/app/src/lib/i18n/chunks/bn-2.ts +++ b/app/src/lib/i18n/chunks/bn-2.ts @@ -232,7 +232,7 @@ const bn2: TranslationMap = { 'composio.triggersStillRecorded': 'ট্রিগারগুলো ইতিহাসে রেকর্ড থাকবে — কোনো LLM টার্ন চলবে না।', 'composio.disableSpecificIntegrations': 'নির্দিষ্ট ইন্টিগ্রেশনের জন্য AI ট্রিয়াজ নিষ্ক্রিয় করুন', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'সেটিংস সংরক্ষিত হয়েছে', 'composio.saveFailed': 'সংরক্ষণ ব্যর্থ। আবার চেষ্টা করুন।', 'cron.title': 'ক্রন জবস', 'cron.scheduledJobs': 'নির্ধারিত জবস', diff --git a/app/src/lib/i18n/chunks/bn-3.ts b/app/src/lib/i18n/chunks/bn-3.ts index cdb37d05a..da5e2de7e 100644 --- a/app/src/lib/i18n/chunks/bn-3.ts +++ b/app/src/lib/i18n/chunks/bn-3.ts @@ -206,7 +206,7 @@ const bn3: TranslationMap = { 'welcome.connectionFailed': 'সংযোগ ব্যর্থ: {status} {statusText}', 'welcome.connectionFailedMsg': 'সংযোগ ব্যর্থ: {message}', 'chat.agentChatDesc': 'এজেন্টের সাথে সরাসরি চ্যাট সেশন খুলুন।', - 'channels.activeRouteValue': '{channel} via {authMode}', + 'channels.activeRouteValue': '{authMode} এর মাধ্যমে {channel}', 'privacy.dataKind.messages': 'বার্তা', 'privacy.dataKind.agents': 'এজেন্ট', 'privacy.dataKind.skills': 'স্কিলস', @@ -251,9 +251,11 @@ const bn3: TranslationMap = { 'accounts.addModal.allConnected': 'সব সংযুক্ত', 'accounts.addModal.title': 'অ্যাকাউন্ট যোগ করুন', 'accounts.respondQueue.empty': 'খালি', + 'accounts.respondQueue.hide': 'প্রতিক্রিয়া সারি লুকান', 'accounts.respondQueue.loadFailed': 'রেসপন্ড কিউ লোড করতে ব্যর্থ', 'accounts.respondQueue.loading': 'কিউ লোড হচ্ছে…', 'accounts.respondQueue.pending': 'মুলতুবি', + 'accounts.respondQueue.show': 'প্রতিক্রিয়া সারি দেখান', 'accounts.respondQueue.title': 'রেসপন্ড কিউ', 'accounts.webviewHost.almostReady': 'প্রায় প্রস্তুত...', 'accounts.webviewHost.loadTimeout': 'Webview লোড টাইমআউট', @@ -270,7 +272,7 @@ const bn3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'কোর অফলাইন', 'app.connectionIndicator.disconnected': 'সংযোগ বিচ্ছিন্ন', 'app.connectionIndicator.offline': 'অফলাইন', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'পুনঃসংযোগ হচ্ছে…', 'app.errorFallback.componentStack': 'কম্পোনেন্ট স্ট্যাক', 'app.errorFallback.downloadLatest': 'সর্বশেষ ডাউনলোড করুন', 'app.errorFallback.heading': 'শিরোনাম', @@ -280,7 +282,7 @@ const bn3: TranslationMap = { 'app.errorFallback.tryRecover': 'পুনরুদ্ধার চেষ্টা করুন', 'app.localAiDownload.installing': 'ইনস্টল হচ্ছে...', 'app.localAiDownload.preparing': 'প্রস্তুত হচ্ছে...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': '{label} সাইন-ইন দিয়ে চালিয়ে যান', 'app.openhumanLink.accounts.done': 'সম্পন্ন', 'app.openhumanLink.accounts.intro': 'ভূমিকা', 'app.openhumanLink.accounts.webviewNote': 'Webview নোট', @@ -307,9 +309,9 @@ const bn3: TranslationMap = { 'app.openhumanLink.notifications.promptHint': 'প্রম্পট হিন্ট', 'app.openhumanLink.notifications.retry': 'পরীক্ষা বিজ্ঞপ্তি আবার চেষ্টা করুন', 'app.openhumanLink.notifications.send': 'পরীক্ষা বিজ্ঞপ্তি পাঠান', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'পাঠানো যায়নি: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'টেস্ট নোটিফিকেশন পাঠানো হয়েছে। যদি না পেয়ে থাকেন, System Settings → Notifications → OpenHuman-এ যান, Allow Notifications চালু করুন, এবং Banner Style-কে Persistent-এ সেট করুন।', 'app.openhumanLink.skipForNow': 'এখনের জন্য এড়িয়ে যান', 'app.openhumanLink.telegramUnavailable': 'Telegram পাওয়া যাচ্ছে না', 'app.openhumanLink.title.accounts': 'আপনার অ্যাপ সংযুক্ত করুন', @@ -321,7 +323,7 @@ const bn3: TranslationMap = { 'app.persistRehydration.heading': 'শিরোনাম', 'app.persistRehydration.resetCta': 'রিসেট হচ্ছে…', 'app.persistRehydration.resetting': 'রিসেট হচ্ছে…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'OpenHuman শুরু হচ্ছে...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'আপডেটের সময় কিছু একটা ভুল হয়েছে।', 'app.update.header.default': 'আপডেট', @@ -331,7 +333,7 @@ const bn3: TranslationMap = { 'app.update.header.restarting': 'রিস্টার্ট হচ্ছে…', 'app.update.later': 'পরে', 'app.update.newVersionReady': 'একটি নতুন ভার্সন ইনস্টলের জন্য প্রস্তুত।', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} ডাউনলোড হয়েছে', 'app.update.progress.installing': 'নতুন ভার্সন ইনস্টল হচ্ছে…', 'app.update.progress.restarting': 'অ্যাপ পুনরায় লঞ্চ হচ্ছে…', 'app.update.progress.working': '{percent}%', @@ -346,7 +348,7 @@ const bn3: TranslationMap = { 'channels.discord.linkTokenOnce': 'লিংক টোকেন একবার', 'channels.discord.picker.allPermissionsOk': 'বট এই চ্যানেলে সব প্রয়োজনীয় অনুমতি পেয়েছে।', 'channels.discord.picker.botNotInServers': 'বট কোনো সার্ভারে নেই', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'ক্যাটাগরি', 'channels.discord.picker.channel': 'চ্যানেল', 'channels.discord.picker.checkingPermissions': 'অনুমতি পরীক্ষা হচ্ছে', 'channels.discord.picker.loadingChannels': 'চ্যানেল লোড হচ্ছে...', @@ -357,7 +359,7 @@ const bn3: TranslationMap = { 'channels.discord.picker.selectChannel': 'একটি চ্যানেল বেছে নিন', 'channels.discord.picker.selectServer': 'একটি সার্ভার বেছে নিন', 'channels.discord.picker.server': 'সার্ভার', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'সার্ভার ও চ্যানেল নির্বাচন', 'channels.discord.savedRestartRequired': 'চ্যানেল সংরক্ষিত। সক্রিয় করতে অ্যাপ রিস্টার্ট করুন।', 'channels.telegram.connect': 'সংযুক্ত করুন', 'channels.telegram.managedDmConnecting': 'ম্যানেজড DM সংযোগ হচ্ছে', diff --git a/app/src/lib/i18n/chunks/bn-4.ts b/app/src/lib/i18n/chunks/bn-4.ts index e8972c41a..5d6fd844a 100644 --- a/app/src/lib/i18n/chunks/bn-4.ts +++ b/app/src/lib/i18n/chunks/bn-4.ts @@ -2,69 +2,69 @@ import type { TranslationMap } from '../types'; // Bengali (বাংলা) chunk 4/5. Translated from chunks/en-4.ts. const bn4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'অনুমোদন ও আনসাবস্ক্রাইব', + 'chat.unsubscribeApproval.approved': '✓ সফলভাবে আনসাবস্ক্রাইব হয়েছে।', 'chat.unsubscribeApproval.denied': '✕ অনুরোধ প্রত্যাখ্যাত।', 'chat.unsubscribeApproval.deny': 'প্রত্যাখ্যান করুন', 'chat.unsubscribeApproval.processing': 'প্রক্রিয়া হচ্ছে...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'আনসাবস্ক্রাইব অনুরোধ', 'commandPalette.ariaLabel': 'কমান্ড প্যালেট', 'commandPalette.description': 'বিবরণ', 'commandPalette.label': 'কমান্ড', 'commandPalette.noResults': 'কোনো ফলাফল নেই', 'commandPalette.placeholder': 'একটি কমান্ড টাইপ করুন বা খুঁজুন…', 'commandPalette.searchAria': 'কমান্ড খুঁজুন', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'সব শর্টকাটের জন্য ? চাপুন', 'commandPalette.title': 'কমান্ড প্যালেট', 'composio.connect.additionalConfigRequired': 'অতিরিক্ত কনফিগ প্রয়োজন', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Atlassian সাবডোমেইন লেবেল', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'সংযোগ করুন', + 'composio.connect.connectionFailed': 'সংযোগ ব্যর্থ (স্ট্যাটাস: {status})।', 'composio.connect.disconnectFailed': 'সংযোগ বিচ্ছিন্ন করতে ব্যর্থ: {msg}', 'composio.connect.disconnecting': 'সংযোগ বিচ্ছিন্ন হচ্ছে…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'সংযোগ করুন আপনার', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'অ্যাকাউন্ট। আমরা একটি ব্রাউজার উইন্ডো খুলব, সেখানে আপনি অ্যাক্সেস অনুমোদন করবেন, এবং এই অ্যাপ স্বয়ংক্রিয়ভাবে সংযোগ শনাক্ত করবে।', + 'composio.connect.isConnected': 'সংযুক্ত।', + 'composio.connect.manage': 'পরিচালনা', + 'composio.connect.needsSubdomain': 'সংযোগ করতে', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'আপনার Atlassian সাবডোমেইন লিখুন (যেমন acme.atlassian.net-এর জন্য acme) এবং আবার চেষ্টা করুন।', + 'composio.connect.oauthComplete': 'OAuth সম্পূর্ণ করতে…', 'composio.connect.oauthTimeout': 'OAuth টাইমআউট', 'composio.connect.permissions': 'অনুমতি', 'composio.connect.permissionsDefault': 'পড়া + লেখা ডিফল্টে সক্রিয়', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'প্রকাশ করতে পারে', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'OpenHuman-এর নিজস্ব এজেন্ট অনুমতি নিচে read, write, এবং admin টগল হিসেবে নিয়ন্ত্রিত।', 'composio.connect.reopenBrowser': 'ব্রাউজার আবার খুলুন', 'composio.connect.requestingUrl': 'সংযোগ URL অনুরোধ হচ্ছে…', 'composio.connect.retryConnection': 'সংযোগ আবার চেষ্টা করুন', 'composio.connect.scopeLoadError': 'স্কোপ পছন্দ লোড করা যায়নি: {msg}', 'composio.connect.scopeSaveError': '{key} স্কোপ সংরক্ষণ করা যায়নি: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'শুধু সংক্ষিপ্ত সাবডোমেইন লিখুন (যেমন "acme"), পুরো URL নয়। এতে শুধু অক্ষর, সংখ্যা এবং হাইফেন থাকা উচিত।', 'composio.connect.subdomainRequired': 'চালিয়ে যেতে আপনার Atlassian সাবডোমেইন দিন।', 'composio.connect.wabaIdLabel': 'WABA ID লেবেল', 'composio.connect.wabaIdRequired': 'চালিয়ে যেতে আপনার WhatsApp Business Account ID (WABA ID) দিন।', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'অপেক্ষা করছে', 'composio.connect.waitingHint': 'অপেক্ষার হিন্ট', 'composio.triggers.heading': 'ট্রিগার', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'ইভেন্টের জন্য শুনুন', + 'composio.triggers.loadError': 'ট্রিগার লোড করা যায়নি', 'composio.triggers.needsConfiguration': 'কনফিগারেশন প্রয়োজন', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'বর্তমানে কোনো ট্রিগার উপলব্ধ নেই', 'conversations.taskKanban.moveLeft': 'বামে সরান', 'conversations.taskKanban.moveRight': 'ডানে সরান', 'conversations.taskKanban.title': 'টাস্ক', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'টার্ন', 'conversations.toolTimeline.workerThread': 'ওয়ার্কার থ্রেড', 'daemon.serviceBlockingGate.body': 'বডি', 'daemon.serviceBlockingGate.downloadHint': 'ডাউনলোড হিন্ট', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'সর্বশেষ সংস্করণ ডাউনলোড করুন', + 'daemon.serviceBlockingGate.retryCore': 'Core আবার চেষ্টা করুন', 'daemon.serviceBlockingGate.retryFailed': 'আবার চেষ্টা ব্যর্থ। সর্বশেষ অ্যাপ বিল্ড ডাউনলোড করে আবার চেষ্টা করুন।', 'daemon.serviceBlockingGate.retrying': 'আবার চেষ্টা হচ্ছে...', @@ -72,11 +72,11 @@ const bn4: TranslationMap = { 'home.banners.discordSubtitle': 'Discord সাবটাইটেল', 'home.banners.discordTitle': 'আমাদের Discord-এ যোগ দিন', 'home.banners.earlyBirdDismiss': 'আর্লি বার্ড ব্যানার বাদ দিন', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'প্রথম সাবস্ক্রিপশন।', 'home.banners.earlyBirdOn': 'আর্লি বার্ড চালু', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': 'প্রথম ১,০০০ ব্যবহারকারী ৬০% ছাড় পাবেন।', 'home.banners.earlyBirdUseCode': 'আর্লি বার্ড কোড ব্যবহার করুন', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'সাবস্ক্রিপশন নিন', 'home.banners.promoCreditsBody': 'প্রোমো ক্রেডিট বডি', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'প্রোমো ক্রেডিট ব্যবহার', @@ -86,21 +86,21 @@ const bn4: TranslationMap = { 'intelligence.memoryChunk.detail.noEmbedding': 'কোনো এম্বেডিং নেই', 'intelligence.memoryChunk.letterhead.from': 'থেকে', 'intelligence.memoryChunk.letterhead.to': 'পর্যন্ত', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', - 'intelligence.memoryChunk.mentioned.heading': 'm e n t i o n e d', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', - 'intelligence.memoryChunk.scoreBars.heading': 'w h y k e p t', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.mentioned.chunkOne': '১টি চাঙ্ক', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count}টি চাঙ্ক', + 'intelligence.memoryChunk.mentioned.heading': 'উ ল্লে খি ত', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} স্কোর {pct} শতাংশ', + 'intelligence.memoryChunk.scoreBars.atThreshold': '{threshold}-এ', + 'intelligence.memoryChunk.scoreBars.dropped': 'বাদ দেওয়া হয়েছে', + 'intelligence.memoryChunk.scoreBars.heading': 'কে ন রা খা', + 'intelligence.memoryChunk.scoreBars.kept': 'রাখা হয়েছে', + 'intelligence.memoryText.entityTypePrefix': 'এনটিটি ধরন', 'intelligence.screenDebug.active': 'সক্রিয়', 'intelligence.screenDebug.app': 'অ্যাপ', 'intelligence.screenDebug.bounds': 'সীমানা', 'intelligence.screenDebug.captureAlt': 'ক্যাপচার পরীক্ষার ফলাফল', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'ব্যর্থ', + 'intelligence.screenDebug.captureSuccess': 'সফল', 'intelligence.screenDebug.captureTest': 'ক্যাপচার পরীক্ষা', 'intelligence.screenDebug.capturing': 'ক্যাপচার হচ্ছে', 'intelligence.screenDebug.frames': 'ফ্রেম', @@ -122,16 +122,16 @@ const bn4: TranslationMap = { 'intelligence.screenDebug.unknown': 'অজানা', 'intelligence.screenDebug.visionQueue': 'ভিশন কিউ', 'intelligence.screenDebug.visionState': 'ভিশন স্টেট', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': 'কথোপকথনজুড়ে ১টি সক্রিয় বোর্ড', + 'intelligence.tasks.activeBoardOther': 'কথোপকথনজুড়ে {count}টি সক্রিয় বোর্ড', 'intelligence.tasks.empty': 'এখনো কোনো এজেন্ট টাস্ক বোর্ড নেই', 'intelligence.tasks.emptyHint': 'খালি হিন্ট', 'intelligence.tasks.failedToLoad': 'লোড করতে ব্যর্থ', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'লাইভ', 'intelligence.tasks.loadingBoards': 'টাস্ক বোর্ড লোড হচ্ছে…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'থ্রেড {thread}', 'notifications.card.dismiss': 'বিজ্ঞপ্তি বাদ দিন', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'গুরুত্ব: {pct}%', 'notifications.center.empty': 'এখনো কোনো বিজ্ঞপ্তি নেই', 'notifications.center.emptyHint': 'খালি হিন্ট', 'notifications.center.filterAll': 'সব ফিল্টার', @@ -143,7 +143,7 @@ const bn4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'আপনার প্রোফাইল তৈরি হচ্ছে...', 'onboarding.contextGathering.continueToChat': 'চ্যাটে চালিয়ে যান', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'আমরা এখনই আপনার পূর্ণ প্রোফাইল তৈরি করতে পারিনি, কিন্তু সমস্যা নেই — আপনি চালিয়ে যেতে পারেন এবং আপনার প্রোফাইল সময়ের সাথে তৈরি হবে।', 'onboarding.contextGathering.title': 'কন্টেক্সট সংগ্রহ', 'openhuman.team_list_teams': 'টিম তালিকা', 'overlay.ariaAttention': 'মনোযোগের বার্তা', @@ -182,20 +182,20 @@ const bn4: TranslationMap = { 'privacy.dataKind.diagnostics': 'ডায়াগনস্টিক্স', 'privacy.dataKind.metadata': 'মেটাডেটা', 'privacy.dataKind.raw': 'রা', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'আমার কম্পিউটার থেকে কী বের হয়?', + 'rewards.community.achievementsUnlocked': '{total}টির মধ্যে {unlocked}টি অর্জন আনলক হয়েছে', 'rewards.community.connectDiscord': 'Discord সংযুক্ত করুন', 'rewards.community.cumulativeTokens': 'সঞ্চিত টোকেন', 'rewards.community.currentStreak': 'বর্তমান স্ট্রিক', 'rewards.community.discordLinkedNotInGuild': 'Discord লিংক কিন্তু গিল্ডে নেই', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'সার্ভারে যোগ দিয়েছেন', 'rewards.community.discordNotLinked': 'Discord লিংক করা হয়নি', 'rewards.community.discordServer': 'Discord সার্ভার', 'rewards.community.discordStatusUnavailable': 'Discord স্ট্যাটাস পাওয়া যাচ্ছে না', 'rewards.community.discordWaiting': 'Discord অপেক্ষায়', 'rewards.community.heroSubtitle': 'হিরো সাবটাইটেল', 'rewards.community.heroTitle': 'হিরো শিরোনাম', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'Discord-এ যোগ দিন', 'rewards.community.loadingRewards': 'পুরস্কার লোড হচ্ছে…', 'rewards.community.locked': 'আনলক করা', 'rewards.community.retrying': 'আবার চেষ্টা হচ্ছে…', @@ -213,20 +213,20 @@ const bn4: TranslationMap = { 'rewards.coupon.colReward': 'পুরস্কার', 'rewards.coupon.colStatus': 'স্ট্যাটাস', 'rewards.coupon.loadingHistory': 'পুরস্কার ইতিহাস লোড হচ্ছে…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'এখনও কোনো রিওয়ার্ড কোড রিডিম করা হয়নি।', 'rewards.coupon.pending': 'মুলতুবি', 'rewards.coupon.placeholder': 'কুপন কোড', 'rewards.coupon.promoCredits': 'প্রোমো ক্রেডিট', 'rewards.coupon.recentRedemptions': 'সাম্প্রতিক রিডেম্পশন', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} গৃহীত হয়েছে। প্রয়োজনীয় কাজটি সম্পন্ন হলে {amount} আনলক হবে।', + 'rewards.coupon.redeemButton': 'কোড রিডিম করুন', + 'rewards.coupon.redeemSuccess': '{code} রিডিম হয়েছে। আপনার ক্রেডিটে {amount} যোগ হয়েছে।', 'rewards.coupon.redeemedCodes': 'রিডিম করা কোড', 'rewards.coupon.redeeming': 'রিডিম হচ্ছে...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': 'প্রয়োগ হয়েছে', + 'rewards.coupon.statusPendingAction': 'অ্যাকশন বাকি', + 'rewards.coupon.statusRedeemed': 'রিডিম হয়েছে', 'rewards.coupon.subtitle': 'সাবটাইটেল', 'rewards.coupon.title': 'একটি কুপন কোড রিডিম করুন', 'rewards.referralSection.activity': 'রেফারেল অ্যাক্টিভিটি', @@ -242,7 +242,7 @@ const bn4: TranslationMap = { 'rewards.referralSection.haveCode': 'রেফারেল কোড আছে?', 'rewards.referralSection.haveCodeDesc': 'কোড আছে বিবরণ', 'rewards.referralSection.linked': 'লিংক করা', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(কোড {code})', 'rewards.referralSection.loading': 'রেফারেল প্রোগ্রাম লোড হচ্ছে…', 'rewards.referralSection.noReferrals': 'কোনো রেফারেল নেই', 'rewards.referralSection.pendingReferrals': 'মুলতুবি রেফারেল', @@ -255,18 +255,18 @@ const bn4: TranslationMap = { 'rewards.referralSection.title': 'বন্ধুদের আমন্ত্রণ জানান, ক্রেডিট অর্জন করুন', 'rewards.referralSection.totalEarned': 'মোট অর্জিত', 'rewards.referralSection.yourCode': 'আপনার কোড', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'ক্লাউড প্রোভাইডার যোগ করুন', 'settings.ai.addProvider': 'সংরক্ষণ হচ্ছে…', 'settings.ai.apiKeyFieldLabel': 'API কী ফিল্ড লেবেল', 'settings.ai.apiKeyRequired': 'চালিয়ে যেতে আপনার API কী পেস্ট করুন।', 'settings.ai.apiKeyStoredEncrypted': 'API কী এনক্রিপ্ট করে সংরক্ষিত', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'সংরক্ষিত কী মুছুন', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'প্রোভাইডার সংযোগ করুন', 'settings.ai.customRouting': 'কাস্টম রুটিং', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'বাতিল করুন', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'প্রোভাইডার সম্পাদনা করুন', 'settings.ai.llmProviders': 'LLM প্রোভাইডার', 'settings.ai.llmProvidersDesc': 'LLM প্রোভাইডার বিবরণ', 'settings.ai.localOllama': 'লোকাল (Ollama)', @@ -275,12 +275,12 @@ const bn4: TranslationMap = { 'settings.ai.providerLabel': 'প্রোভাইডার', 'settings.ai.routing': 'রুটিং', 'settings.ai.routingCustom': 'কাস্টম রুটিং', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': 'ডিফল্ট', 'settings.ai.routingDesc': 'রুটিং বিবরণ', 'settings.ai.saveChanges': 'সংরক্ষণ হচ্ছে…', 'settings.ai.saving': 'সংরক্ষণ হচ্ছে…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'অসংরক্ষিত পরিবর্তন', + 'settings.ai.unsavedChanges': 'অসংরক্ষিত পরিবর্তন', 'settings.ai.workloadGroupBackground': 'ওয়ার্কলোড গ্রুপ ব্যাকগ্রাউন্ড', 'settings.ai.workloadGroupChat': 'ওয়ার্কলোড গ্রুপ চ্যাট', 'settings.autocomplete.appFilter.acceptSuggestion': 'পরামর্শ গ্রহণ করুন', @@ -294,9 +294,9 @@ const bn4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'রানটাইম', 'settings.autocomplete.appFilter.test': 'পরীক্ষা', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count}টি গৃহীত completion সংরক্ষিত — ভবিষ্যৎ পরামর্শ ব্যক্তিগতকরণে ব্যবহৃত হয়।', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count}টি গৃহীত completion সংরক্ষিত — ভবিষ্যৎ পরামর্শ ব্যক্তিগতকরণে ব্যবহৃত হয়।', 'settings.autocomplete.completionStyle.clearHistory': 'পরিষ্কার হচ্ছে…', 'settings.autocomplete.completionStyle.clearing': 'পরিষ্কার হচ্ছে…', 'settings.autocomplete.completionStyle.debounce': 'ডিবাউন্স (ms)', @@ -346,7 +346,7 @@ const bn4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'ক্রেডিট ব্যালেন্স শিরোনাম', 'settings.billing.payAsYouGo.customAmount': 'কাস্টম পরিমাণ', 'settings.billing.payAsYouGo.enterAmount': 'পরিমাণ দিন', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'খোলা হচ্ছে', 'settings.billing.payAsYouGo.promotionalCredits': 'প্রচারমূলক ক্রেডিট', 'settings.billing.payAsYouGo.topUpBalance': 'টপ-আপ ব্যালেন্স', 'settings.billing.payAsYouGo.topUpCredits': 'ক্রেডিট টপ আপ করুন', diff --git a/app/src/lib/i18n/chunks/bn-5.ts b/app/src/lib/i18n/chunks/bn-5.ts index 3acaf5579..0ee567448 100644 --- a/app/src/lib/i18n/chunks/bn-5.ts +++ b/app/src/lib/i18n/chunks/bn-5.ts @@ -6,49 +6,49 @@ const bn5: TranslationMap = { 'settings.billing.subscription.upgrade': 'আপগ্রেড করুন', 'settings.billing.subscription.waiting': 'অপেক্ষা করছে', 'settings.billing.subscription.waitingPayment': 'পেমেন্টের অপেক্ষায়', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', + 'settings.composio.apiKeyDesc': 'এই ডিভাইসে বর্তমানে একটি Composio API key সংরক্ষিত আছে।', 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyStored': 'API key সংরক্ষিত', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'ব্যাকএন্ড মোডে পরিবর্তিত', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'API key সহ app.composio.dev-এ একটি অ্যাকাউন্ট', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'আপনার ব্যক্তিগত Composio অ্যাকাউন্টের মাধ্যমে প্রতিটি ইন্টিগ্রেশন পুনঃলিঙ্ক করতে', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'নোট: Composio ট্রিগার (রিয়েল-টাইম webhooks) এখনও Direct মোডে কাজ করে না — শুধু সিঙ্ক্রোনাস টুল কল', + 'settings.composio.confirmNeedItems': 'আপনার প্রয়োজন হবে:', + 'settings.composio.confirmSwitch': 'আমি বুঝেছি, Direct-এ স্যুইচ করুন', + 'settings.composio.confirmTitle': '⚠️ Direct মোডে স্যুইচ হচ্ছে', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'OpenHuman-এর মাধ্যমে লিঙ্ক করা আপনার বিদ্যমান ইন্টিগ্রেশনগুলি (Gmail, Slack, GitHub ইত্যাদি) দৃশ্যমান হবে না — সেগুলি OpenHuman-পরিচালিত Composio টেন্যান্টে থাকে।', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio ২৫০+ বহিরাগত অ্যাপকে টুল হিসেবে ইন্টিগ্রেট করে যা আপনার এজেন্ট কল করতে পারে। এই টুল কলগুলি কীভাবে রুট হবে তা নির্বাচন করুন।', 'settings.composio.modeDirect': 'ডাইরেক্ট (নিজের API কী আনুন)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'কলগুলি সরাসরি backend.composio.dev-এ যায়। সার্বভৌম / অফলাইন-বান্ধব। টুল এক্সিকিউশন সিঙ্ক্রোনাসভাবে কাজ করে; রিয়েল-টাইম ট্রিগার webhooks এখনও direct মোডে রুট করা হয় না (ফলো-আপ ইস্যু)।', 'settings.composio.modeManaged': 'ম্যানেজড (OpenHuman আপনার হয়ে পরিচালনা করে)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman আমাদের ব্যাকএন্ডের মাধ্যমে টুল কল প্রক্সি করে (প্রস্তাবিত)। অথ ব্রোকার করা হয়; আপনি কখনও Composio API key পেস্ট করেন না। Webhooks সম্পূর্ণরূপে রুট করা।', 'settings.composio.routingMode': 'রুটিং মোড', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': 'সংরক্ষণ ব্যর্থ। Direct মোডের জন্য একটি API key প্রয়োজন।', 'settings.composio.saving': 'সংরক্ষণ হচ্ছে…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'স্যুইচ হচ্ছে…', 'settings.cron.jobs.desc': 'বিবরণ', 'settings.cron.jobs.empty': 'কোনো কোর ক্রন জব পাওয়া যায়নি।', 'settings.cron.jobs.lastStatus': 'শেষ স্ট্যাটাস', 'settings.cron.jobs.loading': 'ক্রন জব লোড হচ্ছে...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'রান লোড হচ্ছে', 'settings.cron.jobs.nextRun': 'পরবর্তী রান', 'settings.cron.jobs.pause': 'বিরতি', 'settings.cron.jobs.paused': 'সক্রিয়', 'settings.cron.jobs.recentRuns': 'সাম্প্রতিক রান', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'অপসারণ হচ্ছে', 'settings.cron.jobs.resume': 'পুনরায় শুরু', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'এখন চলছে', 'settings.cron.jobs.saving': 'সংরক্ষণ হচ্ছে…', 'settings.cron.jobs.schedule': 'সময়সূচি', 'settings.cron.jobs.title': 'কোর ক্রন জবস', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'রান দেখুন', 'settings.localModel.deviceCapability.active': 'সক্রিয়', 'settings.localModel.deviceCapability.appliedTier': 'প্রয়োগকৃত টায়ার', 'settings.localModel.deviceCapability.applying': 'প্রয়োগ হচ্ছে', @@ -67,10 +67,11 @@ const bn5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Ollama ইনস্টল ব্যর্থ', 'settings.localModel.deviceCapability.installFailedDesc': 'Ollama ব্যবহারযোগ্য হওয়ার আগে ইনস্টলার বন্ধ হয়েছে। আবার চেষ্টা করতে ক্লিক করুন, বা ollama.com থেকে ম্যানুয়ালি ইনস্টল করুন।', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'প্রথমে Ollama চালান।', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'লোকাল টিয়ার একটি বাহ্যিকভাবে পরিচালিত Ollama endpoint-এর উপর নির্ভর করে। নিজে এটি শুরু করুন, আপনি যে মডেলগুলি চান তা টানুন, এবং রানটাইম পৌঁছানো না যাওয়া পর্যন্ত "Disabled (cloud fallback)" ব্যবহার করতে থাকুন।', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'এই টিয়ার ব্যবহার করতে প্রথমে Ollama চালান', 'settings.localModel.deviceCapability.installingOllama': 'Ollama ইনস্টল হচ্ছে', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'ডিভাইস তথ্য লোড হচ্ছে', 'settings.localModel.deviceCapability.localAiDisabled': @@ -92,8 +93,8 @@ const bn5: TranslationMap = { 'যেকোনো প্রম্পট টাইপ করুন এবং লোকাল মডেলে চালান...', 'settings.localModel.download.quantizationPref': 'কোয়ান্টাইজেশন পছন্দ', 'settings.localModel.download.runEmbeddingTest': 'চলছে...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'Prompt Test চালান', + 'settings.localModel.download.runSummaryTest': 'Summary Test চালান', 'settings.localModel.download.runTranscriptionTest': 'চলছে...', 'settings.localModel.download.runTtsTest': 'চলছে...', 'settings.localModel.download.runVisionTest': 'চলছে...', @@ -122,11 +123,11 @@ const bn5: TranslationMap = { 'settings.localModel.status.customLocation': 'কাস্টম লোকেশন', 'settings.localModel.status.customLocationDesc': 'কাস্টম লোকেশন বিবরণ', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Ollama চলছে এবং মডেল ইনস্টল আছে কিনা যাচাই করতে "Run Diagnostics"-এ ক্লিক করুন।', 'settings.localModel.status.downloadingUnknown': 'ডাউনলোড হচ্ছে (আকার অজানা)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'প্রত্যাশিত মডেল', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'ফোর্স রি-বুটস্ট্র্যাপ', 'settings.localModel.status.generationTps': 'জেনারেশন TPS', 'settings.localModel.status.hideErrorDetails': 'ত্রুটির বিবরণ লুকান', 'settings.localModel.status.installManually': 'ম্যানুয়ালি ইনস্টল করুন', @@ -136,16 +137,16 @@ const bn5: TranslationMap = { 'settings.localModel.status.installing': 'ইনস্টল হচ্ছে...', 'settings.localModel.status.installingOllama': 'Ollama রানটাইম ইনস্টল হচ্ছে...', 'settings.localModel.status.issues': 'সমস্যা', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '{count}টি সমস্যা পাওয়া গেছে', 'settings.localModel.status.lastLatency': 'শেষ লেটেন্সি', 'settings.localModel.status.model': 'মডেল', 'settings.localModel.status.notFound': 'পাওয়া যায়নি', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'চলছে না', 'settings.localModel.status.ollamaBinaryPath': 'Ollama বাইনারি পথ', 'settings.localModel.status.ollamaDiagnostics': 'Ollama ডায়াগনস্টিক্স', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Ollama রানটাইম অনুপলব্ধ', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman এখন Ollama-কে একটি বাহ্যিক ইনফারেন্স রানটাইম হিসেবে গণ্য করে। আপনার নিজের Ollama সার্ভার শুরু করুন, যে মডেলগুলি চান টানুন, এবং ওয়ার্কলোড রাউটিং সেদিকে নির্দেশ করুন।', 'settings.localModel.status.progress': 'অগ্রগতি', 'settings.localModel.status.provider': 'প্রোভাইডার', 'settings.localModel.status.retryBootstrap': 'বুটস্ট্র্যাপ আবার চেষ্টা করুন', @@ -170,26 +171,26 @@ const bn5: TranslationMap = { 'settings.mascot.colorHeading': 'রঙের শিরোনাম', 'settings.mascot.loadingLibrary': 'OpenHuman লাইব্রেরি লোড হচ্ছে…', 'settings.mascot.localDefault': 'লোকাল OpenHuman (ডিফল্ট)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'কোনো OpenHuman ক্যারেক্টার এখনও উপলব্ধ নেই', 'settings.mascot.noColorVariants': 'কোনো রঙের ভেরিয়েন্ট নেই', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'প্রস্তাবিত', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'যৌক্তিক ডিফল্ট — প্রতিটি রানে অতিরিক্ত টোকেন না পুড়িয়ে ভাল ধারাবাহিকতা।', + 'settings.memoryWindow.balanced.label': 'সুষম', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'প্রতিটি নতুন এজেন্ট রানে OpenHuman কতটা মনে রাখা প্রসঙ্গ ইনজেক্ট করে। বড় উইন্ডো অতীত কথোপকথন সম্পর্কে বেশি সচেতন মনে হয় কিন্তু প্রতিটি রানে বেশি টোকেন ব্যবহার করে — এবং বেশি খরচ হয়।', + 'settings.memoryWindow.extended.badge': 'আরও প্রসঙ্গ', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'প্রতিটি রানে আরও দীর্ঘমেয়াদী মেমরি ইনজেক্ট করা হয়। প্রতি টার্নে উচ্চ টোকেন খরচ।', + 'settings.memoryWindow.extended.label': 'বর্ধিত', + 'settings.memoryWindow.maximum.badge': 'সর্বোচ্চ খরচ', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'সবচেয়ে বড় নিরাপদ উইন্ডো। সেরা ধারাবাহিকতা, প্রতিটি রানে উল্লেখযোগ্যভাবে বেশি টোকেন বিল।', + 'settings.memoryWindow.maximum.label': 'সর্বোচ্চ', + 'settings.memoryWindow.minimal.badge': 'সবচেয়ে সস্তা', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'সবচেয়ে ছোট মেমরি উইন্ডো। সবচেয়ে সস্তা, দ্রুততম, রানগুলির মধ্যে সবচেয়ে কম ধারাবাহিকতা।', + 'settings.memoryWindow.minimal.label': 'ন্যূনতম', 'settings.memoryWindow.title': 'দীর্ঘমেয়াদী মেমোরি উইন্ডো', 'settings.screenIntel.permissions.accessibility': 'অ্যাক্সেসিবিলিটি', 'settings.screenIntel.permissions.grantHint': 'গ্রান্ট হিন্ট', @@ -206,17 +207,17 @@ const bn5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'স্ক্রিন রেকর্ডিং', 'settings.screenIntel.permissions.title': 'অনুমতি', 'skills.card.moreActions': 'আরও কাজ', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'অনুমোদিত টুল', + 'skills.create.author': 'লেখক', 'skills.create.authorPlaceholder': 'আপনার নাম', 'skills.create.commaSeparated': '(কমা দিয়ে আলাদা)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'স্কিল তৈরি করুন', 'skills.create.createError': 'স্কিল তৈরি করা যায়নি', 'skills.create.creating': 'তৈরি হচ্ছে…', - 'skills.create.description': 'Description', + 'skills.create.description': 'বিবরণ', 'skills.create.descriptionPlaceholder': 'এই স্কিল কী করে?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'লাইসেন্স', + 'skills.create.name': 'নাম', 'skills.create.namePlaceholder': 'যেমন Trade Journal', 'skills.create.scope': 'স্কোপ', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -224,8 +225,8 @@ const bn5: TranslationMap = { '~/.openhuman/skills//SKILL.md-এ লেখা — সব ওয়ার্কস্পেসে পাওয়া যায়।', 'skills.create.slugLabel': 'স্লাগ লেবেল', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'ট্যাগ', + 'skills.create.title': 'নতুন স্কিল', 'skills.detail.allowedTools': 'অনুমোদিত টুলস', 'skills.detail.author': 'লেখক', 'skills.detail.bundledResources': 'বান্ডেলড রিসোর্স', @@ -242,13 +243,13 @@ const bn5: TranslationMap = { 'skills.install.rawError': 'রা ত্রুটি', 'skills.install.timeoutHint': '(সেকেন্ড, ঐচ্ছিক)', 'skills.install.timeoutLabel': 'টাইমআউট লেবেল', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'URL থেকে স্কিল ইনস্টল করুন', + 'skills.install.urlLabel': 'স্কিল URL', 'skills.meetingBots.bannerDesc': 'ব্যানার বিবরণ', 'skills.meetingBots.bannerTitle': 'ব্যানার শিরোনাম', 'skills.meetingBots.busyTitle': 'OpenHuman ব্যস্ত', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'শীঘ্রই আসছে', + 'skills.meetingBots.couldNotStartTitle': 'OpenHuman শুরু করা যায়নি', 'skills.meetingBots.displayName': 'প্রদর্শন নাম', 'skills.meetingBots.failedToStart': 'OpenHuman শুরু করতে ব্যর্থ।', 'skills.meetingBots.joiningMessage': 'কয়েক সেকেন্ডের মধ্যে অংশগ্রহণকারী হিসেবে দেখা যাবে।', @@ -258,10 +259,10 @@ const bn5: TranslationMap = { 'skills.meetingBots.modalDesc': 'মোডাল বিবরণ', 'skills.meetingBots.modalTitle': 'OpenHuman-কে একটি মিটিংয়ে পাঠান', 'skills.meetingBots.newBadge': 'নতুন ব্যাজ', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'পাঠান', 'skills.meetingBots.starting': 'শুরু হচ্ছে…', 'skills.resource.preview.closeAriaLabel': 'প্রিভিউ বন্ধ করুন', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'প্রিভিউ ব্যর্থ', 'skills.resource.preview.loading': 'প্রিভিউ লোড হচ্ছে…', 'skills.resource.tree.empty': 'কোনো বান্ডেলড রিসোর্স নেই।', 'skills.search.placeholder': 'প্লেসহোল্ডার', @@ -329,32 +330,32 @@ const bn5: TranslationMap = { 'skills.setup.voice.sttReady': 'স্পিচ-টু-টেক্সট মডেল প্রস্তুত', 'skills.setup.voice.sttReturnHint': 'STT রিটার্ন হিন্ট', 'skills.setup.voice.title': 'ভয়েস ইন্টেলিজেন্স', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'আনইনস্টল করা যায়নি', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'এটি স্থায়ীভাবে স্কিল ডিরেক্টরি এবং এর সমস্ত বান্ডল রিসোর্স মুছে ফেলে। এজেন্ট পরবর্তী টার্নে এটি দেখা বন্ধ করবে।', + 'skills.uninstall.title': 'আনইনস্টল', + 'skills.uninstall.uninstallBtn': 'আনইনস্টল', + 'skills.uninstall.uninstalling': 'আনইনস্টল হচ্ছে…', 'upsell.global.limitMessage': 'চালিয়ে যেতে আপনার প্ল্যান আপগ্রেড করুন বা ক্রেডিট টপ আপ করুন', 'upsell.global.limitTitle': 'আপনি', 'upsell.global.nearLimitMessage': 'আপনি আপনার ব্যবহার সীমার {pct}% ব্যবহার করেছেন। উচ্চ সীমার জন্য আপগ্রেড করুন।', 'upsell.global.nearLimitTitle': 'ব্যবহার সীমার কাছাকাছি', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'আপনি সাপ্তাহিক সীমায় পৌঁছেছেন।{reset} সীমা এড়াতে আপনার প্ল্যান আপগ্রেড করুন বা ক্রেডিট টপ আপ করুন।', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'আপনি ১০-ঘণ্টার ইনফারেন্স রেট সীমায় পৌঁছেছেন।{reset} উচ্চতর সীমার জন্য আপগ্রেড করুন।', 'upsell.usageLimit.heading': 'ব্যবহার সীমা পৌঁছেছে', 'upsell.usageLimit.notNow': 'এখন না', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'এটি {time} রিসেট হবে।', 'upsell.usageLimit.upgradePlan': 'প্ল্যান আপগ্রেড করুন', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'চলুন শুরু করি!', + 'walkthrough.tooltip.next': 'পরবর্তী →', + 'walkthrough.tooltip.skip': 'ট্যুর এড়িয়ে যান', + 'walkthrough.tooltip.stepCounter': '{total}-এর মধ্যে {n}', 'webhooks.activity.empty': 'খালি', 'webhooks.activity.title': 'সাম্প্রতিক কার্যক্রম', 'webhooks.composioHistory.empty': 'খালি', @@ -376,26 +377,26 @@ const bn5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'ইকো সরান', 'webhooks.tunnels.title': 'Webhook টানেল', 'webhooks.tunnels.toggleFailed': 'ইকো টগল করতে ব্যর্থ', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'অথ মেয়াদোত্তীর্ণ', + 'composio.reconnect': 'পুনঃসংযোগ', + 'composio.directModeRequiresKey': 'সংরক্ষণ ব্যর্থ। Direct মোডের জন্য একটি API key প্রয়োজন।', + 'composio.notYetRouted': 'এখনও রুট করা হয়নি', + 'composio.triggers.loading': 'লোড হচ্ছে…', + 'conversations.taskKanban.todo': 'করণীয়', + 'settings.composio.loading': 'লোড হচ্ছে…', + 'settings.mascot.noCharactersAvailable': 'কোনো OpenHuman ক্যারেক্টার এখনও উপলব্ধ নেই', + 'skills.uninstall.confirmTitle': '{name} আনইনস্টল করবেন?', + 'conversations.taskKanban.blocked': 'ব্লকড', + 'conversations.taskKanban.done': 'সম্পন্ন', + 'conversations.taskKanban.inProgress': 'চলমান', + 'intelligence.memoryChunk.detail.copiedHint': 'কপি হয়েছে', + 'settings.composio.notYetRouted': 'এখনও রুট করা হয়নি', + 'settings.localModel.download.manageExternal': 'আপনার বাহ্যিক রানটাইমে এই মডেলটি পরিচালনা করুন।', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'OpenHuman-এর বাইরে Ollama প্রক্রিয়া এবং মডেল পুল পরিচালনা করুন, তারপর ডায়াগনস্টিক পুনরায় চালান।', + 'settings.localModel.status.ollamaDocs': 'Ollama ডকস', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'সেটআপ নির্দেশনার জন্য, তারপর আপনার রানটাইম পৌঁছানো গেলে পুনরায় চেষ্টা করুন।', }; export default bn5; diff --git a/app/src/lib/i18n/chunks/en-3.ts b/app/src/lib/i18n/chunks/en-3.ts index 98df5a92e..87de9eacc 100644 --- a/app/src/lib/i18n/chunks/en-3.ts +++ b/app/src/lib/i18n/chunks/en-3.ts @@ -249,9 +249,11 @@ const en3: TranslationMap = { 'accounts.addModal.allConnected': 'All connected', 'accounts.addModal.title': 'Add account', 'accounts.respondQueue.empty': 'Empty', + 'accounts.respondQueue.hide': 'Hide respond queue', 'accounts.respondQueue.loadFailed': 'Failed to load respond queue', 'accounts.respondQueue.loading': 'Loading queue…', 'accounts.respondQueue.pending': 'Pending', + 'accounts.respondQueue.show': 'Show respond queue', 'accounts.respondQueue.title': 'Respond queue', 'accounts.webviewHost.almostReady': 'Almost ready...', 'accounts.webviewHost.loadTimeout': 'Webview load timeout', diff --git a/app/src/lib/i18n/chunks/es-1.ts b/app/src/lib/i18n/chunks/es-1.ts index a15cf6920..94d42501a 100644 --- a/app/src/lib/i18n/chunks/es-1.ts +++ b/app/src/lib/i18n/chunks/es-1.ts @@ -3,7 +3,7 @@ import type { TranslationMap } from '../types'; // Spanish (Español) chunk 1/5. Translated from chunks/en-1.ts. const es1: TranslationMap = { 'nav.home': 'Inicio', - 'nav.human': 'Human', + 'nav.human': 'Humano', 'nav.chat': 'Chat', 'nav.connections': 'Conexiones', 'nav.memory': 'Inteligencia', @@ -17,7 +17,7 @@ const es1: TranslationMap = { 'common.edit': 'Editar', 'common.create': 'Crear', 'common.search': 'Buscar', - 'common.loading': 'loading…', + 'common.loading': 'cargando…', 'common.error': 'Error', 'common.success': 'Éxito', 'common.back': 'Atrás', @@ -31,9 +31,9 @@ const es1: TranslationMap = { 'common.yes': 'Sí', 'common.no': 'No', 'common.ok': 'Entendido', - 'common.retry': 'Try again', + 'common.retry': 'Reintentar', 'common.copy': 'Copiar', - 'common.copied': 'Copied', + 'common.copied': 'Copiado', 'common.learnMore': 'Más información', 'common.seeAll': 'Ver', 'common.dismiss': 'Descartar', @@ -157,7 +157,7 @@ const es1: TranslationMap = { 'chat.copyResponse': 'Copiar respuesta', 'chat.citations': 'Citas', 'chat.toolUsed': 'Herramienta usada', - 'scope.legacy': 'Legacy', + 'scope.legacy': 'Legado', 'scope.user': 'Usuario', 'scope.project': 'Proyecto', 'skills.title': 'Conexiones', diff --git a/app/src/lib/i18n/chunks/es-2.ts b/app/src/lib/i18n/chunks/es-2.ts index 7b17f79ba..68d770d30 100644 --- a/app/src/lib/i18n/chunks/es-2.ts +++ b/app/src/lib/i18n/chunks/es-2.ts @@ -27,7 +27,7 @@ const es2: TranslationMap = { 'settings.ai.toolsAvailable': 'Herramientas disponibles', 'settings.ai.tools': 'herramientas', 'settings.ai.activeSkills': 'Skills activos', - 'settings.ai.skills': 'skills', + 'settings.ai.skills': 'habilidades', 'settings.ai.skillsOverview': 'Resumen de skills', 'settings.ai.refreshingAll': 'Actualizando todo...', 'settings.ai.refreshAll': 'Actualizar toda la configuración de IA', @@ -100,7 +100,7 @@ const es2: TranslationMap = { 'devOptions.local': 'Local', 'devOptions.embeddedCoreSidecar': 'Core sidecar integrado', 'devOptions.sidecarSpawned': 'Iniciado en proceso por el shell de Tauri al arrancar la app.', - 'devOptions.cloud': 'Cloud', + 'devOptions.cloud': 'Nube', 'devOptions.remoteCoreRpc': 'RPC de core remoto', 'devOptions.token': 'Token', 'devOptions.tokenNotSet': 'no establecido — RPC devolverá 401', @@ -218,7 +218,7 @@ const es2: TranslationMap = { 'autocomplete.advancedSettings': 'Configuración avanzada', 'autocomplete.debugTitle': 'Depuración de autocompletado', 'chat.agentChat': 'Chat con agente', - 'chat.overrides': 'Overrides', + 'chat.overrides': 'Anulaciones', 'chat.model': 'Modelo', 'chat.temperature': 'Temperatura', 'chat.conversation': 'Conversación', @@ -235,7 +235,7 @@ const es2: TranslationMap = { 'Los disparadores siguen registrándose en el historial — no se ejecuta ningún turno de LLM.', 'composio.disableSpecificIntegrations': 'Desactivar clasificación de IA para integraciones específicas', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'Ajustes guardados', 'composio.saveFailed': 'No se pudo guardar. Inténtalo de nuevo.', 'cron.title': 'Tareas cron', 'cron.scheduledJobs': 'Trabajos programados', @@ -263,7 +263,7 @@ const es2: TranslationMap = { 'Sin respuesta del agente después de 2 minutos. Intenta de nuevo o verifica tu conexión.', 'chat.filter.all': 'Todos', 'chat.filter.work': 'Trabajo', - 'chat.filter.briefing': 'Briefing', + 'chat.filter.briefing': 'Resumen', 'chat.filter.notification': 'Notificación', 'chat.filter.workers': 'Workers', 'chat.selectThread': 'Selecciona un hilo', @@ -308,7 +308,7 @@ const es2: TranslationMap = { 'memory.searchAria': 'Buscar en memoria', 'memory.searchPlaceholder': 'Buscar entradas de memoria...', 'memory.sourceFilter.all': 'Todas las fuentes', - 'memory.sourceFilter.email': 'Email', + 'memory.sourceFilter.email': 'Correo', 'memory.sourceFilter.calendar': 'Calendario', 'memory.sourceFilter.telegram': 'Telegram', 'memory.sourceFilter.aiInsight': 'Insight de IA', @@ -363,7 +363,7 @@ const es2: TranslationMap = { 'navigator.today': 'Hoy', 'navigator.thisWeek': 'Esta semana', 'navigator.sources': 'Fuentes', - 'navigator.email': 'Email', + 'navigator.email': 'Correo', 'navigator.slack': 'Slack', 'navigator.chat': 'Chat', 'navigator.documents': 'Documentos', @@ -381,7 +381,7 @@ const es2: TranslationMap = { 'insights.knownFacts': 'Hechos conocidos', 'insights.preferences': 'Preferencias', 'insights.relationships': 'Relaciones', - 'insights.skills': 'Skills', + 'insights.skills': 'Habilidades', 'insights.opinions': 'Opiniones', }; diff --git a/app/src/lib/i18n/chunks/es-3.ts b/app/src/lib/i18n/chunks/es-3.ts index 2a9a14a52..32a904236 100644 --- a/app/src/lib/i18n/chunks/es-3.ts +++ b/app/src/lib/i18n/chunks/es-3.ts @@ -78,7 +78,7 @@ const es3: TranslationMap = { 'sync.noContent': 'Aún no se ha sincronizado contenido en la memoria. Conecta una integración para empezar.', 'backend.aiBackend': 'Backend de IA', - 'backend.cloud': 'Cloud', + 'backend.cloud': 'Nube', 'backend.recommended': 'Recomendado', 'backend.cloudDescription': 'Modelos rápidos y potentes alojados en nuestros servidores. Listos para usar de inmediato.', @@ -189,7 +189,7 @@ const es3: TranslationMap = { 'notifications.dayAgo': 'hace {n}d', 'notifications.category.messages': 'Mensajes', 'notifications.category.agents': 'Agentes', - 'notifications.category.skills': 'Skills', + 'notifications.category.skills': 'Habilidades', 'notifications.category.system': 'Sistema', 'notifications.category.meetings': 'Reuniones', 'notifications.category.reminders': 'Recordatorios', @@ -212,7 +212,7 @@ const es3: TranslationMap = { 'channels.activeRouteValue': '{channel} vía {authMode}', 'privacy.dataKind.messages': 'Mensajes', 'privacy.dataKind.agents': 'Agentes', - 'privacy.dataKind.skills': 'Skills', + 'privacy.dataKind.skills': 'Habilidades', 'privacy.dataKind.system': 'Sistema', 'privacy.dataKind.meetings': 'Reuniones', 'privacy.dataKind.reminders': 'Recordatorios', @@ -254,9 +254,11 @@ const es3: TranslationMap = { 'accounts.addModal.allConnected': 'Todo conectado', 'accounts.addModal.title': 'Agregar cuenta', 'accounts.respondQueue.empty': 'Vacío', + 'accounts.respondQueue.hide': 'Ocultar cola de respuestas', 'accounts.respondQueue.loadFailed': 'No se pudo cargar la cola de respuestas', 'accounts.respondQueue.loading': 'Cargando cola…', 'accounts.respondQueue.pending': 'Pendiente', + 'accounts.respondQueue.show': 'Mostrar cola de respuestas', 'accounts.respondQueue.title': 'Cola de respuestas', 'accounts.webviewHost.almostReady': 'Casi listo...', 'accounts.webviewHost.loadTimeout': 'Tiempo de carga agotado', @@ -273,7 +275,7 @@ const es3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'Core sin conexión', 'app.connectionIndicator.disconnected': 'Desconectado', 'app.connectionIndicator.offline': 'Sin conexión', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'Reconectando…', 'app.errorFallback.componentStack': 'Pila de componentes', 'app.errorFallback.downloadLatest': 'Descargar la última versión', 'app.errorFallback.heading': 'Encabezado', @@ -283,22 +285,22 @@ const es3: TranslationMap = { 'app.errorFallback.tryRecover': 'Intentar recuperar', 'app.localAiDownload.installing': 'Instalando...', 'app.localAiDownload.preparing': 'Preparando...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'Continuar con inicio de sesión de {label}', 'app.openhumanLink.accounts.done': 'Listo', - 'app.openhumanLink.accounts.intro': 'Intro', + 'app.openhumanLink.accounts.intro': 'Introducción', 'app.openhumanLink.accounts.webviewNote': 'Nota de webview', 'app.openhumanLink.billing.openDashboard': 'Abrir panel', 'app.openhumanLink.billing.stayOnTrial': 'Continuar con prueba', 'app.openhumanLink.billing.trialCredit': 'Crédito de prueba', 'app.openhumanLink.billing.trialDesc': 'Descripción de prueba', 'app.openhumanLink.defaultBody': - 'Not ready in the popup yet. Open the full settings page when you need it.', - 'app.openhumanLink.discord.intro': 'Intro', + 'Aún no está listo en el menú emergente. Abre la página completa de ajustes cuando la necesites.', + 'app.openhumanLink.discord.intro': 'Introducción', 'app.openhumanLink.discord.openInvite': 'Abrir invitación', - 'app.openhumanLink.discord.perk1': 'Perk1', - 'app.openhumanLink.discord.perk2': 'Perk2', - 'app.openhumanLink.discord.perk3': 'Perk3', - 'app.openhumanLink.discord.perk4': 'Perk4', + 'app.openhumanLink.discord.perk1': 'Ventaja 1', + 'app.openhumanLink.discord.perk2': 'Ventaja 2', + 'app.openhumanLink.discord.perk3': 'Ventaja 3', + 'app.openhumanLink.discord.perk4': 'Ventaja 4', 'app.openhumanLink.done': 'Listo', 'app.openhumanLink.loadingChannelSetup': 'Cargando configuración de canal', 'app.openhumanLink.maybeLater': 'Quizás después', @@ -307,13 +309,13 @@ const es3: TranslationMap = { 'app.openhumanLink.notifications.blockedStep1': 'Paso bloqueado 1', 'app.openhumanLink.notifications.blockedStep2': 'Paso bloqueado 2', 'app.openhumanLink.notifications.blockedStep3': 'Paso bloqueado 3', - 'app.openhumanLink.notifications.intro': 'Intro', + 'app.openhumanLink.notifications.intro': 'Introducción', 'app.openhumanLink.notifications.promptHint': 'Sugerencia de permiso', 'app.openhumanLink.notifications.retry': 'Reintentar notificación de prueba', 'app.openhumanLink.notifications.send': 'Enviar notificación de prueba', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'No se pudo enviar: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'Notificación de prueba enviada. Si no la recibiste, ve a Ajustes del sistema → Notificaciones → OpenHuman, activa Permitir notificaciones y configura el estilo de banner como Persistente.', 'app.openhumanLink.skipForNow': 'Omitir por ahora', 'app.openhumanLink.telegramUnavailable': 'Telegram no disponible', 'app.openhumanLink.title.accounts': 'Conecta tus apps', @@ -325,7 +327,7 @@ const es3: TranslationMap = { 'app.persistRehydration.heading': 'Encabezado', 'app.persistRehydration.resetCta': 'Restableciendo…', 'app.persistRehydration.resetting': 'Restableciendo…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'Inicializando OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'Algo salió mal durante la actualización.', 'app.update.header.default': 'Actualización', @@ -335,7 +337,7 @@ const es3: TranslationMap = { 'app.update.header.restarting': 'Reiniciando…', 'app.update.later': 'Después', 'app.update.newVersionReady': 'Una nueva versión está lista para instalar.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} descargado', 'app.update.progress.installing': 'Instalando la nueva versión…', 'app.update.progress.restarting': 'Relanzando la app…', 'app.update.progress.working': '{percent}%', @@ -351,7 +353,7 @@ const es3: TranslationMap = { 'channels.discord.picker.allPermissionsOk': 'El bot tiene todos los permisos requeridos en este canal.', 'channels.discord.picker.botNotInServers': 'Bot no está en servidores', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'Categoría', 'channels.discord.picker.channel': 'Canal', 'channels.discord.picker.checkingPermissions': 'Verificando permisos', 'channels.discord.picker.loadingChannels': 'Cargando canales...', @@ -362,7 +364,7 @@ const es3: TranslationMap = { 'channels.discord.picker.selectChannel': 'Selecciona un canal', 'channels.discord.picker.selectServer': 'Selecciona un servidor', 'channels.discord.picker.server': 'Servidor', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'Selección de servidor y canal', 'channels.discord.savedRestartRequired': 'Canal guardado. Reinicia la app para activarlo.', 'channels.telegram.connect': 'Conectar', 'channels.telegram.managedDmConnecting': 'Conectando DM gestionado', diff --git a/app/src/lib/i18n/chunks/es-4.ts b/app/src/lib/i18n/chunks/es-4.ts index dc5bc059b..81353fc2e 100644 --- a/app/src/lib/i18n/chunks/es-4.ts +++ b/app/src/lib/i18n/chunks/es-4.ts @@ -2,69 +2,69 @@ import type { TranslationMap } from '../types'; // Spanish (Español) chunk 4/5. Translated from chunks/en-4.ts. const es4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'Aprobar y darse de baja', + 'chat.unsubscribeApproval.approved': '✓ Baja realizada con éxito.', 'chat.unsubscribeApproval.denied': '✕ Solicitud denegada.', 'chat.unsubscribeApproval.deny': 'Denegar', 'chat.unsubscribeApproval.processing': 'Procesando...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'Solicitud de baja', 'commandPalette.ariaLabel': 'Paleta de comandos', 'commandPalette.description': 'Descripción', 'commandPalette.label': 'Comandos', 'commandPalette.noResults': 'Sin resultados', 'commandPalette.placeholder': 'Escribe un comando o busca…', 'commandPalette.searchAria': 'Buscar comandos', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'Pulsa ? para ver todos los atajos', 'commandPalette.title': 'Paleta de comandos', 'composio.connect.additionalConfigRequired': 'Configuración adicional requerida', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Etiqueta de subdominio de Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'Conectar', + 'composio.connect.connectionFailed': 'Falló la conexión (estado: {status}).', 'composio.connect.disconnectFailed': 'Desconexión fallida: {msg}', 'composio.connect.disconnecting': 'Desconectando…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'Conecta tu', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'cuenta. Abriremos una ventana del navegador, apruebas el acceso allí, y esta app detectará la conexión automáticamente.', + 'composio.connect.isConnected': 'está conectado.', + 'composio.connect.manage': 'Gestionar', + 'composio.connect.needsSubdomain': 'Para conectar', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'introduce tu subdominio de Atlassian (p. ej. acme para acme.atlassian.net) e inténtalo de nuevo.', + 'composio.connect.oauthComplete': 'OAuth por completar…', 'composio.connect.oauthTimeout': 'Tiempo de OAuth agotado', 'composio.connect.permissions': 'Permisos', 'composio.connect.permissionsDefault': 'Lectura + Escritura habilitados por defecto', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'puede exponer', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'los propios permisos del agente de OpenHuman se controlan abajo con conmutadores de lectura, escritura y administración.', 'composio.connect.reopenBrowser': 'Reabrir navegador', 'composio.connect.requestingUrl': 'Solicitando URL de conexión…', 'composio.connect.retryConnection': 'Reintentar conexión', 'composio.connect.scopeLoadError': 'No se pudieron cargar las preferencias de alcance: {msg}', 'composio.connect.scopeSaveError': 'No se pudo guardar el alcance {key}: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'Introduce solo el subdominio corto (p. ej. "acme"), no la URL completa. Debe contener solo letras, números y guiones.', 'composio.connect.subdomainRequired': 'Ingresa tu subdominio de Atlassian para continuar.', 'composio.connect.wabaIdLabel': 'Etiqueta de ID de WABA', 'composio.connect.wabaIdRequired': 'Ingresa tu ID de cuenta de WhatsApp Business (WABA ID) para continuar.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'Esperando a', 'composio.connect.waitingHint': 'Sugerencia de espera', 'composio.triggers.heading': 'Disparadores', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'Escuchar eventos de', + 'composio.triggers.loadError': 'No se pudieron cargar los triggers', 'composio.triggers.needsConfiguration': 'Necesita configuración', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'Actualmente no hay triggers disponibles para', 'conversations.taskKanban.moveLeft': 'Mover a la izquierda', 'conversations.taskKanban.moveRight': 'Mover a la derecha', 'conversations.taskKanban.title': 'Tareas', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'turno', 'conversations.toolTimeline.workerThread': 'hilo de worker', 'daemon.serviceBlockingGate.body': 'Cuerpo', 'daemon.serviceBlockingGate.downloadHint': 'Sugerencia de descarga', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'Descargar la última versión', + 'daemon.serviceBlockingGate.retryCore': 'Reintentar Core', 'daemon.serviceBlockingGate.retryFailed': 'Reintento fallido. Descarga la última versión de la app e inténtalo de nuevo.', 'daemon.serviceBlockingGate.retrying': 'Reintentando...', @@ -72,11 +72,11 @@ const es4: TranslationMap = { 'home.banners.discordSubtitle': 'Subtítulo de Discord', 'home.banners.discordTitle': 'Únete a nuestro Discord', 'home.banners.earlyBirdDismiss': 'Descartar banner de early bird', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'primera suscripción.', 'home.banners.earlyBirdOn': 'Early bird activo', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': 'Los primeros 1.000 usuarios obtienen un 60% de descuento.', 'home.banners.earlyBirdUseCode': 'Usar código early bird', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'obtener una suscripción', 'home.banners.promoCreditsBody': 'Cuerpo de créditos promocionales', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'Uso de créditos promocionales', @@ -86,21 +86,21 @@ const es4: TranslationMap = { 'intelligence.memoryChunk.detail.noEmbedding': 'Sin embedding', 'intelligence.memoryChunk.letterhead.from': 'de', 'intelligence.memoryChunk.letterhead.to': 'a', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 fragmento', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} fragmentos', 'intelligence.memoryChunk.mentioned.heading': 'm e n c i o n a d o', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} puntuación {pct} por ciento', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'en {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'descartado', 'intelligence.memoryChunk.scoreBars.heading': 'p o r q u é s e c o n s e r v ó', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'conservado', + 'intelligence.memoryText.entityTypePrefix': 'Tipo de entidad', 'intelligence.screenDebug.active': 'Activo', 'intelligence.screenDebug.app': 'App', 'intelligence.screenDebug.bounds': 'Límites', 'intelligence.screenDebug.captureAlt': 'Resultado de prueba de captura', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'Falló', + 'intelligence.screenDebug.captureSuccess': 'Éxito', 'intelligence.screenDebug.captureTest': 'Prueba de captura', 'intelligence.screenDebug.capturing': 'Capturando', 'intelligence.screenDebug.frames': 'Fotogramas', @@ -122,16 +122,16 @@ const es4: TranslationMap = { 'intelligence.screenDebug.unknown': 'Desconocido', 'intelligence.screenDebug.visionQueue': 'Cola de visión', 'intelligence.screenDebug.visionState': 'Estado de visión', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 tablero activo entre conversaciones', + 'intelligence.tasks.activeBoardOther': '{count} tableros activos entre conversaciones', 'intelligence.tasks.empty': 'Sin tableros de tareas de agente aún', 'intelligence.tasks.emptyHint': 'Sugerencia de vacío', 'intelligence.tasks.failedToLoad': 'No se pudo cargar', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'en vivo', 'intelligence.tasks.loadingBoards': 'Cargando tableros de tareas…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'Hilo {thread}', 'notifications.card.dismiss': 'Descartar notificación', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'Importancia: {pct}%', 'notifications.center.empty': 'Sin notificaciones aún', 'notifications.center.emptyHint': 'Sugerencia de vacío', 'notifications.center.filterAll': 'Filtrar todo', @@ -143,7 +143,7 @@ const es4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'Construyendo tu perfil...', 'onboarding.contextGathering.continueToChat': 'Continuar al chat', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'No pudimos construir tu perfil completo ahora mismo, pero no pasa nada — puedes continuar y tu perfil se construirá con el tiempo.', 'onboarding.contextGathering.title': 'Recopilación de contexto', 'openhuman.team_list_teams': 'Lista de equipos', 'overlay.ariaAttention': 'Mensaje de atención', @@ -183,21 +183,21 @@ const es4: TranslationMap = { 'privacy.dataKind.derived': 'Derivado', 'privacy.dataKind.diagnostics': 'Diagnósticos', 'privacy.dataKind.metadata': 'Metadatos', - 'privacy.dataKind.raw': 'Raw', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.dataKind.raw': 'Sin procesar', + 'privacy.whatLeaves.link.label': '¿Qué sale de mi ordenador?', + 'rewards.community.achievementsUnlocked': '{unlocked} de {total} logros desbloqueados', 'rewards.community.connectDiscord': 'Conectar Discord', 'rewards.community.cumulativeTokens': 'Tokens acumulados', 'rewards.community.currentStreak': 'Racha actual', 'rewards.community.discordLinkedNotInGuild': 'Discord vinculado pero no en el servidor', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'Te uniste al servidor', 'rewards.community.discordNotLinked': 'Discord no vinculado', 'rewards.community.discordServer': 'Servidor de Discord', 'rewards.community.discordStatusUnavailable': 'Estado de Discord no disponible', 'rewards.community.discordWaiting': 'Esperando en Discord', 'rewards.community.heroSubtitle': 'Subtítulo hero', 'rewards.community.heroTitle': 'Título hero', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'Unirse a Discord', 'rewards.community.loadingRewards': 'Cargando recompensas…', 'rewards.community.locked': 'Desbloqueado', 'rewards.community.retrying': 'Reintentando…', @@ -215,20 +215,20 @@ const es4: TranslationMap = { 'rewards.coupon.colReward': 'Recompensa', 'rewards.coupon.colStatus': 'Estado', 'rewards.coupon.loadingHistory': 'Cargando historial de recompensas…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'Aún no se han canjeado códigos de recompensa.', 'rewards.coupon.pending': 'Pendiente', 'rewards.coupon.placeholder': 'Código de cupón', 'rewards.coupon.promoCredits': 'Créditos promocionales', 'rewards.coupon.recentRedemptions': 'Canjes recientes', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} aceptado. {amount} se desbloqueará cuando se complete la acción requerida.', + 'rewards.coupon.redeemButton': 'Canjear código', + 'rewards.coupon.redeemSuccess': '{code} canjeado. Se añadieron {amount} a tus créditos.', 'rewards.coupon.redeemedCodes': 'Códigos canjeados', 'rewards.coupon.redeeming': 'Canjeando...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': 'Aplicado', + 'rewards.coupon.statusPendingAction': 'Acción pendiente', + 'rewards.coupon.statusRedeemed': 'Canjeado', 'rewards.coupon.subtitle': 'Subtítulo', 'rewards.coupon.title': 'Canjear un código de cupón', 'rewards.referralSection.activity': 'Actividad de referidos', @@ -244,7 +244,7 @@ const es4: TranslationMap = { 'rewards.referralSection.haveCode': '¿Tienes un código de referido?', 'rewards.referralSection.haveCodeDesc': 'Descripción de código disponible', 'rewards.referralSection.linked': 'Vinculado', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(código {code})', 'rewards.referralSection.loading': 'Cargando programa de referidos…', 'rewards.referralSection.noReferrals': 'Sin referidos', 'rewards.referralSection.pendingReferrals': 'Referidos pendientes', @@ -257,18 +257,18 @@ const es4: TranslationMap = { 'rewards.referralSection.title': 'Invita amigos, gana créditos', 'rewards.referralSection.totalEarned': 'Total ganado', 'rewards.referralSection.yourCode': 'Tu código', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'Añadir proveedor en la nube', 'settings.ai.addProvider': 'Guardando…', 'settings.ai.apiKeyFieldLabel': 'Etiqueta de campo de clave API', 'settings.ai.apiKeyRequired': 'Pega tu clave API para continuar.', 'settings.ai.apiKeyStoredEncrypted': 'Clave API almacenada cifrada', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'Borrar clave almacenada', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'Conectar proveedor', 'settings.ai.customRouting': 'Enrutamiento personalizado', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'Descartar', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'Editar proveedor', 'settings.ai.llmProviders': 'Proveedores LLM', 'settings.ai.llmProvidersDesc': 'Descripción de proveedores LLM', 'settings.ai.localOllama': 'Local (Ollama)', @@ -277,12 +277,12 @@ const es4: TranslationMap = { 'settings.ai.providerLabel': 'Proveedor', 'settings.ai.routing': 'Enrutamiento', 'settings.ai.routingCustom': 'Enrutamiento personalizado', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': 'Predeterminado', 'settings.ai.routingDesc': 'Descripción de enrutamiento', 'settings.ai.saveChanges': 'Guardando…', 'settings.ai.saving': 'Guardando…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'cambio sin guardar', + 'settings.ai.unsavedChanges': 'cambios sin guardar', 'settings.ai.workloadGroupBackground': 'Grupo de carga de trabajo en segundo plano', 'settings.ai.workloadGroupChat': 'Grupo de carga de trabajo de chat', 'settings.autocomplete.appFilter.acceptSuggestion': 'Aceptar sugerencia', @@ -296,9 +296,9 @@ const es4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'Runtime', 'settings.autocomplete.appFilter.test': 'Probar', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count} completado aceptado almacenado — se usa para personalizar futuras sugerencias.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count} completados aceptados almacenados — se usan para personalizar futuras sugerencias.', 'settings.autocomplete.completionStyle.clearHistory': 'Limpiando…', 'settings.autocomplete.completionStyle.clearing': 'Limpiando…', 'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)', @@ -348,7 +348,7 @@ const es4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'Título de saldo de crédito', 'settings.billing.payAsYouGo.customAmount': 'Cantidad personalizada', 'settings.billing.payAsYouGo.enterAmount': 'Ingresar cantidad', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'Abriendo', 'settings.billing.payAsYouGo.promotionalCredits': 'Créditos promocionales', 'settings.billing.payAsYouGo.topUpBalance': 'Recargar saldo', 'settings.billing.payAsYouGo.topUpCredits': 'Recargar créditos', diff --git a/app/src/lib/i18n/chunks/es-5.ts b/app/src/lib/i18n/chunks/es-5.ts index d01ebf452..79282f272 100644 --- a/app/src/lib/i18n/chunks/es-5.ts +++ b/app/src/lib/i18n/chunks/es-5.ts @@ -6,49 +6,51 @@ const es5: TranslationMap = { 'settings.billing.subscription.upgrade': 'Mejorar plan', 'settings.billing.subscription.waiting': 'Esperando', 'settings.billing.subscription.waitingPayment': 'Esperando pago', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': + 'Actualmente hay una clave API de Composio almacenada en este dispositivo.', + 'settings.composio.apiKeyLabel': 'Clave API de Composio', + 'settings.composio.apiKeyStored': 'Clave API almacenada', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Cambiado al modo Backend', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'Una cuenta en app.composio.dev con una clave API', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'Vuelve a vincular cada integración a través de tu cuenta personal de Composio', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'Nota: los triggers de Composio (webhooks en tiempo real) aún no funcionan en modo Directo — solo las llamadas de herramientas síncronas', + 'settings.composio.confirmNeedItems': 'Necesitarás:', + 'settings.composio.confirmSwitch': 'Entiendo, cambiar a Directo', + 'settings.composio.confirmTitle': '⚠️ Cambiando a modo Directo', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'Tus integraciones existentes (Gmail, Slack, GitHub, etc. vinculadas a través de OpenHuman) no serán visibles — viven en el inquilino de Composio gestionado por OpenHuman.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio integra más de 250 aplicaciones externas como herramientas que tu agente puede invocar. Elige cómo se enrutan esas llamadas.', 'settings.composio.modeDirect': 'Directo (usa tu propia clave API)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'Las llamadas van directamente a backend.composio.dev. Soberano / amigable con uso sin conexión. La ejecución de herramientas funciona de forma síncrona; los webhooks de triggers en tiempo real aún no están enrutados en modo directo (incidencia pendiente).', 'settings.composio.modeManaged': 'Gestionado (OpenHuman lo maneja por ti)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman canaliza las llamadas de herramientas a través de nuestro backend (recomendado). La autenticación se intermedia; nunca pegas una clave API de Composio. Los webhooks están totalmente enrutados.', 'settings.composio.routingMode': 'Modo de enrutamiento', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + 'Error al guardar. El modo Directo requiere una clave API no vacía.', 'settings.composio.saving': 'Guardando…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'Cambiando…', 'settings.cron.jobs.desc': 'Descripción', 'settings.cron.jobs.empty': 'No se encontraron tareas cron del core.', 'settings.cron.jobs.lastStatus': 'Último estado', 'settings.cron.jobs.loading': 'Cargando tareas cron...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'Cargando ejecuciones', 'settings.cron.jobs.nextRun': 'Próxima ejecución', 'settings.cron.jobs.pause': 'Pausar', 'settings.cron.jobs.paused': 'Activado', 'settings.cron.jobs.recentRuns': 'Ejecuciones recientes', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'Eliminando', 'settings.cron.jobs.resume': 'Reanudar', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'Ejecutando ahora', 'settings.cron.jobs.saving': 'Guardando…', 'settings.cron.jobs.schedule': 'Programación', 'settings.cron.jobs.title': 'Tareas cron del core', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'Ver ejecuciones', 'settings.localModel.deviceCapability.active': 'Activo', 'settings.localModel.deviceCapability.appliedTier': 'Nivel aplicado', 'settings.localModel.deviceCapability.applying': 'Aplicando', @@ -67,10 +69,11 @@ const es5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Instalación de Ollama fallida', 'settings.localModel.deviceCapability.installFailedDesc': 'El instalador terminó antes de que Ollama estuviera disponible. Haz clic en reintentar o instálalo manualmente desde ollama.com.', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'Ejecuta Ollama primero.', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'Los niveles locales dependen de un endpoint de Ollama gestionado externamente. Inícialo tú mismo, descarga los modelos que quieras y sigue usando "Desactivado (respaldo en la nube)" hasta que el runtime sea accesible.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'Ejecuta Ollama primero para usar este nivel', 'settings.localModel.deviceCapability.installingOllama': 'Instalando Ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'Cargando info del dispositivo', 'settings.localModel.deviceCapability.localAiDisabled': @@ -92,8 +95,8 @@ const es5: TranslationMap = { 'Escribe cualquier prompt y ejecútalo en el modelo local...', 'settings.localModel.download.quantizationPref': 'Preferencia de cuantización', 'settings.localModel.download.runEmbeddingTest': 'Ejecutando...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'Ejecutar prueba de prompt', + 'settings.localModel.download.runSummaryTest': 'Ejecutar prueba de resumen', 'settings.localModel.download.runTranscriptionTest': 'Ejecutando...', 'settings.localModel.download.runTtsTest': 'Ejecutando...', 'settings.localModel.download.runVisionTest': 'Ejecutando...', @@ -123,11 +126,11 @@ const es5: TranslationMap = { 'settings.localModel.status.customLocation': 'Ubicación personalizada', 'settings.localModel.status.customLocationDesc': 'Descripción de ubicación personalizada', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Haz clic en "Ejecutar diagnósticos" para verificar que Ollama está en ejecución y los modelos están instalados.', 'settings.localModel.status.downloadingUnknown': 'Descargando (tamaño desconocido)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'Modelos esperados', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'Forzar re-bootstrap', 'settings.localModel.status.generationTps': 'TPS de generación', 'settings.localModel.status.hideErrorDetails': 'Ocultar detalles del error', 'settings.localModel.status.installManually': 'Instalar manualmente', @@ -137,16 +140,16 @@ const es5: TranslationMap = { 'settings.localModel.status.installing': 'Instalando...', 'settings.localModel.status.installingOllama': 'Instalando runtime de Ollama...', 'settings.localModel.status.issues': 'Problemas', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': 'Se encontraron {count} problema(s)', 'settings.localModel.status.lastLatency': 'Última latencia', 'settings.localModel.status.model': 'Modelo', 'settings.localModel.status.notFound': 'No encontrado', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'No en ejecución', 'settings.localModel.status.ollamaBinaryPath': 'Ruta del binario de Ollama', 'settings.localModel.status.ollamaDiagnostics': 'Diagnósticos de Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Runtime de Ollama no disponible', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman ahora trata Ollama como un runtime de inferencia externo. Inicia tu propio servidor Ollama, descarga los modelos que quieras y apunta el enrutado de cargas hacia él.', 'settings.localModel.status.progress': 'Progreso', 'settings.localModel.status.provider': 'Proveedor', 'settings.localModel.status.retryBootstrap': 'Reintentar bootstrap', @@ -171,26 +174,26 @@ const es5: TranslationMap = { 'settings.mascot.colorHeading': 'Encabezado del color', 'settings.mascot.loadingLibrary': 'Cargando biblioteca de OpenHuman…', 'settings.mascot.localDefault': 'OpenHuman local (predeterminado)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'Aún no hay personajes de OpenHuman disponibles', 'settings.mascot.noColorVariants': 'Sin variantes de color', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'Recomendado', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'Predeterminado sensato — buena continuidad sin quemar tokens extra en cada ejecución.', + 'settings.memoryWindow.balanced.label': 'Equilibrado', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'Cuánto contexto recordado inyecta OpenHuman en cada nueva ejecución del agente. Ventanas más grandes parecen más conscientes de conversaciones pasadas, pero usan más tokens — y cuestan más — en cada ejecución.', + 'settings.memoryWindow.extended.badge': 'Más contexto', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'Más memoria a largo plazo inyectada en cada ejecución. Mayor coste de tokens por turno.', + 'settings.memoryWindow.extended.label': 'Extendido', + 'settings.memoryWindow.maximum.badge': 'Mayor coste', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'La ventana segura más grande. Mejor continuidad, factura de tokens significativamente mayor en cada ejecución.', + 'settings.memoryWindow.maximum.label': 'Máximo', + 'settings.memoryWindow.minimal.badge': 'Más barato', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'Ventana de memoria más pequeña. La más barata, rápida y con menor continuidad entre ejecuciones.', + 'settings.memoryWindow.minimal.label': 'Mínimo', 'settings.memoryWindow.title': 'Ventana de memoria a largo plazo', 'settings.screenIntel.permissions.accessibility': 'Accesibilidad', 'settings.screenIntel.permissions.grantHint': 'Sugerencia de permiso', @@ -207,17 +210,17 @@ const es5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'Grabación de pantalla', 'settings.screenIntel.permissions.title': 'Permisos', 'skills.card.moreActions': 'Más acciones', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'Herramientas permitidas', + 'skills.create.author': 'Autor', 'skills.create.authorPlaceholder': 'Tu nombre', 'skills.create.commaSeparated': '(separado por comas)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'Crear habilidad', 'skills.create.createError': 'No se pudo crear el skill', 'skills.create.creating': 'Creando…', - 'skills.create.description': 'Description', + 'skills.create.description': 'Descripción', 'skills.create.descriptionPlaceholder': '¿Qué hace este skill?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'Licencia', + 'skills.create.name': 'Nombre', 'skills.create.namePlaceholder': 'p. ej. Trade Journal', 'skills.create.scope': 'Alcance', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -225,8 +228,8 @@ const es5: TranslationMap = { 'Se escribe en ~/.openhuman/skills//SKILL.md — disponible en todos los espacios de trabajo.', 'skills.create.slugLabel': 'Etiqueta de slug', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'Etiquetas', + 'skills.create.title': 'Nueva habilidad', 'skills.detail.allowedTools': 'Herramientas permitidas', 'skills.detail.author': 'Autor', 'skills.detail.bundledResources': 'Recursos incluidos', @@ -243,13 +246,13 @@ const es5: TranslationMap = { 'skills.install.rawError': 'Error sin procesar', 'skills.install.timeoutHint': '(segundos, opcional)', 'skills.install.timeoutLabel': 'Etiqueta de tiempo límite', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'Instalar habilidad desde URL', + 'skills.install.urlLabel': 'URL de la habilidad', 'skills.meetingBots.bannerDesc': 'Descripción del banner', 'skills.meetingBots.bannerTitle': 'Título del banner', 'skills.meetingBots.busyTitle': 'OpenHuman está ocupado', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'Próximamente', + 'skills.meetingBots.couldNotStartTitle': 'No se pudo iniciar OpenHuman', 'skills.meetingBots.displayName': 'Nombre de visualización', 'skills.meetingBots.failedToStart': 'No se pudo iniciar OpenHuman.', 'skills.meetingBots.joiningMessage': 'Debería aparecer como participante en unos segundos.', @@ -259,13 +262,13 @@ const es5: TranslationMap = { 'skills.meetingBots.modalDesc': 'Descripción del modal', 'skills.meetingBots.modalTitle': 'Enviar OpenHuman a una reunión', 'skills.meetingBots.newBadge': 'Nuevo', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'Enviar a', 'skills.meetingBots.starting': 'Iniciando…', 'skills.resource.preview.closeAriaLabel': 'Cerrar vista previa', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'Vista previa fallida', 'skills.resource.preview.loading': 'Cargando vista previa…', 'skills.resource.tree.empty': 'Sin recursos incluidos.', - 'skills.search.placeholder': 'Placeholder', + 'skills.search.placeholder': 'Marcador de posición', 'skills.setup.autocomplete.acceptKey': 'Tecla de aceptación', 'skills.setup.autocomplete.activeDesc': 'Descripción activa', 'skills.setup.autocomplete.activeTitle': 'Autocompletado está activo', @@ -330,32 +333,32 @@ const es5: TranslationMap = { 'skills.setup.voice.sttReady': 'Modelo de voz a texto listo', 'skills.setup.voice.sttReturnHint': 'Sugerencia de retorno STT', 'skills.setup.voice.title': 'Inteligencia de voz', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'No se pudo desinstalar', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'Esto elimina permanentemente el directorio de la habilidad y todos sus recursos incluidos. El agente dejará de verlo en el próximo turno.', + 'skills.uninstall.title': 'Desinstalar', + 'skills.uninstall.uninstallBtn': 'Desinstalar', + 'skills.uninstall.uninstalling': 'Desinstalando…', 'upsell.global.limitMessage': 'Mejora tu plan o recarga créditos para continuar', 'upsell.global.limitTitle': 'Tú', 'upsell.global.nearLimitMessage': 'Has usado el {pct}% de tu límite de uso. Mejora el plan para límites más altos.', 'upsell.global.nearLimitTitle': 'Acercándote al límite de uso', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'Has alcanzado tu límite semanal.{reset} Mejora tu plan o recarga créditos para evitar límites.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'Has alcanzado tu límite de inferencia de 10 horas.{reset} Mejora para obtener límites más altos.', 'upsell.usageLimit.heading': 'Límite de uso alcanzado', 'upsell.usageLimit.notNow': 'Ahora no', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'Se restablece {time}.', 'upsell.usageLimit.upgradePlan': 'Mejorar plan', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': '¡Vamos!', + 'walkthrough.tooltip.next': 'Siguiente →', + 'walkthrough.tooltip.skip': 'Omitir tour', + 'walkthrough.tooltip.stepCounter': '{n} de {total}', 'webhooks.activity.empty': 'Vacío', 'webhooks.activity.title': 'Actividad reciente', 'webhooks.composioHistory.empty': 'Vacío', @@ -377,26 +380,27 @@ const es5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'Eliminar echo', 'webhooks.tunnels.title': 'Túneles de webhook', 'webhooks.tunnels.toggleFailed': 'No se pudo alternar el echo', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'Autenticación caducada', + 'composio.reconnect': 'Reconectar', + 'composio.directModeRequiresKey': + 'Error al guardar. El modo Directo requiere una clave API no vacía.', + 'composio.notYetRouted': 'aún sin enrutar', + 'composio.triggers.loading': 'Cargando…', + 'conversations.taskKanban.todo': 'Pendiente', + 'settings.composio.loading': 'Cargando…', + 'settings.mascot.noCharactersAvailable': 'Aún no hay personajes de OpenHuman disponibles', + 'skills.uninstall.confirmTitle': '¿Desinstalar {name}?', + 'conversations.taskKanban.blocked': 'Bloqueado', + 'conversations.taskKanban.done': 'Completado', + 'conversations.taskKanban.inProgress': 'En progreso', + 'intelligence.memoryChunk.detail.copiedHint': 'copiado', + 'settings.composio.notYetRouted': 'aún sin enrutar', + 'settings.localModel.download.manageExternal': 'Gestiona este modelo en tu runtime externo.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'Gestiona el proceso de Ollama y las descargas de modelos fuera de OpenHuman, luego vuelve a ejecutar los diagnósticos.', + 'settings.localModel.status.ollamaDocs': 'Documentación de Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'para instrucciones de configuración, luego reintenta cuando tu runtime sea accesible.', }; export default es5; diff --git a/app/src/lib/i18n/chunks/fr-1.ts b/app/src/lib/i18n/chunks/fr-1.ts index f3742c2a1..1b79e7dd7 100644 --- a/app/src/lib/i18n/chunks/fr-1.ts +++ b/app/src/lib/i18n/chunks/fr-1.ts @@ -17,7 +17,7 @@ const fr1: TranslationMap = { 'common.edit': 'Modifier', 'common.create': 'Créer', 'common.search': 'Rechercher', - 'common.loading': 'loading…', + 'common.loading': 'chargement…', 'common.error': 'Erreur', 'common.success': 'Succès', 'common.back': 'Retour', @@ -31,9 +31,9 @@ const fr1: TranslationMap = { 'common.yes': 'Oui', 'common.no': 'Non', 'common.ok': 'Compris', - 'common.retry': 'Try again', + 'common.retry': 'Réessayer', 'common.copy': 'Copier', - 'common.copied': 'Copied', + 'common.copied': 'Copié', 'common.learnMore': 'En savoir plus', 'common.seeAll': 'Voir', 'common.dismiss': 'Ignorer', @@ -53,7 +53,7 @@ const fr1: TranslationMap = { 'settings.general': 'Général', 'settings.featuresAndAI': 'Fonctionnalités & IA', 'settings.billingAndRewards': 'Facturation & Récompenses', - 'settings.support': 'Support', + 'settings.support': 'Assistance', 'settings.advanced': 'Avancé', 'settings.dangerZone': 'Zone de danger', 'settings.account': 'Compte', diff --git a/app/src/lib/i18n/chunks/fr-2.ts b/app/src/lib/i18n/chunks/fr-2.ts index 3936331e6..852616a1e 100644 --- a/app/src/lib/i18n/chunks/fr-2.ts +++ b/app/src/lib/i18n/chunks/fr-2.ts @@ -105,7 +105,7 @@ const fr2: TranslationMap = { "Lancé en processus interne par le shell Tauri au démarrage de l'app.", 'devOptions.cloud': 'Cloud', 'devOptions.remoteCoreRpc': 'RPC core distant', - 'devOptions.token': 'Token', + 'devOptions.token': 'Jeton', 'devOptions.tokenNotSet': 'non défini — le RPC renverra 401', 'devOptions.triggerSentryTest': 'Déclencher un test Sentry (staging)', 'devOptions.triggerSentryTestDesc': @@ -148,7 +148,7 @@ const fr2: TranslationMap = { 'team.role.admin': 'Admin', 'team.role.billingManager': 'Gestionnaire de facturation', 'team.role.member': 'Membre', - 'team.active': 'Active', + 'team.active': 'Actif', 'team.personalTeam': 'Équipe personnelle', 'team.manageTeam': "Gérer l'équipe", 'team.switching': 'Changement…', @@ -237,7 +237,7 @@ const fr2: TranslationMap = { "Les déclencheurs sont toujours enregistrés dans l'historique — aucun tour LLM n'est exécuté.", 'composio.disableSpecificIntegrations': 'Désactiver le triage IA pour des intégrations spécifiques', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'Paramètres enregistrés', 'composio.saveFailed': "Échec de l'enregistrement. Réessaie.", 'cron.title': 'Tâches cron', 'cron.scheduledJobs': 'Tâches planifiées', diff --git a/app/src/lib/i18n/chunks/fr-3.ts b/app/src/lib/i18n/chunks/fr-3.ts index e690f546b..980d20f35 100644 --- a/app/src/lib/i18n/chunks/fr-3.ts +++ b/app/src/lib/i18n/chunks/fr-3.ts @@ -126,7 +126,7 @@ const fr3: TranslationMap = { 'stats.firstMemory': 'Premier souvenir', 'stats.latest': 'Dernier', 'stats.sessions': 'Sessions', - 'stats.tokens': 'tokens', + 'stats.tokens': 'jetons', 'bootCheck.invalidUrl': 'Saisis une URL de runtime.', 'bootCheck.urlMustStartWith': "L'URL doit commencer par http:// ou https://", 'bootCheck.validUrlRequired': @@ -255,9 +255,11 @@ const fr3: TranslationMap = { 'accounts.addModal.allConnected': 'Tout est connecté', 'accounts.addModal.title': 'Ajouter un compte', 'accounts.respondQueue.empty': 'Vide', + 'accounts.respondQueue.hide': 'Masquer la file de réponses', 'accounts.respondQueue.loadFailed': 'Échec du chargement de la file de réponses', 'accounts.respondQueue.loading': 'Chargement de la file…', 'accounts.respondQueue.pending': 'En attente', + 'accounts.respondQueue.show': 'Afficher la file de réponses', 'accounts.respondQueue.title': 'File de réponses', 'accounts.webviewHost.almostReady': 'Presque prêt…', 'accounts.webviewHost.loadTimeout': 'Délai de chargement de la webview dépassé', @@ -274,7 +276,7 @@ const fr3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'Core hors ligne', 'app.connectionIndicator.disconnected': 'Déconnecté', 'app.connectionIndicator.offline': 'Hors ligne', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'Reconnexion…', 'app.errorFallback.componentStack': 'Pile de composants', 'app.errorFallback.downloadLatest': 'Télécharger la dernière version', 'app.errorFallback.heading': 'Titre', @@ -284,7 +286,7 @@ const fr3: TranslationMap = { 'app.errorFallback.tryRecover': 'Essayer de récupérer', 'app.localAiDownload.installing': 'Installation…', 'app.localAiDownload.preparing': 'Préparation…', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'Continuer avec la connexion {label}', 'app.openhumanLink.accounts.done': 'Terminé', 'app.openhumanLink.accounts.intro': 'Intro', 'app.openhumanLink.accounts.webviewNote': 'Note webview', @@ -293,7 +295,7 @@ const fr3: TranslationMap = { 'app.openhumanLink.billing.trialCredit': "Crédit d'essai", 'app.openhumanLink.billing.trialDesc': "Description de l'essai", 'app.openhumanLink.defaultBody': - 'Not ready in the popup yet. Open the full settings page when you need it.', + 'Pas encore disponible dans la fenêtre contextuelle. Ouvrez la page des paramètres complète si nécessaire.', 'app.openhumanLink.discord.intro': 'Intro', 'app.openhumanLink.discord.openInvite': "Ouvrir l'invitation", 'app.openhumanLink.discord.perk1': 'Avantage 1', @@ -312,9 +314,9 @@ const fr3: TranslationMap = { 'app.openhumanLink.notifications.promptHint': "Indice d'invite", 'app.openhumanLink.notifications.retry': 'Renvoyer une notification de test', 'app.openhumanLink.notifications.send': 'Envoyer une notification de test', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': "Impossible d'envoyer : {error}", 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + "Notification de test envoyée. Si vous ne l'avez pas reçue, allez dans Réglages Système → Notifications → OpenHuman, activez Autoriser les notifications, et définissez le style de bannière sur Persistant.", 'app.openhumanLink.skipForNow': "Passer pour l'instant", 'app.openhumanLink.telegramUnavailable': 'Telegram indisponible', 'app.openhumanLink.title.accounts': 'Connecte tes apps', @@ -326,7 +328,7 @@ const fr3: TranslationMap = { 'app.persistRehydration.heading': 'Titre', 'app.persistRehydration.resetCta': 'Réinitialisation…', 'app.persistRehydration.resetting': 'Réinitialisation…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': "Initialisation d'OpenHuman...", 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': "Une erreur s'est produite lors de la mise à jour.", 'app.update.header.default': 'Mise à jour', @@ -336,10 +338,10 @@ const fr3: TranslationMap = { 'app.update.header.restarting': 'Redémarrage…', 'app.update.later': 'Plus tard', 'app.update.newVersionReady': 'Une nouvelle version est prête à installer.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} téléchargé', 'app.update.progress.installing': 'Installation de la nouvelle version…', 'app.update.progress.restarting': "Relancement de l'app…", - 'app.update.progress.working': '{percent}%', + 'app.update.progress.working': '{percent} %', 'app.update.restartNote': 'Note de redémarrage', 'app.update.restartNow': 'Redémarrer maintenant', 'app.update.versionReady': 'La version {newVersion} est prête à installer.', @@ -352,7 +354,7 @@ const fr3: TranslationMap = { 'channels.discord.picker.allPermissionsOk': 'Le bot dispose de toutes les permissions requises dans ce canal.', 'channels.discord.picker.botNotInServers': 'Bot absent des serveurs', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'Catégorie', 'channels.discord.picker.channel': 'Canal', 'channels.discord.picker.checkingPermissions': 'Vérification des permissions', 'channels.discord.picker.loadingChannels': 'Chargement des canaux…', @@ -363,7 +365,7 @@ const fr3: TranslationMap = { 'channels.discord.picker.selectChannel': 'Sélectionner un canal', 'channels.discord.picker.selectServer': 'Sélectionner un serveur', 'channels.discord.picker.server': 'Serveur', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'Sélection du serveur et du canal', 'channels.discord.savedRestartRequired': "Canal enregistré. Redémarre l'app pour l'activer.", 'channels.telegram.connect': 'Connecter', 'channels.telegram.managedDmConnecting': 'Connexion du DM géré', diff --git a/app/src/lib/i18n/chunks/fr-4.ts b/app/src/lib/i18n/chunks/fr-4.ts index 6702a891f..acddf8cdc 100644 --- a/app/src/lib/i18n/chunks/fr-4.ts +++ b/app/src/lib/i18n/chunks/fr-4.ts @@ -2,69 +2,69 @@ import type { TranslationMap } from '../types'; // French (Français) chunk 4/5. Translated from chunks/en-4.ts. const fr4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'Approuver et se désabonner', + 'chat.unsubscribeApproval.approved': '✓ Désabonnement réussi.', 'chat.unsubscribeApproval.denied': '✕ Demande refusée.', 'chat.unsubscribeApproval.deny': 'Refuser', 'chat.unsubscribeApproval.processing': 'Traitement…', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'Demande de désabonnement', 'commandPalette.ariaLabel': 'Palette de commandes', 'commandPalette.description': 'Description', 'commandPalette.label': 'Commandes', 'commandPalette.noResults': 'Aucun résultat', 'commandPalette.placeholder': 'Tape une commande ou recherche…', 'commandPalette.searchAria': 'Rechercher des commandes', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'Appuyez sur ? pour tous les raccourcis', 'commandPalette.title': 'Palette de commandes', 'composio.connect.additionalConfigRequired': 'Configuration supplémentaire requise', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Libellé du sous-domaine Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'Connecter', + 'composio.connect.connectionFailed': 'Échec de la connexion (statut : {status}).', 'composio.connect.disconnectFailed': 'Déconnexion échouée : {msg}', 'composio.connect.disconnecting': 'Déconnexion…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'Connectez votre', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + "compte. Nous ouvrirons une fenêtre du navigateur, vous y approuvez l'accès, et cette application détectera la connexion automatiquement.", + 'composio.connect.isConnected': 'est connecté.', + 'composio.connect.manage': 'Gérer', + 'composio.connect.needsSubdomain': 'Pour connecter', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'saisissez votre sous-domaine Atlassian (par ex. acme pour acme.atlassian.net) et réessayez.', + 'composio.connect.oauthComplete': 'OAuth à compléter…', 'composio.connect.oauthTimeout': 'Délai OAuth dépassé', - 'composio.connect.permissions': 'Permissions', + 'composio.connect.permissions': 'Autorisations', 'composio.connect.permissionsDefault': 'Lecture + Écriture activées par défaut', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'peut exposer', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + "Les autorisations de l'agent OpenHuman sont contrôlées ci-dessous par des bascules lecture, écriture et admin.", 'composio.connect.reopenBrowser': 'Rouvrir le navigateur', 'composio.connect.requestingUrl': "Demande de l'URL de connexion…", 'composio.connect.retryConnection': 'Réessayer la connexion', 'composio.connect.scopeLoadError': 'Impossible de charger les préférences de portée : {msg}', 'composio.connect.scopeSaveError': "Impossible d'enregistrer la portée {key} : {msg}", 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'Saisissez uniquement le sous-domaine court (par ex. "acme"), pas l\'URL complète. Il doit contenir uniquement des lettres, chiffres et tirets.', 'composio.connect.subdomainRequired': 'Saisis ton sous-domaine Atlassian pour continuer.', 'composio.connect.wabaIdLabel': "Libellé de l'identifiant WABA", 'composio.connect.wabaIdRequired': 'Saisis ton identifiant WhatsApp Business Account (WABA ID) pour continuer.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'En attente de', 'composio.connect.waitingHint': "Indice d'attente", 'composio.triggers.heading': 'Déclencheurs', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'Écouter les événements de', + 'composio.triggers.loadError': 'Impossible de charger les déclencheurs', 'composio.triggers.needsConfiguration': 'Configuration requise', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': "Aucun déclencheur n'est actuellement disponible pour", 'conversations.taskKanban.moveLeft': 'Déplacer à gauche', 'conversations.taskKanban.moveRight': 'Déplacer à droite', 'conversations.taskKanban.title': 'Tâches', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'tour', 'conversations.toolTimeline.workerThread': 'fil worker', 'daemon.serviceBlockingGate.body': 'Corps', 'daemon.serviceBlockingGate.downloadHint': 'Indice de téléchargement', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'Télécharger la dernière version', + 'daemon.serviceBlockingGate.retryCore': 'Réessayer le Core', 'daemon.serviceBlockingGate.retryFailed': "Nouvelle tentative échouée. Télécharge la dernière version de l'app et réessaie.", 'daemon.serviceBlockingGate.retrying': 'Nouvelle tentative…', @@ -72,11 +72,11 @@ const fr4: TranslationMap = { 'home.banners.discordSubtitle': 'Sous-titre Discord', 'home.banners.discordTitle': 'Rejoins notre Discord', 'home.banners.earlyBirdDismiss': 'Ignorer la bannière early bird', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'premier abonnement.', 'home.banners.earlyBirdOn': 'Early bird activé', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': 'Les 1 000 premiers utilisateurs bénéficient de 60 % de remise.', 'home.banners.earlyBirdUseCode': 'Utiliser le code early bird', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'obtenir un abonnement', 'home.banners.promoCreditsBody': 'Corps des crédits promo', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'Utilisation des crédits promo', @@ -86,21 +86,21 @@ const fr4: TranslationMap = { 'intelligence.memoryChunk.detail.noEmbedding': "Pas d'embedding", 'intelligence.memoryChunk.letterhead.from': 'de', 'intelligence.memoryChunk.letterhead.to': 'à', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 fragment', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} fragments', 'intelligence.memoryChunk.mentioned.heading': 'm e n t i o n n é', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} pour cent', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'à {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'abandonné', 'intelligence.memoryChunk.scoreBars.heading': 'p o u r q u o i c o n s e r v é', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'conservé', + 'intelligence.memoryText.entityTypePrefix': "Type d'entité", 'intelligence.screenDebug.active': 'Actif', 'intelligence.screenDebug.app': 'App', 'intelligence.screenDebug.bounds': 'Limites', 'intelligence.screenDebug.captureAlt': 'Résultat du test de capture', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'Échec', + 'intelligence.screenDebug.captureSuccess': 'Succès', 'intelligence.screenDebug.captureTest': 'Test de capture', 'intelligence.screenDebug.capturing': 'Capture en cours', 'intelligence.screenDebug.frames': 'Images', @@ -110,7 +110,7 @@ const fr4: TranslationMap = { 'intelligence.screenDebug.permAccessibility': 'Permission accessibilité', 'intelligence.screenDebug.permInput': 'Permission saisie', 'intelligence.screenDebug.permScreen': 'Accessibilité', - 'intelligence.screenDebug.permissions': 'Permissions', + 'intelligence.screenDebug.permissions': 'Autorisations', 'intelligence.screenDebug.platformNotSupported': 'Plateforme non prise en charge', 'intelligence.screenDebug.recentVisionSummaries': 'Résumés de vision récents', 'intelligence.screenDebug.session': 'Session', @@ -122,16 +122,16 @@ const fr4: TranslationMap = { 'intelligence.screenDebug.unknown': 'Inconnu', 'intelligence.screenDebug.visionQueue': 'File de vision', 'intelligence.screenDebug.visionState': 'État de la vision', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 tableau actif dans les conversations', + 'intelligence.tasks.activeBoardOther': '{count} tableaux actifs dans les conversations', 'intelligence.tasks.empty': "Aucun tableau de tâches agent pour l'instant", 'intelligence.tasks.emptyHint': 'Indice vide', 'intelligence.tasks.failedToLoad': 'Échec du chargement', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'en direct', 'intelligence.tasks.loadingBoards': 'Chargement des tableaux de tâches…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'Fil {thread}', 'notifications.card.dismiss': 'Ignorer la notification', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'Importance : {pct} %', 'notifications.center.empty': "Aucune notification pour l'instant", 'notifications.center.emptyHint': 'Indice vide', 'notifications.center.filterAll': 'Tout filtrer', @@ -143,7 +143,7 @@ const fr4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'Construction de ton profil…', 'onboarding.contextGathering.continueToChat': 'Accéder au chat', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + "Nous n'avons pas pu créer votre profil complet pour l'instant, mais ce n'est pas grave — vous pouvez continuer et votre profil se construira au fil du temps.", 'onboarding.contextGathering.title': 'Collecte de contexte', 'openhuman.team_list_teams': 'Liste des équipes', 'overlay.ariaAttention': "Message d'attention", @@ -183,20 +183,20 @@ const fr4: TranslationMap = { 'privacy.dataKind.diagnostics': 'Diagnostics', 'privacy.dataKind.metadata': 'Métadonnées', 'privacy.dataKind.raw': 'Brut', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': "Qu'est-ce qui quitte mon ordinateur ?", + 'rewards.community.achievementsUnlocked': '{unlocked} sur {total} succès débloqués', 'rewards.community.connectDiscord': 'Connecter Discord', 'rewards.community.cumulativeTokens': 'Tokens cumulés', 'rewards.community.currentStreak': 'Série actuelle', 'rewards.community.discordLinkedNotInGuild': 'Discord lié mais pas dans la guilde', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'A rejoint le serveur', 'rewards.community.discordNotLinked': 'Discord non lié', 'rewards.community.discordServer': 'Serveur Discord', 'rewards.community.discordStatusUnavailable': 'État Discord indisponible', 'rewards.community.discordWaiting': 'En attente de Discord', 'rewards.community.heroSubtitle': 'Sous-titre principal', 'rewards.community.heroTitle': 'Titre principal', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'Rejoindre Discord', 'rewards.community.loadingRewards': 'Chargement des récompenses…', 'rewards.community.locked': 'Débloqué', 'rewards.community.retrying': 'Nouvelle tentative…', @@ -214,20 +214,20 @@ const fr4: TranslationMap = { 'rewards.coupon.colReward': 'Récompense', 'rewards.coupon.colStatus': 'Statut', 'rewards.coupon.loadingHistory': "Chargement de l'historique des récompenses…", - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': "Aucun code de récompense utilisé pour l'instant.", 'rewards.coupon.pending': 'En attente', 'rewards.coupon.placeholder': 'Code de coupon', 'rewards.coupon.promoCredits': 'Crédits promo', 'rewards.coupon.recentRedemptions': 'Échanges récents', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + "{code} accepté. {amount} sera débloqué après que l'action requise sera effectuée.", + 'rewards.coupon.redeemButton': 'Utiliser le code', + 'rewards.coupon.redeemSuccess': '{code} utilisé. {amount} a été ajouté à vos crédits.', 'rewards.coupon.redeemedCodes': 'Codes échangés', 'rewards.coupon.redeeming': 'Échange en cours…', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': 'Appliqué', + 'rewards.coupon.statusPendingAction': 'Action en attente', + 'rewards.coupon.statusRedeemed': 'Utilisé', 'rewards.coupon.subtitle': 'Sous-titre', 'rewards.coupon.title': 'Échanger un code de coupon', 'rewards.referralSection.activity': 'Activité de parrainage', @@ -256,18 +256,18 @@ const fr4: TranslationMap = { 'rewards.referralSection.title': 'Invite des amis, gagne des crédits', 'rewards.referralSection.totalEarned': 'Total gagné', 'rewards.referralSection.yourCode': 'Ton code', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'Ajouter un fournisseur cloud', 'settings.ai.addProvider': 'Enregistrement…', 'settings.ai.apiKeyFieldLabel': 'Libellé du champ clé API', 'settings.ai.apiKeyRequired': 'Colle ta clé API pour continuer.', 'settings.ai.apiKeyStoredEncrypted': 'Clé API stockée chiffrée', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'Effacer la clé stockée', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'Connecter un fournisseur', 'settings.ai.customRouting': 'Routage personnalisé', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'Annuler', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'Modifier le fournisseur', 'settings.ai.llmProviders': 'Fournisseurs LLM', 'settings.ai.llmProvidersDesc': 'Description des fournisseurs LLM', 'settings.ai.localOllama': 'Local (Ollama)', @@ -276,12 +276,12 @@ const fr4: TranslationMap = { 'settings.ai.providerLabel': 'Fournisseur', 'settings.ai.routing': 'Routage', 'settings.ai.routingCustom': 'Routage personnalisé', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': 'Par défaut', 'settings.ai.routingDesc': 'Description du routage', 'settings.ai.saveChanges': 'Enregistrement…', 'settings.ai.saving': 'Enregistrement…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'modification non enregistrée', + 'settings.ai.unsavedChanges': 'modifications non enregistrées', 'settings.ai.workloadGroupBackground': 'Groupe de charge de fond', 'settings.ai.workloadGroupChat': 'Groupe de charge chat', 'settings.autocomplete.appFilter.acceptSuggestion': 'Accepter la suggestion', @@ -295,9 +295,9 @@ const fr4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'Runtime', 'settings.autocomplete.appFilter.test': 'Tester', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count} complétion acceptée stockée — utilisée pour personnaliser les suggestions futures.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count} complétions acceptées stockées — utilisées pour personnaliser les suggestions futures.', 'settings.autocomplete.completionStyle.clearHistory': 'Effacement…', 'settings.autocomplete.completionStyle.clearing': 'Effacement…', 'settings.autocomplete.completionStyle.debounce': 'Délai anti-rebond (ms)', @@ -347,7 +347,7 @@ const fr4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'Titre du solde de crédits', 'settings.billing.payAsYouGo.customAmount': 'Montant personnalisé', 'settings.billing.payAsYouGo.enterAmount': 'Saisir un montant', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'Ouverture', 'settings.billing.payAsYouGo.promotionalCredits': 'Crédits promotionnels', 'settings.billing.payAsYouGo.topUpBalance': 'Recharger le solde', 'settings.billing.payAsYouGo.topUpCredits': 'Recharger les crédits', diff --git a/app/src/lib/i18n/chunks/fr-5.ts b/app/src/lib/i18n/chunks/fr-5.ts index 0ec279ec2..423d8ea11 100644 --- a/app/src/lib/i18n/chunks/fr-5.ts +++ b/app/src/lib/i18n/chunks/fr-5.ts @@ -6,49 +6,50 @@ const fr5: TranslationMap = { 'settings.billing.subscription.upgrade': 'Passer à la version supérieure', 'settings.billing.subscription.waiting': 'En attente', 'settings.billing.subscription.waitingPayment': 'En attente de paiement', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': 'Une clé API Composio est actuellement stockée sur cet appareil.', + 'settings.composio.apiKeyLabel': 'Clé API Composio', + 'settings.composio.apiKeyStored': 'Clé API stockée', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Basculé en mode Backend', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'Un compte sur app.composio.dev avec une clé API', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'Re-lier chaque intégration via votre compte Composio personnel', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + "Remarque : les déclencheurs Composio (webhooks en temps réel) ne se déclenchent pas encore en mode Direct — uniquement les appels d'outils synchrones", + 'settings.composio.confirmNeedItems': 'Vous aurez besoin de :', + 'settings.composio.confirmSwitch': 'Je comprends, passer en Direct', + 'settings.composio.confirmTitle': '⚠️ Passage au mode Direct', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'Vos intégrations existantes (Gmail, Slack, GitHub, etc. liées via OpenHuman) ne seront pas visibles — elles vivent dans le tenant Composio géré par OpenHuman.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + "Composio intègre plus de 250 applications externes en tant qu'outils que votre agent peut appeler. Choisissez comment ces appels d'outils sont routés.", 'settings.composio.modeDirect': 'Direct (apporte ta propre clé API)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + "Les appels vont directement à backend.composio.dev. Souverain / compatible hors ligne. L'exécution des outils fonctionne de manière synchrone ; les webhooks de déclencheurs en temps réel ne sont pas encore routés en mode direct (problème de suivi).", 'settings.composio.modeManaged': "Géré (OpenHuman s'en occupe pour toi)", 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + "OpenHuman relaie les appels d'outils via notre backend (recommandé). L'authentification est négociée ; vous ne collez jamais de clé API Composio. Les webhooks sont entièrement routés.", 'settings.composio.routingMode': 'Mode de routage', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + "Échec de l'enregistrement. Le mode Direct nécessite une clé API non vide.", 'settings.composio.saving': 'Enregistrement…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'Bascule en cours…', 'settings.cron.jobs.desc': 'Description', 'settings.cron.jobs.empty': 'Aucune tâche cron core trouvée.', 'settings.cron.jobs.lastStatus': 'Dernier statut', 'settings.cron.jobs.loading': 'Chargement des tâches cron…', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'Chargement des exécutions', 'settings.cron.jobs.nextRun': 'Prochaine exécution', 'settings.cron.jobs.pause': 'Mettre en pause', 'settings.cron.jobs.paused': 'Activé', 'settings.cron.jobs.recentRuns': 'Exécutions récentes', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'Suppression', 'settings.cron.jobs.resume': 'Reprendre', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': "En cours d'exécution", 'settings.cron.jobs.saving': 'Enregistrement…', 'settings.cron.jobs.schedule': 'Planification', 'settings.cron.jobs.title': 'Tâches cron du core', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'Voir les exécutions', 'settings.localModel.deviceCapability.active': 'Actif', 'settings.localModel.deviceCapability.appliedTier': 'Niveau appliqué', 'settings.localModel.deviceCapability.applying': 'Application en cours', @@ -69,10 +70,11 @@ const fr5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': "Échec de l'installation d'Ollama", 'settings.localModel.deviceCapability.installFailedDesc': "L'installateur s'est terminé avant qu'Ollama soit utilisable. Clique sur Réessayer pour recommencer, ou installe manuellement depuis ollama.com.", - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': "Lancez Ollama d'abord.", 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'Les niveaux locaux dépendent d\'un point de terminaison Ollama géré en externe. Lancez-le vous-même, téléchargez les modèles souhaités, et continuez à utiliser "Désactivé (repli cloud)" jusqu\'à ce que le runtime soit accessible.', + 'settings.localModel.deviceCapability.installOllamaFirst': + "Lancez Ollama d'abord pour utiliser ce niveau", 'settings.localModel.deviceCapability.installingOllama': "Installation d'Ollama", 'settings.localModel.deviceCapability.loadingDeviceInfo': "Chargement des informations de l'appareil", @@ -95,8 +97,8 @@ const fr5: TranslationMap = { "Tape n'importe quelle invite et exécute-la sur le modèle local…", 'settings.localModel.download.quantizationPref': 'Préférence de quantification', 'settings.localModel.download.runEmbeddingTest': 'En cours…', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': "Lancer le test d'invite", + 'settings.localModel.download.runSummaryTest': 'Lancer le test de résumé', 'settings.localModel.download.runTranscriptionTest': 'En cours…', 'settings.localModel.download.runTtsTest': 'En cours…', 'settings.localModel.download.runVisionTest': 'En cours…', @@ -126,11 +128,11 @@ const fr5: TranslationMap = { 'settings.localModel.status.customLocation': 'Emplacement personnalisé', 'settings.localModel.status.customLocationDesc': "Description de l'emplacement personnalisé", 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Cliquez sur "Lancer les diagnostics" pour vérifier qu\'Ollama fonctionne et que les modèles sont installés.', 'settings.localModel.status.downloadingUnknown': 'Téléchargement (taille inconnue)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'Modèles attendus', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'Forcer le ré-amorçage', 'settings.localModel.status.generationTps': 'TPS de génération', 'settings.localModel.status.hideErrorDetails': "Masquer les détails de l'erreur", 'settings.localModel.status.installManually': 'Installer manuellement', @@ -140,16 +142,16 @@ const fr5: TranslationMap = { 'settings.localModel.status.installing': 'Installation…', 'settings.localModel.status.installingOllama': 'Installation du runtime Ollama…', 'settings.localModel.status.issues': 'Problèmes', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '{count} problème(s) trouvé(s)', 'settings.localModel.status.lastLatency': 'Dernière latence', 'settings.localModel.status.model': 'Modèle', 'settings.localModel.status.notFound': 'Introuvable', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': "Non en cours d'exécution", 'settings.localModel.status.ollamaBinaryPath': 'Chemin du binaire Ollama', 'settings.localModel.status.ollamaDiagnostics': 'Diagnostics Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Runtime Ollama indisponible', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + "OpenHuman traite désormais Ollama comme un runtime d'inférence externe. Lancez votre propre serveur Ollama, téléchargez les modèles souhaités, et dirigez le routage des charges de travail vers celui-ci.", 'settings.localModel.status.progress': 'Progression', 'settings.localModel.status.provider': 'Fournisseur', 'settings.localModel.status.retryBootstrap': 'Réessayer le bootstrap', @@ -174,25 +176,25 @@ const fr5: TranslationMap = { 'settings.mascot.colorHeading': 'Titre de la couleur', 'settings.mascot.loadingLibrary': 'Chargement de la bibliothèque OpenHuman…', 'settings.mascot.localDefault': 'OpenHuman local (par défaut)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': "Aucun personnage OpenHuman n'est encore disponible", 'settings.mascot.noColorVariants': 'Aucune variante de couleur', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'Recommandé', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'Valeur par défaut raisonnable — bonne continuité sans consommer de jetons supplémentaires à chaque exécution.', + 'settings.memoryWindow.balanced.label': 'Équilibré', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + "Quelle quantité de contexte mémorisé OpenHuman injecte dans chaque nouvelle exécution d'agent. Des fenêtres plus larges semblent plus conscientes des conversations passées mais consomment plus de jetons — et coûtent plus cher — à chaque exécution.", + 'settings.memoryWindow.extended.badge': 'Plus de contexte', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'Plus de mémoire à long terme injectée à chaque exécution. Coût en jetons plus élevé par tour.', + 'settings.memoryWindow.extended.label': 'Étendu', + 'settings.memoryWindow.maximum.badge': 'Coût maximum', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', + 'La plus grande fenêtre sûre. Meilleure continuité, facture de jetons nettement plus élevée à chaque exécution.', 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'settings.memoryWindow.minimal.badge': 'Le moins cher', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', + 'Plus petite fenêtre de mémoire. Le moins cher, le plus rapide, le moins de continuité entre les exécutions.', 'settings.memoryWindow.minimal.label': 'Minimal', 'settings.memoryWindow.title': 'Fenêtre de mémoire à long terme', 'settings.screenIntel.permissions.accessibility': 'Accessibilité', @@ -208,19 +210,19 @@ const fr5: TranslationMap = { 'settings.screenIntel.permissions.restartRefresh': 'Redémarrage du core…', 'settings.screenIntel.permissions.restartingCore': 'Redémarrage du core…', 'settings.screenIntel.permissions.screenRecording': "Enregistrement d'écran", - 'settings.screenIntel.permissions.title': 'Permissions', + 'settings.screenIntel.permissions.title': 'Autorisations', 'skills.card.moreActions': "Plus d'actions", - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'Outils autorisés', + 'skills.create.author': 'Auteur', 'skills.create.authorPlaceholder': 'Ton nom', 'skills.create.commaSeparated': '(séparés par des virgules)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'Créer la compétence', 'skills.create.createError': 'Impossible de créer la compétence', 'skills.create.creating': 'Création…', 'skills.create.description': 'Description', 'skills.create.descriptionPlaceholder': 'Que fait cette compétence ?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'Licence', + 'skills.create.name': 'Nom', 'skills.create.namePlaceholder': 'ex. Journal de trading', 'skills.create.scope': 'Portée', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -228,15 +230,15 @@ const fr5: TranslationMap = { 'Écrit dans ~/.openhuman/skills//SKILL.md — disponible dans tous les espaces de travail.', 'skills.create.slugLabel': 'Libellé du slug', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'Étiquettes', + 'skills.create.title': 'Nouvelle compétence', 'skills.detail.allowedTools': 'Outils autorisés', 'skills.detail.author': 'Auteur', 'skills.detail.bundledResources': 'Ressources groupées', 'skills.detail.closeAriaLabel': 'Fermer les détails de la compétence', 'skills.detail.location': 'Emplacement', 'skills.detail.noBundledResources': 'Aucune ressource groupée.', - 'skills.detail.tags': 'Tags', + 'skills.detail.tags': 'Étiquettes', 'skills.detail.warnings': 'Avertissements', 'skills.install.fetchLog': 'Récupérer le journal', 'skills.install.installBtn': 'Installation…', @@ -246,13 +248,13 @@ const fr5: TranslationMap = { 'skills.install.rawError': 'Erreur brute', 'skills.install.timeoutHint': '(secondes, optionnel)', 'skills.install.timeoutLabel': "Libellé du délai d'attente", - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'Installer une compétence depuis une URL', + 'skills.install.urlLabel': 'URL de la compétence', 'skills.meetingBots.bannerDesc': 'Description de la bannière', 'skills.meetingBots.bannerTitle': 'Titre de la bannière', 'skills.meetingBots.busyTitle': 'OpenHuman est occupé', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'Bientôt disponible', + 'skills.meetingBots.couldNotStartTitle': 'Impossible de démarrer OpenHuman', 'skills.meetingBots.displayName': "Nom d'affichage", 'skills.meetingBots.failedToStart': "Échec du démarrage d'OpenHuman.", 'skills.meetingBots.joiningMessage': @@ -263,10 +265,10 @@ const fr5: TranslationMap = { 'skills.meetingBots.modalDesc': 'Description de la modal', 'skills.meetingBots.modalTitle': 'Envoyer OpenHuman à une réunion', 'skills.meetingBots.newBadge': 'Nouveau badge', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'Envoyer à', 'skills.meetingBots.starting': 'Démarrage…', 'skills.resource.preview.closeAriaLabel': "Fermer l'aperçu", - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': "Échec de l'aperçu", 'skills.resource.preview.loading': "Chargement de l'aperçu…", 'skills.resource.tree.empty': 'Aucune ressource groupée.', 'skills.search.placeholder': 'Espace réservé', @@ -335,32 +337,32 @@ const fr5: TranslationMap = { 'skills.setup.voice.sttReady': 'Modèle speech-to-text prêt', 'skills.setup.voice.sttReturnHint': 'Indice de retour STT', 'skills.setup.voice.title': 'Intelligence vocale', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'Impossible de désinstaller', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + "Cela supprime définitivement le répertoire de la compétence et toutes ses ressources fournies. L'agent cessera de la voir au prochain tour.", + 'skills.uninstall.title': 'Désinstaller', + 'skills.uninstall.uninstallBtn': 'Désinstaller', + 'skills.uninstall.uninstalling': 'Désinstallation…', 'upsell.global.limitMessage': 'Mets à niveau ton plan ou recharge des crédits pour continuer', 'upsell.global.limitTitle': 'Toi', 'upsell.global.nearLimitMessage': "Tu as utilisé {pct}% de ta limite d'utilisation. Mets à niveau pour des limites plus élevées.", 'upsell.global.nearLimitTitle': "Limite d'utilisation proche", 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'Vous avez atteint votre limite hebdomadaire.{reset} Améliorez votre forfait ou rechargez des crédits pour éviter les limites.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + "Vous avez atteint votre limite de taux d'inférence sur 10 heures.{reset} Améliorez pour des limites plus élevées.", 'upsell.usageLimit.heading': "Limite d'utilisation atteinte", 'upsell.usageLimit.notNow': 'Pas maintenant', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'Réinitialisation {time}.', 'upsell.usageLimit.upgradePlan': 'Mettre à niveau le plan', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': "C'est parti !", + 'walkthrough.tooltip.next': 'Suivant →', + 'walkthrough.tooltip.skip': 'Passer la visite', + 'walkthrough.tooltip.stepCounter': '{n} sur {total}', 'webhooks.activity.empty': 'Vide', 'webhooks.activity.title': 'Activité récente', 'webhooks.composioHistory.empty': 'Vide', @@ -382,26 +384,27 @@ const fr5: TranslationMap = { 'webhooks.tunnels.removeEcho': "Supprimer l'écho", 'webhooks.tunnels.title': 'Tunnels webhook', 'webhooks.tunnels.toggleFailed': "Échec de la bascule de l'écho", - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'Authentification expirée', + 'composio.reconnect': 'Reconnecter', + 'composio.directModeRequiresKey': + "Échec de l'enregistrement. Le mode Direct nécessite une clé API non vide.", + 'composio.notYetRouted': 'pas encore routé', + 'composio.triggers.loading': 'Chargement…', + 'conversations.taskKanban.todo': 'À faire', + 'settings.composio.loading': 'Chargement…', + 'settings.mascot.noCharactersAvailable': "Aucun personnage OpenHuman n'est encore disponible", + 'skills.uninstall.confirmTitle': 'Désinstaller {name} ?', + 'conversations.taskKanban.blocked': 'Bloqué', + 'conversations.taskKanban.done': 'Terminé', + 'conversations.taskKanban.inProgress': 'En cours', + 'intelligence.memoryChunk.detail.copiedHint': 'copié', + 'settings.composio.notYetRouted': 'pas encore routé', + 'settings.localModel.download.manageExternal': 'Gérez ce modèle dans votre runtime externe.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + "Gérez le processus Ollama et les téléchargements de modèles en dehors d'OpenHuman, puis relancez les diagnostics.", + 'settings.localModel.status.ollamaDocs': 'Documentation Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'pour les instructions de configuration, puis réessayez une fois votre runtime accessible.', }; export default fr5; diff --git a/app/src/lib/i18n/chunks/hi-1.ts b/app/src/lib/i18n/chunks/hi-1.ts index 07029e4e3..133fbdfbf 100644 --- a/app/src/lib/i18n/chunks/hi-1.ts +++ b/app/src/lib/i18n/chunks/hi-1.ts @@ -3,7 +3,7 @@ import type { TranslationMap } from '../types'; // Hindi (हिन्दी) chunk 1/5. Translated from chunks/en-1.ts. const hi1: TranslationMap = { 'nav.home': 'होम', - 'nav.human': 'Human', + 'nav.human': 'मानव', 'nav.chat': 'चैट', 'nav.connections': 'कनेक्शन', 'nav.memory': 'इंटेलिजेंस', @@ -17,7 +17,7 @@ const hi1: TranslationMap = { 'common.edit': 'एडिट करें', 'common.create': 'बनाएं', 'common.search': 'सर्च करें', - 'common.loading': 'loading…', + 'common.loading': 'लोड हो रहा है…', 'common.error': 'एरर', 'common.success': 'सफल', 'common.back': 'वापस', @@ -31,9 +31,9 @@ const hi1: TranslationMap = { 'common.yes': 'हाँ', 'common.no': 'नहीं', 'common.ok': 'ठीक है', - 'common.retry': 'Try again', + 'common.retry': 'पुनः प्रयास करें', 'common.copy': 'कॉपी करें', - 'common.copied': 'Copied', + 'common.copied': 'कॉपी हो गया', 'common.learnMore': 'और जानें', 'common.seeAll': 'देखें', 'common.dismiss': 'हटाएं', @@ -149,7 +149,7 @@ const hi1: TranslationMap = { 'chat.copyResponse': 'जवाब कॉपी करें', 'chat.citations': 'सोर्स', 'chat.toolUsed': 'टूल इस्तेमाल हुआ', - 'scope.legacy': 'Legacy', + 'scope.legacy': 'लीगेसी', 'scope.user': 'यूज़र', 'scope.project': 'प्रोजेक्ट', 'skills.title': 'कनेक्शन', @@ -223,9 +223,9 @@ const hi1: TranslationMap = { 'onboarding.apiKeys.title': 'अपनी API Keys जोड़ें', 'onboarding.apiKeys.subtitle': 'अभी पेस्ट करें या बाद में Settings › AI में जोड़ें। Keys इस डिवाइस पर एन्क्रिप्टेड रहती हैं।', - 'onboarding.apiKeys.openaiLabel': 'OpenAI API key', + 'onboarding.apiKeys.openaiLabel': 'OpenAI API कुंजी', 'onboarding.apiKeys.openaiPlaceholder': 'sk-...', - 'onboarding.apiKeys.anthropicLabel': 'Anthropic API key', + 'onboarding.apiKeys.anthropicLabel': 'Anthropic API कुंजी', 'onboarding.apiKeys.anthropicPlaceholder': 'sk-ant-...', 'onboarding.apiKeys.saveError': 'वह key सेव नहीं हो पाई। दोबारा चेक करके कोशिश करें।', 'onboarding.apiKeys.skipForNow': 'अभी के लिए स्किप करें', @@ -299,7 +299,7 @@ const hi1: TranslationMap = { 'channels.status.error': 'एरर', 'channels.status.configuring': 'कॉन्फिगर हो रहा है', 'channels.defaultMessaging': 'डिफ़ॉल्ट मैसेजिंग चैनल', - 'webhooks.title': 'Webhooks', + 'webhooks.title': 'वेबहुक्स', 'webhooks.create': 'Webhook बनाएं', 'webhooks.noWebhooks': 'कोई webhook कॉन्फिगर नहीं है', 'webhooks.url': 'URL', @@ -317,7 +317,7 @@ const hi1: TranslationMap = { 'devOptions.diagnosticsDesc': 'सिस्टम हेल्थ, लॉग्स और परफॉर्मेंस मेट्रिक्स', 'devOptions.debugPanels': 'डिबग पैनल', 'devOptions.debugPanelsDesc': 'फीचर फ्लैग्स, स्टेट इंस्पेक्शन और डिबगिंग टूल्स', - 'devOptions.webhooks': 'Webhooks', + 'devOptions.webhooks': 'वेबहुक्स', 'devOptions.webhooksDesc': 'Webhook इंटीग्रेशन कॉन्फिगर और टेस्ट करें', 'devOptions.memoryInspection': 'मेमोरी इंस्पेक्शन', 'devOptions.memoryInspectionDesc': 'मेमोरी एंट्रीज़ ब्राउज़, क्वेरी और मैनेज करें', diff --git a/app/src/lib/i18n/chunks/hi-2.ts b/app/src/lib/i18n/chunks/hi-2.ts index 12f7f83cd..e73035948 100644 --- a/app/src/lib/i18n/chunks/hi-2.ts +++ b/app/src/lib/i18n/chunks/hi-2.ts @@ -170,7 +170,7 @@ const hi2: TranslationMap = { 'voice.title': 'वॉइस डिक्टेशन', 'voice.settings': 'वॉइस सेटिंग्स', 'voice.settingsDesc': 'डिक्टेट करने और एक्टिव फील्ड में टेक्स्ट डालने के लिए hotkey दबाकर रखें।', - 'voice.hotkey': 'Hotkey', + 'voice.hotkey': 'हॉटकी', 'voice.activationMode': 'एक्टिवेशन मोड', 'voice.tapToToggle': 'टॉगल के लिए टैप करें', 'voice.writingStyle': 'राइटिंग स्टाइल', @@ -230,9 +230,9 @@ const hi2: TranslationMap = { 'composio.triggersStillRecorded': 'ट्रिगर हिस्ट्री में रिकॉर्ड होते रहते हैं — कोई LLM टर्न नहीं चलता।', 'composio.disableSpecificIntegrations': 'खास इंटीग्रेशन के लिए AI triage बंद करें', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'सेटिंग्स सहेजी गईं', 'composio.saveFailed': 'सेव नहीं हो पाया। दोबारा कोशिश करें।', - 'cron.title': 'Cron Jobs', + 'cron.title': 'क्रॉन जॉब्स', 'cron.scheduledJobs': 'शेड्यूल्ड जॉब्स', 'cron.manageCronJobs': 'कोर शेड्यूलर से cron jobs मैनेज करें।', 'cron.refreshCronJobs': 'Cron Jobs रिफ्रेश करें', @@ -342,7 +342,7 @@ const hi2: TranslationMap = { 'token.usageLimitReached': 'उपयोग सीमा पहुँच गई', 'token.approachingLimit': 'सीमा के करीब', 'token.planClickForDetails': 'प्लान - डिटेल्स के लिए क्लिक करें', - 'token.sessionTokens': 'In: {in} | Out: {out} | Turns: {turns}', + 'token.sessionTokens': 'इन: {in} | आउट: {out} | टर्न: {turns}', 'token.limit': 'सीमा पहुँच गई', 'catalog.noCapabilityBinding': 'कोई कैपेबिलिटी बाइंडिंग नहीं', 'catalog.downloadFailed': 'डाउनलोड विफल', diff --git a/app/src/lib/i18n/chunks/hi-3.ts b/app/src/lib/i18n/chunks/hi-3.ts index 5046d8eb6..982e1dd5b 100644 --- a/app/src/lib/i18n/chunks/hi-3.ts +++ b/app/src/lib/i18n/chunks/hi-3.ts @@ -205,7 +205,7 @@ const hi3: TranslationMap = { 'welcome.connectionFailed': 'कनेक्शन विफल: {status} {statusText}', 'welcome.connectionFailedMsg': 'कनेक्शन विफल: {message}', 'chat.agentChatDesc': 'एजेंट के साथ डायरेक्ट चैट सेशन खोलें।', - 'channels.activeRouteValue': '{channel} via {authMode}', + 'channels.activeRouteValue': '{channel} द्वारा {authMode}', 'privacy.dataKind.messages': 'मैसेज', 'privacy.dataKind.agents': 'एजेंट', 'privacy.dataKind.skills': 'स्किल्स', @@ -250,9 +250,11 @@ const hi3: TranslationMap = { 'accounts.addModal.allConnected': 'सब कनेक्टेड', 'accounts.addModal.title': 'अकाउंट जोड़ें', 'accounts.respondQueue.empty': 'खाली है', + 'accounts.respondQueue.hide': 'उत्तर कतार छिपाएँ', 'accounts.respondQueue.loadFailed': 'रिस्पॉन्ड क्यू लोड नहीं हो पाई', 'accounts.respondQueue.loading': 'क्यू लोड हो रही है…', 'accounts.respondQueue.pending': 'पेंडिंग', + 'accounts.respondQueue.show': 'उत्तर कतार दिखाएँ', 'accounts.respondQueue.title': 'रिस्पॉन्ड क्यू', 'accounts.webviewHost.almostReady': 'लगभग तैयार है...', 'accounts.webviewHost.loadTimeout': 'Webview लोड टाइमआउट', @@ -269,47 +271,47 @@ const hi3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'कोर ऑफलाइन', 'app.connectionIndicator.disconnected': 'डिसकनेक्टेड', 'app.connectionIndicator.offline': 'ऑफलाइन', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'पुनः कनेक्ट हो रहा है…', 'app.errorFallback.componentStack': 'कम्पोनेंट स्टैक', 'app.errorFallback.downloadLatest': 'लेटेस्ट डाउनलोड करें', - 'app.errorFallback.heading': 'Heading', - 'app.errorFallback.hint': 'Hint', + 'app.errorFallback.heading': 'शीर्षक', + 'app.errorFallback.hint': 'संकेत', 'app.errorFallback.reloadApp': 'ऐप रिलोड करें', - 'app.errorFallback.subheading': 'Subheading', + 'app.errorFallback.subheading': 'उपशीर्षक', 'app.errorFallback.tryRecover': 'रिकवर करने की कोशिश करें', 'app.localAiDownload.installing': 'इन्स्टॉल हो रहा है...', 'app.localAiDownload.preparing': 'तैयार हो रहा है...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': '{label} साइन-इन के साथ जारी रखें', 'app.openhumanLink.accounts.done': 'हो गया', - 'app.openhumanLink.accounts.intro': 'Intro', - 'app.openhumanLink.accounts.webviewNote': 'Webview note', + 'app.openhumanLink.accounts.intro': 'परिचय', + 'app.openhumanLink.accounts.webviewNote': 'वेबव्यू नोट', 'app.openhumanLink.billing.openDashboard': 'डैशबोर्ड खोलें', 'app.openhumanLink.billing.stayOnTrial': 'ट्रायल पर रहें', - 'app.openhumanLink.billing.trialCredit': 'Trial credit', - 'app.openhumanLink.billing.trialDesc': 'Trial desc', + 'app.openhumanLink.billing.trialCredit': 'ट्रायल क्रेडिट', + 'app.openhumanLink.billing.trialDesc': 'ट्रायल विवरण', 'app.openhumanLink.defaultBody': - 'Not ready in the popup yet. Open the full settings page when you need it.', - 'app.openhumanLink.discord.intro': 'Intro', + 'पॉपअप में अभी तैयार नहीं है। जब आवश्यकता हो तो पूर्ण सेटिंग्स पृष्ठ खोलें।', + 'app.openhumanLink.discord.intro': 'परिचय', 'app.openhumanLink.discord.openInvite': 'इनवाइट खोलें', - 'app.openhumanLink.discord.perk1': 'Perk1', - 'app.openhumanLink.discord.perk2': 'Perk2', - 'app.openhumanLink.discord.perk3': 'Perk3', - 'app.openhumanLink.discord.perk4': 'Perk4', + 'app.openhumanLink.discord.perk1': 'लाभ 1', + 'app.openhumanLink.discord.perk2': 'लाभ 2', + 'app.openhumanLink.discord.perk3': 'लाभ 3', + 'app.openhumanLink.discord.perk4': 'लाभ 4', 'app.openhumanLink.done': 'हो गया', 'app.openhumanLink.loadingChannelSetup': 'चैनल सेटअप लोड हो रहा है', 'app.openhumanLink.maybeLater': 'शायद बाद में', 'app.openhumanLink.notifications.asking': 'OS से पूछ रहे हैं…', 'app.openhumanLink.notifications.blocked': 'ब्लॉक्ड', - 'app.openhumanLink.notifications.blockedStep1': 'Blocked step1', - 'app.openhumanLink.notifications.blockedStep2': 'Blocked step2', - 'app.openhumanLink.notifications.blockedStep3': 'Blocked step3', - 'app.openhumanLink.notifications.intro': 'Intro', - 'app.openhumanLink.notifications.promptHint': 'Prompt hint', + 'app.openhumanLink.notifications.blockedStep1': 'ब्लॉक्ड चरण 1', + 'app.openhumanLink.notifications.blockedStep2': 'ब्लॉक्ड चरण 2', + 'app.openhumanLink.notifications.blockedStep3': 'ब्लॉक्ड चरण 3', + 'app.openhumanLink.notifications.intro': 'परिचय', + 'app.openhumanLink.notifications.promptHint': 'प्रॉम्प्ट संकेत', 'app.openhumanLink.notifications.retry': 'टेस्ट नोटिफिकेशन फिर भेजें', 'app.openhumanLink.notifications.send': 'टेस्ट नोटिफिकेशन भेजें', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'भेजा नहीं जा सका: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'टेस्ट नोटिफ़िकेशन भेज दिया गया। यदि आपको प्राप्त नहीं हुआ, तो System Settings → Notifications → OpenHuman पर जाएँ, Allow Notifications चालू करें, और Banner Style को Persistent पर सेट करें।', 'app.openhumanLink.skipForNow': 'अभी के लिए स्किप करें', 'app.openhumanLink.telegramUnavailable': 'Telegram उपलब्ध नहीं', 'app.openhumanLink.title.accounts': 'अपने ऐप्स कनेक्ट करें', @@ -317,11 +319,11 @@ const hi3: TranslationMap = { 'app.openhumanLink.title.discord': 'कम्युनिटी जॉइन करें', 'app.openhumanLink.title.messaging': 'चैट चैनल कनेक्ट करें', 'app.openhumanLink.title.notifications': 'नोटिफिकेशन की अनुमति दें', - 'app.persistRehydration.body': 'Body', - 'app.persistRehydration.heading': 'Heading', + 'app.persistRehydration.body': 'विवरण', + 'app.persistRehydration.heading': 'शीर्षक', 'app.persistRehydration.resetCta': 'रीसेट हो रहा है…', 'app.persistRehydration.resetting': 'रीसेट हो रहा है…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'OpenHuman आरंभ हो रहा है...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'अपडेट के दौरान कुछ गड़बड़ हो गई।', 'app.update.header.default': 'अपडेट', @@ -331,11 +333,11 @@ const hi3: TranslationMap = { 'app.update.header.restarting': 'रीस्टार्ट हो रहा है…', 'app.update.later': 'बाद में', 'app.update.newVersionReady': 'नया वर्जन इन्स्टॉल के लिए तैयार है।', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} डाउनलोड हुआ', 'app.update.progress.installing': 'नया वर्जन इन्स्टॉल हो रहा है…', 'app.update.progress.restarting': 'ऐप फिर से लॉन्च हो रहा है…', 'app.update.progress.working': '{percent}%', - 'app.update.restartNote': 'Restart note', + 'app.update.restartNote': 'पुनः आरंभ नोट', 'app.update.restartNow': 'अभी रीस्टार्ट करें', 'app.update.versionReady': 'वर्जन {newVersion} इन्स्टॉल के लिए तैयार है।', 'channels.discord.accountLinked': 'अकाउंट लिंक हो गया', @@ -346,7 +348,7 @@ const hi3: TranslationMap = { 'channels.discord.linkTokenOnce': 'लिंक टोकन एक बार', 'channels.discord.picker.allPermissionsOk': 'बॉट के पास इस चैनल में सभी ज़रूरी परमिशन हैं।', 'channels.discord.picker.botNotInServers': 'बॉट किसी सर्वर में नहीं है', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'श्रेणी', 'channels.discord.picker.channel': 'चैनल', 'channels.discord.picker.checkingPermissions': 'परमिशन चेक हो रही हैं', 'channels.discord.picker.loadingChannels': 'चैनल लोड हो रहे हैं...', @@ -357,7 +359,7 @@ const hi3: TranslationMap = { 'channels.discord.picker.selectChannel': 'एक चैनल चुनें', 'channels.discord.picker.selectServer': 'एक सर्वर चुनें', 'channels.discord.picker.server': 'सर्वर', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'सर्वर और चैनल चयन', 'channels.discord.savedRestartRequired': 'चैनल सेव हो गया। एक्टिवेट करने के लिए ऐप रीस्टार्ट करें।', 'channels.telegram.connect': 'कनेक्ट करें', diff --git a/app/src/lib/i18n/chunks/hi-4.ts b/app/src/lib/i18n/chunks/hi-4.ts index 98554d6e6..713bda55e 100644 --- a/app/src/lib/i18n/chunks/hi-4.ts +++ b/app/src/lib/i18n/chunks/hi-4.ts @@ -2,105 +2,105 @@ import type { TranslationMap } from '../types'; // Hindi (हिन्दी) chunk 4/5. Translated from chunks/en-4.ts. const hi4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'स्वीकृत करें और सदस्यता समाप्त करें', + 'chat.unsubscribeApproval.approved': '✓ सफलतापूर्वक सदस्यता समाप्त की गई।', 'chat.unsubscribeApproval.denied': '✕ रिक्वेस्ट नामंज़ूर।', 'chat.unsubscribeApproval.deny': 'नामंज़ूर करें', 'chat.unsubscribeApproval.processing': 'प्रोसेस हो रहा है...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'सदस्यता समाप्ति अनुरोध', 'commandPalette.ariaLabel': 'कमांड पैलेट', - 'commandPalette.description': 'Description', + 'commandPalette.description': 'विवरण', 'commandPalette.label': 'कमांड', 'commandPalette.noResults': 'कोई रिज़ल्ट नहीं', 'commandPalette.placeholder': 'कोई कमांड टाइप करें या सर्च करें…', 'commandPalette.searchAria': 'कमांड सर्च करें', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'सभी शॉर्टकट के लिए ? दबाएँ', 'commandPalette.title': 'कमांड पैलेट', 'composio.connect.additionalConfigRequired': 'अतिरिक्त कॉन्फिग ज़रूरी है', 'composio.connect.atlassianSubdomainHint': 'acme', - 'composio.connect.atlassianSubdomainLabel': 'Atlassian subdomain label', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.atlassianSubdomainLabel': 'Atlassian सबडोमेन लेबल', + 'composio.connect.connect': 'कनेक्ट करें', + 'composio.connect.connectionFailed': 'कनेक्शन विफल (स्थिति: {status})।', 'composio.connect.disconnectFailed': 'डिसकनेक्ट विफल: {msg}', 'composio.connect.disconnecting': 'डिसकनेक्ट हो रहा है…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'अपना कनेक्ट करें', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'खाता। हम एक ब्राउज़र विंडो खोलेंगे, आप वहाँ एक्सेस स्वीकृत करते हैं, और यह ऐप कनेक्शन को स्वचालित रूप से पहचान लेगा।', + 'composio.connect.isConnected': 'कनेक्ट है।', + 'composio.connect.manage': 'प्रबंधित करें', + 'composio.connect.needsSubdomain': 'कनेक्ट करने के लिए', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'अपना Atlassian सबडोमेन दर्ज करें (जैसे acme.atlassian.net के लिए acme) और पुनः प्रयास करें।', + 'composio.connect.oauthComplete': 'OAuth पूरा करने के लिए…', 'composio.connect.oauthTimeout': 'OAuth टाइमआउट', 'composio.connect.permissions': 'परमिशन', 'composio.connect.permissionsDefault': 'Read + Write डिफ़ॉल्ट रूप से चालू', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'उजागर कर सकता है', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'OpenHuman की अपनी एजेंट अनुमतियाँ नीचे पढ़ें, लिखें और एडमिन टॉगल के रूप में नियंत्रित होती हैं।', 'composio.connect.reopenBrowser': 'ब्राउज़र फिर से खोलें', 'composio.connect.requestingUrl': 'कनेक्ट URL माँगा जा रहा है…', 'composio.connect.retryConnection': 'कनेक्शन फिर से करें', 'composio.connect.scopeLoadError': 'स्कोप प्रेफरेंस लोड नहीं हो पाई: {msg}', 'composio.connect.scopeSaveError': '{key} स्कोप सेव नहीं हो पाया: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'केवल छोटा सबडोमेन दर्ज करें (जैसे "acme"), पूर्ण URL नहीं। इसमें केवल अक्षर, संख्याएँ और हाइफ़न होने चाहिए।', 'composio.connect.subdomainRequired': 'जारी रखने के लिए अपना Atlassian subdomain डालें।', - 'composio.connect.wabaIdLabel': 'Waba id label', + 'composio.connect.wabaIdLabel': 'Waba आईडी लेबल', 'composio.connect.wabaIdRequired': 'जारी रखने के लिए अपना WhatsApp Business Account ID (WABA ID) डालें।', - 'composio.connect.waitingFor': 'Waiting for', - 'composio.connect.waitingHint': 'Waiting hint', + 'composio.connect.waitingFor': 'प्रतीक्षा कर रहा है', + 'composio.connect.waitingHint': 'प्रतीक्षा संकेत', 'composio.triggers.heading': 'ट्रिगर', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'से इवेंट्स सुनें', + 'composio.triggers.loadError': 'ट्रिगर्स लोड नहीं हो सके', 'composio.triggers.needsConfiguration': 'कॉन्फिगरेशन ज़रूरी है', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'वर्तमान में कोई ट्रिगर उपलब्ध नहीं है', 'conversations.taskKanban.moveLeft': 'बाएं ले जाएं', 'conversations.taskKanban.moveRight': 'दाएं ले जाएं', 'conversations.taskKanban.title': 'टास्क', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'टर्न', 'conversations.toolTimeline.workerThread': 'वर्कर थ्रेड', - 'daemon.serviceBlockingGate.body': 'Body', - 'daemon.serviceBlockingGate.downloadHint': 'Download hint', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.body': 'विवरण', + 'daemon.serviceBlockingGate.downloadHint': 'डाउनलोड संकेत', + 'daemon.serviceBlockingGate.downloadLatest': 'नवीनतम संस्करण डाउनलोड करें', + 'daemon.serviceBlockingGate.retryCore': 'कोर पुनः प्रयास करें', 'daemon.serviceBlockingGate.retryFailed': 'फिर से कोशिश विफल। लेटेस्ट ऐप बिल्ड डाउनलोड करके दोबारा कोशिश करें।', 'daemon.serviceBlockingGate.retrying': 'फिर से कोशिश हो रही है...', 'daemon.serviceBlockingGate.title': 'OpenHuman कोर उपलब्ध नहीं है', - 'home.banners.discordSubtitle': 'Discord subtitle', + 'home.banners.discordSubtitle': 'Discord उपशीर्षक', 'home.banners.discordTitle': 'हमारा Discord जॉइन करें', 'home.banners.earlyBirdDismiss': 'अर्ली बर्ड बैनर हटाएं', - 'home.banners.earlyBirdFirstSub': 'first subscription.', - 'home.banners.earlyBirdOn': 'Early bird on', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', - 'home.banners.earlyBirdUseCode': 'Early bird use code', - 'home.banners.getSubscription': 'get a subscription', - 'home.banners.promoCreditsBody': 'Promo credits body', + 'home.banners.earlyBirdFirstSub': 'पहली सदस्यता।', + 'home.banners.earlyBirdOn': 'अर्ली बर्ड चालू', + 'home.banners.earlyBirdTitle': 'पहले 1,000 उपयोगकर्ताओं को 60% की छूट मिलती है।', + 'home.banners.earlyBirdUseCode': 'अर्ली बर्ड कोड का उपयोग करें', + 'home.banners.getSubscription': 'सदस्यता लें', + 'home.banners.promoCreditsBody': 'प्रोमो क्रेडिट विवरण', 'home.banners.promoCreditsTitle': '{amount}', - 'home.banners.promoCreditsUsage': 'Promo credits usage', + 'home.banners.promoCreditsUsage': 'प्रोमो क्रेडिट उपयोग', 'intelligence.memoryChunk.detail.chunk': 'चंक', 'intelligence.memoryChunk.detail.copyChunkId': 'Chunk ID कॉपी करें', 'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024dim', 'intelligence.memoryChunk.detail.noEmbedding': 'कोई एम्बेडिंग नहीं', 'intelligence.memoryChunk.letterhead.from': 'से', 'intelligence.memoryChunk.letterhead.to': 'को', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', - 'intelligence.memoryChunk.mentioned.heading': 'm e n t i o n e d', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', - 'intelligence.memoryChunk.scoreBars.heading': 'w h y k e p t', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 चंक', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} चंक', + 'intelligence.memoryChunk.mentioned.heading': 'उल्लेखित', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} स्कोर {pct} प्रतिशत', + 'intelligence.memoryChunk.scoreBars.atThreshold': '{threshold} पर', + 'intelligence.memoryChunk.scoreBars.dropped': 'हटाया गया', + 'intelligence.memoryChunk.scoreBars.heading': 'क्यों रखा', + 'intelligence.memoryChunk.scoreBars.kept': 'रखा गया', + 'intelligence.memoryText.entityTypePrefix': 'इकाई प्रकार', 'intelligence.screenDebug.active': 'एक्टिव', 'intelligence.screenDebug.app': 'ऐप', 'intelligence.screenDebug.bounds': 'बाउंड्स', 'intelligence.screenDebug.captureAlt': 'कैप्चर टेस्ट रिज़ल्ट', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'विफल', + 'intelligence.screenDebug.captureSuccess': 'सफल', 'intelligence.screenDebug.captureTest': 'कैप्चर टेस्ट', 'intelligence.screenDebug.capturing': 'कैप्चर हो रहा है', 'intelligence.screenDebug.frames': 'फ्रेम', @@ -109,7 +109,7 @@ const hi4: TranslationMap = { 'intelligence.screenDebug.mode': 'मोड', 'intelligence.screenDebug.permAccessibility': 'Accessibility परमिशन', 'intelligence.screenDebug.permInput': 'इनपुट परमिशन', - 'intelligence.screenDebug.permScreen': 'Accessibility', + 'intelligence.screenDebug.permScreen': 'स्क्रीन रिकॉर्डिंग अनुमति', 'intelligence.screenDebug.permissions': 'परमिशन', 'intelligence.screenDebug.platformNotSupported': 'प्लेटफॉर्म सपोर्टेड नहीं', 'intelligence.screenDebug.recentVisionSummaries': 'हाल के विज़न समरीज़', @@ -122,59 +122,59 @@ const hi4: TranslationMap = { 'intelligence.screenDebug.unknown': 'अज्ञात', 'intelligence.screenDebug.visionQueue': 'विज़न क्यू', 'intelligence.screenDebug.visionState': 'विज़न स्टेट', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': 'बातचीतों में 1 सक्रिय बोर्ड', + 'intelligence.tasks.activeBoardOther': 'बातचीतों में {count} सक्रिय बोर्ड', 'intelligence.tasks.empty': 'अभी कोई एजेंट टास्क बोर्ड नहीं', - 'intelligence.tasks.emptyHint': 'Empty hint', + 'intelligence.tasks.emptyHint': 'खाली संकेत', 'intelligence.tasks.failedToLoad': 'लोड नहीं हो पाया', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'लाइव', 'intelligence.tasks.loadingBoards': 'टास्क बोर्ड लोड हो रहे हैं…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'थ्रेड {thread}', 'notifications.card.dismiss': 'नोटिफिकेशन हटाएं', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'महत्व: {pct}%', 'notifications.center.empty': 'अभी कोई नोटिफिकेशन नहीं', - 'notifications.center.emptyHint': 'Empty hint', + 'notifications.center.emptyHint': 'खाली संकेत', 'notifications.center.filterAll': 'सभी फिल्टर', 'notifications.center.markAllRead': 'सभी पढ़ा हुआ मार्क करें', 'notifications.center.title': 'नोटिफिकेशन', 'oauth.button.connecting': 'कनेक्ट हो रहा है...', 'oauth.login.continueWith': 'के साथ जारी रखें', - 'onboarding.contextGathering.buildingDesc': 'Building desc', + 'onboarding.contextGathering.buildingDesc': 'बिल्डिंग विवरण', 'onboarding.contextGathering.buildingProfile': 'आपकी प्रोफ़ाइल बन रही है...', 'onboarding.contextGathering.continueToChat': 'चैट पर जाएं', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'हम अभी आपकी पूरी प्रोफ़ाइल नहीं बना सके, लेकिन कोई बात नहीं — आप जारी रख सकते हैं और आपकी प्रोफ़ाइल समय के साथ बनती जाएगी।', 'onboarding.contextGathering.title': 'कॉन्टेक्स्ट गैदरिंग', - 'openhuman.team_list_teams': 'Team list teams', + 'openhuman.team_list_teams': 'टीम सूची टीमें', 'overlay.ariaAttention': 'ध्यान संदेश', 'overlay.ariaOrb': 'OpenHuman ओवरले', 'overlay.ariaVoiceActive': 'वॉइस इनपुट एक्टिव', 'overlay.orbTitle': 'मूव करने के लिए खींचें · पोज़िशन रीसेट के लिए डबल-क्लिक करें', 'pages.settings.account.connections': 'कनेक्शन', - 'pages.settings.account.connectionsDesc': 'Connections desc', + 'pages.settings.account.connectionsDesc': 'कनेक्शन विवरण', 'pages.settings.account.privacy': 'प्राइवेसी', - 'pages.settings.account.privacyDesc': 'Privacy desc', + 'pages.settings.account.privacyDesc': 'गोपनीयता विवरण', 'pages.settings.account.recoveryPhrase': 'रिकवरी फ्रेज़', - 'pages.settings.account.recoveryPhraseDesc': 'Recovery phrase desc', + 'pages.settings.account.recoveryPhraseDesc': 'रिकवरी फ़्रेज़ विवरण', 'pages.settings.account.team': 'टीम', - 'pages.settings.account.teamDesc': 'Team desc', + 'pages.settings.account.teamDesc': 'टीम विवरण', 'pages.settings.accountSection.description': 'रिकवरी फ्रेज़, टीम, कनेक्शन और प्राइवेसी सेटिंग्स।', 'pages.settings.accountSection.title': 'अकाउंट', 'pages.settings.ai.llm': 'LLM', - 'pages.settings.ai.llmDesc': 'Llm desc', + 'pages.settings.ai.llmDesc': 'LLM विवरण', 'pages.settings.ai.voice': 'वॉइस', - 'pages.settings.ai.voiceDesc': 'Voice desc', + 'pages.settings.ai.voiceDesc': 'वॉइस विवरण', 'pages.settings.aiSection.description': 'लैंग्वेज मॉडल प्रोवाइडर, लोकल Ollama और वॉइस (STT / TTS)।', 'pages.settings.aiSection.title': 'AI', 'pages.settings.features.messagingChannels': 'मैसेजिंग चैनल', - 'pages.settings.features.messagingChannelsDesc': 'Messaging channels desc', + 'pages.settings.features.messagingChannelsDesc': 'मैसेजिंग चैनल विवरण', 'pages.settings.features.notifications': 'नोटिफिकेशन', - 'pages.settings.features.notificationsDesc': 'Notifications desc', + 'pages.settings.features.notificationsDesc': 'नोटिफ़िकेशन विवरण', 'pages.settings.features.screenAwareness': 'स्क्रीन अवेयरनेस', - 'pages.settings.features.screenAwarenessDesc': 'Screen awareness desc', + 'pages.settings.features.screenAwarenessDesc': 'स्क्रीन अवेयरनेस विवरण', 'pages.settings.features.tools': 'टूल्स', - 'pages.settings.features.toolsDesc': 'Tools desc', + 'pages.settings.features.toolsDesc': 'टूल्स विवरण', 'pages.settings.featuresSection.description': 'स्क्रीन अवेयरनेस, मैसेजिंग और टूल्स।', 'pages.settings.featuresSection.title': 'फीचर्स', 'privacy.dataKind.credentials': 'क्रेडेंशियल', @@ -182,27 +182,27 @@ const hi4: TranslationMap = { 'privacy.dataKind.diagnostics': 'डायग्नोस्टिक्स', 'privacy.dataKind.metadata': 'मेटाडेटा', 'privacy.dataKind.raw': 'रॉ', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'मेरे कंप्यूटर से क्या जाता है?', + 'rewards.community.achievementsUnlocked': '{total} में से {unlocked} उपलब्धियाँ अनलॉक हुईं', 'rewards.community.connectDiscord': 'Discord कनेक्ट करें', 'rewards.community.cumulativeTokens': 'कुल टोकन', 'rewards.community.currentStreak': 'मौजूदा स्ट्रीक', 'rewards.community.discordLinkedNotInGuild': 'Discord लिंक्ड, Guild में नहीं', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'सर्वर में शामिल हुए', 'rewards.community.discordNotLinked': 'Discord लिंक्ड नहीं', 'rewards.community.discordServer': 'Discord सर्वर', 'rewards.community.discordStatusUnavailable': 'Discord स्टेटस उपलब्ध नहीं', 'rewards.community.discordWaiting': 'Discord का इंतज़ार', - 'rewards.community.heroSubtitle': 'Hero subtitle', - 'rewards.community.heroTitle': 'Hero title', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.heroSubtitle': 'हीरो उपशीर्षक', + 'rewards.community.heroTitle': 'हीरो शीर्षक', + 'rewards.community.joinDiscord': 'Discord से जुड़ें', 'rewards.community.loadingRewards': 'रिवॉर्ड लोड हो रहे हैं…', 'rewards.community.locked': 'अनलॉक्ड', 'rewards.community.retrying': 'फिर से कोशिश हो रही है…', 'rewards.community.rolesAndRewards': 'रोल्स और रिवॉर्ड', 'rewards.community.streakDays': '{n}', 'rewards.community.syncPending': 'रिवॉर्ड सिंक पेंडिंग', - 'rewards.community.syncPendingDesc': 'Sync pending desc', + 'rewards.community.syncPendingDesc': 'सिंक लंबित विवरण', 'rewards.community.syncUnavailable': 'सिंक उपलब्ध नहीं', 'rewards.community.tryAgain': 'फिर से कोशिश हो रही है…', 'rewards.community.unknown': 'अज्ञात', @@ -213,21 +213,21 @@ const hi4: TranslationMap = { 'rewards.coupon.colReward': 'रिवॉर्ड', 'rewards.coupon.colStatus': 'स्टेटस', 'rewards.coupon.loadingHistory': 'रिवॉर्ड हिस्ट्री लोड हो रही है…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'अभी तक कोई रिवॉर्ड कोड रिडीम नहीं किया गया।', 'rewards.coupon.pending': 'पेंडिंग', 'rewards.coupon.placeholder': 'कूपन कोड', 'rewards.coupon.promoCredits': 'प्रोमो क्रेडिट', 'rewards.coupon.recentRedemptions': 'हाल के रिडेम्प्शन', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} स्वीकृत। आवश्यक कार्रवाई पूरी होने के बाद {amount} अनलॉक होगा।', + 'rewards.coupon.redeemButton': 'कोड रिडीम करें', + 'rewards.coupon.redeemSuccess': '{code} रिडीम किया गया। {amount} आपके क्रेडिट में जोड़ा गया।', 'rewards.coupon.redeemedCodes': 'रिडीम हुए कोड', 'rewards.coupon.redeeming': 'रिडीम हो रहा है...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', - 'rewards.coupon.subtitle': 'Subtitle', + 'rewards.coupon.statusApplied': 'लागू', + 'rewards.coupon.statusPendingAction': 'कार्रवाई लंबित', + 'rewards.coupon.statusRedeemed': 'रिडीम किया गया', + 'rewards.coupon.subtitle': 'उपशीर्षक', 'rewards.coupon.title': 'कूपन कोड रिडीम करें', 'rewards.referralSection.activity': 'रेफरल एक्टिविटी', 'rewards.referralSection.apply': 'लागू हो रहा है…', @@ -240,9 +240,9 @@ const hi4: TranslationMap = { 'rewards.referralSection.copyCode': 'कोड कॉपी करें', 'rewards.referralSection.copyFailed': 'कॉपी विफल', 'rewards.referralSection.haveCode': 'रेफरल कोड है?', - 'rewards.referralSection.haveCodeDesc': 'Have code desc', + 'rewards.referralSection.haveCodeDesc': 'कोड है विवरण', 'rewards.referralSection.linked': 'लिंक्ड', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(कोड {code})', 'rewards.referralSection.loading': 'रेफरल प्रोग्राम लोड हो रहा है…', 'rewards.referralSection.noReferrals': 'कोई रेफरल नहीं', 'rewards.referralSection.pendingReferrals': 'पेंडिंग रेफरल', @@ -251,22 +251,22 @@ const hi4: TranslationMap = { 'rewards.referralSection.statusCompleted': 'पूरा हुआ', 'rewards.referralSection.statusExpired': 'एक्सपायर हो गया', 'rewards.referralSection.statusJoined': 'जॉइन हुआ', - 'rewards.referralSection.subtitle': 'Subtitle', + 'rewards.referralSection.subtitle': 'उपशीर्षक', 'rewards.referralSection.title': 'दोस्तों को इनवाइट करें, क्रेडिट कमाएं', 'rewards.referralSection.totalEarned': 'कुल कमाया', 'rewards.referralSection.yourCode': 'आपका कोड', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'क्लाउड प्रदाता जोड़ें', 'settings.ai.addProvider': 'सेव हो रहा है…', 'settings.ai.apiKeyFieldLabel': 'API key फील्ड लेबल', 'settings.ai.apiKeyRequired': 'जारी रखने के लिए अपनी API key पेस्ट करें।', 'settings.ai.apiKeyStoredEncrypted': 'API key एन्क्रिप्टेड रूप में स्टोर है', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'स्टोर्ड key क्लियर करें', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'प्रदाता कनेक्ट करें', 'settings.ai.customRouting': 'कस्टम रूटिंग', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'रद्द करें', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'प्रदाता संपादित करें', 'settings.ai.llmProviders': 'LLM प्रोवाइडर', 'settings.ai.llmProvidersDesc': 'LLM providers desc', 'settings.ai.localOllama': 'लोकल (Ollama)', @@ -275,12 +275,12 @@ const hi4: TranslationMap = { 'settings.ai.providerLabel': 'प्रोवाइडर', 'settings.ai.routing': 'रूटिंग', 'settings.ai.routingCustom': 'कस्टम रूटिंग', - 'settings.ai.routingDefault': 'Default', - 'settings.ai.routingDesc': 'Routing desc', + 'settings.ai.routingDefault': 'डिफ़ॉल्ट', + 'settings.ai.routingDesc': 'रूटिंग विवरण', 'settings.ai.saveChanges': 'सेव हो रहा है…', 'settings.ai.saving': 'सेव हो रहा है…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'असहेजा परिवर्तन', + 'settings.ai.unsavedChanges': 'असहेजे परिवर्तन', 'settings.ai.workloadGroupBackground': 'बैकग्राउंड वर्कलोड ग्रुप', 'settings.ai.workloadGroupChat': 'चैट वर्कलोड ग्रुप', 'settings.autocomplete.appFilter.acceptSuggestion': 'सुझाव एक्सेप्ट करें', @@ -294,23 +294,23 @@ const hi4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'रनटाइम', 'settings.autocomplete.appFilter.test': 'टेस्ट', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count} स्वीकृत कम्प्लीशन संग्रहीत — भविष्य के सुझावों को निजीकृत करने के लिए उपयोग किया गया।', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count} स्वीकृत कम्प्लीशन संग्रहीत — भविष्य के सुझावों को निजीकृत करने के लिए उपयोग किया गया।', 'settings.autocomplete.completionStyle.clearHistory': 'क्लियर हो रहा है…', 'settings.autocomplete.completionStyle.clearing': 'क्लियर हो रहा है…', - 'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)', + 'settings.autocomplete.completionStyle.debounce': 'डिबाउंस (ms)', 'settings.autocomplete.completionStyle.enabled': 'चालू है', 'settings.autocomplete.completionStyle.maxChars': 'मैक्स कैरेक्टर', 'settings.autocomplete.completionStyle.noHistory': 'अभी कोई एक्सेप्टेड कम्पलीशन नहीं। पर्सनलाइज़ेशन शुरू करने के लिए Tab से सुझाव एक्सेप्ट करें।', - 'settings.autocomplete.completionStyle.overlayTtl': 'Overlay TTL (ms)', + 'settings.autocomplete.completionStyle.overlayTtl': 'ओवरले TTL (ms)', 'settings.autocomplete.completionStyle.personalizationHistory': 'पर्सनलाइज़ेशन हिस्ट्री', 'settings.autocomplete.completionStyle.styleExamples': 'स्टाइल उदाहरण (एक प्रति लाइन)', 'settings.autocomplete.completionStyle.styleInstructions': 'स्टाइल इंस्ट्रक्शन', 'settings.billing.autoRecharge.addAmount': 'यह राशि जोड़ें', 'settings.billing.autoRecharge.addCard': 'कार्ड जोड़ें', - 'settings.billing.autoRecharge.amountHint': 'Amount hint', + 'settings.billing.autoRecharge.amountHint': 'राशि संकेत', 'settings.billing.autoRecharge.defaultCard': 'डिफ़ॉल्ट कार्ड', 'settings.billing.autoRecharge.lastRechargeFailed': 'आखिरी रिचार्ज विफल', 'settings.billing.autoRecharge.lastRecharged': 'आखिरी रिचार्ज', @@ -321,42 +321,42 @@ const hi4: TranslationMap = { 'settings.billing.autoRecharge.saveSettings': 'सेव हो रहा है…', 'settings.billing.autoRecharge.saving': 'सेव हो रहा है…', 'settings.billing.autoRecharge.setDefault': ':', - 'settings.billing.autoRecharge.subtitle': 'Subtitle', + 'settings.billing.autoRecharge.subtitle': 'उपशीर्षक', 'settings.billing.autoRecharge.title': 'ऑटो-रिचार्ज चालू करें', 'settings.billing.autoRecharge.toggleAriaLabel': 'ऑटो-रिचार्ज टॉगल करें', 'settings.billing.autoRecharge.weeklyLimit': 'साप्ताहिक खर्च सीमा', - 'settings.billing.history.desc': 'Desc', + 'settings.billing.history.desc': 'विवरण', 'settings.billing.history.empty': 'खाली है', 'settings.billing.history.openPortal': 'पोर्टल खोलें', 'settings.billing.history.posted': 'पोस्ट हुआ', - 'settings.billing.history.title': 'Title', + 'settings.billing.history.title': 'शीर्षक', 'settings.billing.inferenceBudget.cycleEnds': 'साइकल खत्म होती है', 'settings.billing.inferenceBudget.exhausted': 'खत्म हो गया', 'settings.billing.inferenceBudget.loadError': 'लोड एरर', - 'settings.billing.inferenceBudget.noBudgetDesc': 'No budget desc', + 'settings.billing.inferenceBudget.noBudgetDesc': 'कोई बजट विवरण नहीं', 'settings.billing.inferenceBudget.noRecurringBudget': 'कोई रेकरिंग बजट नहीं', 'settings.billing.inferenceBudget.remaining': 'बचा हुआ', 'settings.billing.inferenceBudget.tenHourCap': 'दस घंटे की सीमा', - 'settings.billing.inferenceBudget.title': 'Title', + 'settings.billing.inferenceBudget.title': 'शीर्षक', 'settings.billing.payAsYouGo.available': 'उपलब्ध', 'settings.billing.payAsYouGo.chargeCustomAmount': 'खुल रहा है…', - 'settings.billing.payAsYouGo.chooseTopUpDesc': 'Choose top up desc', - 'settings.billing.payAsYouGo.chooseTopUpTitle': 'Choose top up title', - 'settings.billing.payAsYouGo.creditBalanceDesc': 'Credit balance desc', - 'settings.billing.payAsYouGo.creditBalanceTitle': 'Credit balance title', + 'settings.billing.payAsYouGo.chooseTopUpDesc': 'टॉप अप चुनें विवरण', + 'settings.billing.payAsYouGo.chooseTopUpTitle': 'टॉप अप चुनें शीर्षक', + 'settings.billing.payAsYouGo.creditBalanceDesc': 'क्रेडिट बैलेंस विवरण', + 'settings.billing.payAsYouGo.creditBalanceTitle': 'क्रेडिट बैलेंस शीर्षक', 'settings.billing.payAsYouGo.customAmount': 'कस्टम राशि', 'settings.billing.payAsYouGo.enterAmount': 'राशि डालें', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'खोला जा रहा है', 'settings.billing.payAsYouGo.promotionalCredits': 'प्रमोशनल क्रेडिट', 'settings.billing.payAsYouGo.topUpBalance': 'बैलेंस टॉप-अप', 'settings.billing.payAsYouGo.topUpCredits': 'क्रेडिट टॉप अप करें', 'settings.billing.payAsYouGo.unableToLoad': 'बैलेंस लोड नहीं हो पाया।', 'settings.billing.subscription.annual': 'वार्षिक', 'settings.billing.subscription.billedAnnually': 'सालाना बिल होता है', - 'settings.billing.subscription.chooseSubtitle': 'Choose subtitle', - 'settings.billing.subscription.chooseTitle': 'Choose title', - 'settings.billing.subscription.cryptoDesc': 'Crypto desc', - 'settings.billing.subscription.cryptoQuestion': 'Crypto question', + 'settings.billing.subscription.chooseSubtitle': 'उपशीर्षक चुनें', + 'settings.billing.subscription.chooseTitle': 'शीर्षक चुनें', + 'settings.billing.subscription.cryptoDesc': 'क्रिप्टो विवरण', + 'settings.billing.subscription.cryptoQuestion': 'क्रिप्टो प्रश्न', 'settings.billing.subscription.current': 'मौजूदा', 'settings.billing.subscription.currentPlan': 'मौजूदा प्लान', 'settings.billing.subscription.monthly': 'मासिक', diff --git a/app/src/lib/i18n/chunks/hi-5.ts b/app/src/lib/i18n/chunks/hi-5.ts index 6fa295e70..7e29dbcc7 100644 --- a/app/src/lib/i18n/chunks/hi-5.ts +++ b/app/src/lib/i18n/chunks/hi-5.ts @@ -6,49 +6,50 @@ const hi5: TranslationMap = { 'settings.billing.subscription.upgrade': 'अपग्रेड करें', 'settings.billing.subscription.waiting': 'इंतज़ार हो रहा है', 'settings.billing.subscription.waitingPayment': 'पेमेंट का इंतज़ार', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': 'इस डिवाइस पर वर्तमान में एक Composio API कुंजी संग्रहीत है।', + 'settings.composio.apiKeyLabel': 'Composio API कुंजी', + 'settings.composio.apiKeyStored': 'API कुंजी संग्रहीत', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Backend मोड पर स्विच हुआ', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'app.composio.dev पर API कुंजी के साथ एक खाता', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'अपने व्यक्तिगत Composio खाते के माध्यम से प्रत्येक एकीकरण को फिर से लिंक करना', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'नोट: Composio ट्रिगर्स (रीयल-टाइम वेबहुक्स) डायरेक्ट मोड में अभी फायर नहीं होते — केवल सिंक्रोनस टूल कॉल्स', + 'settings.composio.confirmNeedItems': 'आपको चाहिए:', + 'settings.composio.confirmSwitch': 'मैं समझ गया, डायरेक्ट पर स्विच करें', + 'settings.composio.confirmTitle': '⚠️ डायरेक्ट मोड पर स्विच कर रहे हैं', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'आपके मौजूदा एकीकरण (Gmail, Slack, GitHub, आदि OpenHuman के माध्यम से लिंक किए गए) दिखाई नहीं देंगे — वे OpenHuman-प्रबंधित Composio टेनेंट में रहते हैं।', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio 250+ बाहरी ऐप्स को टूल्स के रूप में एकीकृत करता है जिन्हें आपका एजेंट कॉल कर सकता है। चुनें कि वे टूल कॉल कैसे रूट किए जाएँ।', 'settings.composio.modeDirect': 'डायरेक्ट (अपनी API key लाएं)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'कॉल सीधे backend.composio.dev पर जाती हैं। संप्रभु / ऑफ़लाइन-अनुकूल। टूल निष्पादन सिंक्रोनस रूप से कार्य करता है; रीयल-टाइम ट्रिगर वेबहुक्स अभी डायरेक्ट मोड में रूट नहीं हैं (फॉलो-अप मुद्दा)।', 'settings.composio.modeManaged': 'मैनेज्ड (OpenHuman मैनेज करेगा)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman हमारे बैकएंड के माध्यम से टूल कॉल्स को प्रॉक्सी करता है (अनुशंसित)। प्रमाणीकरण ब्रोकर किया जाता है; आप कभी भी Composio API कुंजी पेस्ट नहीं करते। वेबहुक्स पूरी तरह से रूट किए जाते हैं।', 'settings.composio.routingMode': 'रूटिंग मोड', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + 'सहेजने में विफल। डायरेक्ट मोड के लिए गैर-रिक्त API कुंजी आवश्यक है।', 'settings.composio.saving': 'सेव हो रहा है…', - 'settings.composio.switching': 'Switching…', - 'settings.cron.jobs.desc': 'Desc', + 'settings.composio.switching': 'स्विच हो रहा है…', + 'settings.cron.jobs.desc': 'विवरण', 'settings.cron.jobs.empty': 'कोई कोर cron job नहीं मिला।', 'settings.cron.jobs.lastStatus': 'आखिरी स्टेटस', 'settings.cron.jobs.loading': 'Cron jobs लोड हो रही हैं...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'रन लोड हो रहे हैं', 'settings.cron.jobs.nextRun': 'अगला रन', 'settings.cron.jobs.pause': 'रोकें', 'settings.cron.jobs.paused': 'चालू है', 'settings.cron.jobs.recentRuns': 'हाल के रन', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'हटाया जा रहा है', 'settings.cron.jobs.resume': 'फिर शुरू करें', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'अभी चल रहा है', 'settings.cron.jobs.saving': 'सेव हो रहा है…', 'settings.cron.jobs.schedule': 'शेड्यूल', 'settings.cron.jobs.title': 'कोर Cron Jobs', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'रन देखें', 'settings.localModel.deviceCapability.active': 'एक्टिव', 'settings.localModel.deviceCapability.appliedTier': 'लागू टियर', 'settings.localModel.deviceCapability.applying': 'लागू हो रहा है', @@ -58,7 +59,7 @@ const hi5: TranslationMap = { 'settings.localModel.deviceCapability.customModelIds': 'कस्टम मॉडल IDs', 'settings.localModel.deviceCapability.detected': 'डिटेक्ट हुआ', 'settings.localModel.deviceCapability.disabled': 'बंद है', - 'settings.localModel.deviceCapability.disabledDesc': 'Disabled desc', + 'settings.localModel.deviceCapability.disabledDesc': 'अक्षम विवरण', 'settings.localModel.deviceCapability.downloadingModels': '(मॉडल डाउनलोड हो रहे हैं)', 'settings.localModel.deviceCapability.downloadingSetupDesc': 'OllamaSetup इन्स्टॉलर (~2 GB) डाउनलोड और अनपैक हो रहा है। पहली इन्स्टॉल पर एक मिनट लग सकता है।', @@ -67,10 +68,11 @@ const hi5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Ollama इन्स्टॉल विफल', 'settings.localModel.deviceCapability.installFailedDesc': 'Ollama यूज़ेबल होने से पहले इन्स्टॉलर बंद हो गया। दोबारा कोशिश करें या ollama.com से मैन्युअली इन्स्टॉल करें।', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'पहले Ollama चलाएँ।', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'स्थानीय टियर बाहरी रूप से प्रबंधित Ollama एंडपॉइंट पर निर्भर हैं। इसे स्वयं प्रारंभ करें, अपने इच्छित मॉडल खींचें, और जब तक रनटाइम पहुँच योग्य न हो तब तक "Disabled (cloud fallback)" का उपयोग करते रहें।', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'इस टियर का उपयोग करने के लिए पहले Ollama चलाएँ', 'settings.localModel.deviceCapability.installingOllama': 'Ollama इन्स्टॉल हो रहा है', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'डिवाइस जानकारी लोड हो रही है', 'settings.localModel.deviceCapability.localAiDisabled': @@ -87,13 +89,13 @@ const hi5: TranslationMap = { 'settings.localModel.download.capabilityAssets': 'कैपेबिलिटी असेट्स', 'settings.localModel.download.downloading': 'डाउनलोड हो रहा है...', 'settings.localModel.download.embeddingPlaceholder': 'एक इनपुट स्ट्रिंग प्रति लाइन...', - 'settings.localModel.download.noThinkMode': 'No think mode', + 'settings.localModel.download.noThinkMode': 'नो थिंक मोड', 'settings.localModel.download.promptPlaceholder': 'कोई भी prompt टाइप करें और लोकल मॉडल पर चलाएं...', - 'settings.localModel.download.quantizationPref': 'Quantization pref', + 'settings.localModel.download.quantizationPref': 'क्वांटाइज़ेशन प्राथमिकता', 'settings.localModel.download.runEmbeddingTest': 'चल रहा है...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'प्रॉम्प्ट टेस्ट चलाएँ', + 'settings.localModel.download.runSummaryTest': 'सारांश टेस्ट चलाएँ', 'settings.localModel.download.runTranscriptionTest': 'चल रहा है...', 'settings.localModel.download.runTtsTest': 'चल रहा है...', 'settings.localModel.download.runVisionTest': 'चल रहा है...', @@ -116,18 +118,18 @@ const hi5: TranslationMap = { 'settings.localModel.status.artifact': 'आर्टिफैक्ट', 'settings.localModel.status.backend': 'बैकएंड', 'settings.localModel.status.binary': 'बाइनरी', - 'settings.localModel.status.bootstrapResume': 'Bootstrap / Resume', + 'settings.localModel.status.bootstrapResume': 'बूटस्ट्रैप / फिर से शुरू', 'settings.localModel.status.checking': 'चेक हो रहा है...', 'settings.localModel.status.checkingOllama': 'Ollama चेक हो रहा है', 'settings.localModel.status.customLocation': 'कस्टम लोकेशन', - 'settings.localModel.status.customLocationDesc': 'Custom location desc', + 'settings.localModel.status.customLocationDesc': 'कस्टम स्थान विवरण', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'यह सत्यापित करने के लिए "Run Diagnostics" पर क्लिक करें कि Ollama चल रहा है और मॉडल इंस्टॉल हैं।', 'settings.localModel.status.downloadingUnknown': 'डाउनलोड हो रहा है (साइज़ अज्ञात)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'एक्सपेक्टेड मॉडल', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', - 'settings.localModel.status.generationTps': 'Generation TPS', + 'settings.localModel.status.forceRebootstrap': 'बल पुनः बूटस्ट्रैप', + 'settings.localModel.status.generationTps': 'जनरेशन TPS', 'settings.localModel.status.hideErrorDetails': 'एरर डिटेल्स छुपाएं', 'settings.localModel.status.installManually': 'मैन्युअली इन्स्टॉल करें', 'settings.localModel.status.installManuallyFrom': 'यहाँ से मैन्युअली इन्स्टॉल करें', @@ -136,16 +138,16 @@ const hi5: TranslationMap = { 'settings.localModel.status.installing': 'इन्स्टॉल हो रहा है...', 'settings.localModel.status.installingOllama': 'Ollama रनटाइम इन्स्टॉल हो रहा है...', 'settings.localModel.status.issues': 'समस्याएं', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '{count} समस्या(एँ) मिलीं', 'settings.localModel.status.lastLatency': 'आखिरी लेटेंसी', 'settings.localModel.status.model': 'मॉडल', 'settings.localModel.status.notFound': 'नहीं मिला', - 'settings.localModel.status.notRunning': 'Not running', - 'settings.localModel.status.ollamaBinaryPath': 'Ollama binary path', + 'settings.localModel.status.notRunning': 'नहीं चल रहा', + 'settings.localModel.status.ollamaBinaryPath': 'Ollama बाइनरी पथ', 'settings.localModel.status.ollamaDiagnostics': 'Ollama डायग्नोस्टिक्स', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Ollama रनटाइम अनुपलब्ध', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman अब Ollama को एक बाहरी इन्फ़रेंस रनटाइम के रूप में मानता है। अपना खुद का Ollama सर्वर शुरू करें, अपने इच्छित मॉडल खींचें, और वर्कलोड रूटिंग को इसकी ओर इंगित करें।', 'settings.localModel.status.progress': 'प्रगति', 'settings.localModel.status.provider': 'प्रोवाइडर', 'settings.localModel.status.retryBootstrap': 'Bootstrap फिर से करें', @@ -164,37 +166,37 @@ const hi5: TranslationMap = { 'settings.localModel.status.unavailable': 'उपलब्ध नहीं', 'settings.localModel.status.working': 'काम हो रहा है...', 'settings.mascot.active': 'एक्टिव', - 'settings.mascot.characterDesc': 'Character desc', - 'settings.mascot.characterHeading': 'Character heading', - 'settings.mascot.colorDesc': 'Color desc', - 'settings.mascot.colorHeading': 'Color heading', + 'settings.mascot.characterDesc': 'कैरेक्टर विवरण', + 'settings.mascot.characterHeading': 'कैरेक्टर शीर्षक', + 'settings.mascot.colorDesc': 'रंग विवरण', + 'settings.mascot.colorHeading': 'रंग शीर्षक', 'settings.mascot.loadingLibrary': 'OpenHuman लाइब्रेरी लोड हो रही है…', 'settings.mascot.localDefault': 'लोकल OpenHuman (डिफ़ॉल्ट)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'अभी तक कोई OpenHuman कैरेक्टर उपलब्ध नहीं है', 'settings.mascot.noColorVariants': 'कोई कलर वेरिएंट नहीं', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'अनुशंसित', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'समझदारी भरा डिफ़ॉल्ट — हर रन पर अतिरिक्त टोकन खर्च किए बिना अच्छी निरंतरता।', + 'settings.memoryWindow.balanced.label': 'संतुलित', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'OpenHuman हर नए एजेंट रन में कितना याद किया गया संदर्भ इंजेक्ट करता है। बड़ी विंडोज़ पिछली बातचीत के बारे में अधिक जागरूक लगती हैं लेकिन हर रन पर अधिक टोकन का उपयोग करती हैं — और अधिक लागत आती है।', + 'settings.memoryWindow.extended.badge': 'अधिक संदर्भ', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'प्रत्येक रन में अधिक दीर्घकालिक मेमोरी इंजेक्ट होती है। प्रति टर्न उच्च टोकन लागत।', + 'settings.memoryWindow.extended.label': 'विस्तारित', + 'settings.memoryWindow.maximum.badge': 'सर्वोच्च लागत', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'सबसे बड़ी सुरक्षित विंडो। सर्वोत्तम निरंतरता, हर रन पर काफी अधिक टोकन बिल।', + 'settings.memoryWindow.maximum.label': 'अधिकतम', + 'settings.memoryWindow.minimal.badge': 'सबसे सस्ता', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'सबसे छोटी मेमोरी विंडो। सबसे सस्ता, सबसे तेज़, रनों के बीच कम से कम निरंतरता।', + 'settings.memoryWindow.minimal.label': 'न्यूनतम', 'settings.memoryWindow.title': 'लॉन्ग-टर्म मेमोरी विंडो', - 'settings.screenIntel.permissions.accessibility': 'Accessibility', - 'settings.screenIntel.permissions.grantHint': 'Grant hint', - 'settings.screenIntel.permissions.inputMonitoring': 'Input Monitoring', - 'settings.screenIntel.permissions.macosAppliesPrivacy': 'Macos applies privacy', + 'settings.screenIntel.permissions.accessibility': 'एक्सेसिबिलिटी', + 'settings.screenIntel.permissions.grantHint': 'स्वीकृति संकेत', + 'settings.screenIntel.permissions.inputMonitoring': 'इनपुट मॉनिटरिंग', + 'settings.screenIntel.permissions.macosAppliesPrivacy': 'macOS गोपनीयता लागू करता है', 'settings.screenIntel.permissions.openInputMonitoring': 'रिक्वेस्ट हो रही है…', 'settings.screenIntel.permissions.refreshStatus': 'रिफ्रेश हो रहा है…', 'settings.screenIntel.permissions.refreshing': 'रिफ्रेश हो रहा है…', @@ -203,29 +205,29 @@ const hi5: TranslationMap = { 'settings.screenIntel.permissions.requesting': 'रिक्वेस्ट हो रही है…', 'settings.screenIntel.permissions.restartRefresh': 'कोर रीस्टार्ट हो रहा है…', 'settings.screenIntel.permissions.restartingCore': 'कोर रीस्टार्ट हो रहा है…', - 'settings.screenIntel.permissions.screenRecording': 'Screen Recording', + 'settings.screenIntel.permissions.screenRecording': 'स्क्रीन रिकॉर्डिंग', 'settings.screenIntel.permissions.title': 'परमिशन', 'skills.card.moreActions': 'और एक्शन', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'अनुमत टूल्स', + 'skills.create.author': 'लेखक', 'skills.create.authorPlaceholder': 'आपका नाम', 'skills.create.commaSeparated': '(कॉमा से अलग करें)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'स्किल बनाएँ', 'skills.create.createError': 'स्किल नहीं बन पाई', 'skills.create.creating': 'बन रहा है…', - 'skills.create.description': 'Description', + 'skills.create.description': 'विवरण', 'skills.create.descriptionPlaceholder': 'यह स्किल क्या करती है?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'लाइसेंस', + 'skills.create.name': 'नाम', 'skills.create.namePlaceholder': 'जैसे Trade Journal', 'skills.create.scope': 'स्कोप', 'skills.create.scopeProjectHint': '/.openhuman/skills/', 'skills.create.scopeUserHint': '~/.openhuman/skills//SKILL.md में लिखा जाता है — सभी वर्कस्पेस में उपलब्ध।', - 'skills.create.slugLabel': 'Slug label', + 'skills.create.slugLabel': 'स्लग लेबल', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'टैग्स', + 'skills.create.title': 'नया स्किल', 'skills.detail.allowedTools': 'अनुमत टूल्स', 'skills.detail.author': 'लेखक', 'skills.detail.bundledResources': 'बंडल्ड रिसोर्सेज़', @@ -234,21 +236,21 @@ const hi5: TranslationMap = { 'skills.detail.noBundledResources': 'कोई बंडल्ड रिसोर्स नहीं।', 'skills.detail.tags': 'टैग्स', 'skills.detail.warnings': 'चेतावनियाँ', - 'skills.install.fetchLog': 'Fetch log', + 'skills.install.fetchLog': 'फ़ेच लॉग', 'skills.install.installBtn': 'इन्स्टॉल हो रहा है…', 'skills.install.installComplete': 'इन्स्टॉल पूरा हुआ', 'skills.install.installing': 'इन्स्टॉल हो रहा है…', 'skills.install.parseWarnings': 'Parse चेतावनियाँ', 'skills.install.rawError': 'रॉ एरर', 'skills.install.timeoutHint': '(सेकंड, वैकल्पिक)', - 'skills.install.timeoutLabel': 'Timeout label', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', - 'skills.meetingBots.bannerDesc': 'Banner desc', - 'skills.meetingBots.bannerTitle': 'Banner title', + 'skills.install.timeoutLabel': 'टाइमआउट लेबल', + 'skills.install.title': 'URL से स्किल इंस्टॉल करें', + 'skills.install.urlLabel': 'स्किल URL', + 'skills.meetingBots.bannerDesc': 'बैनर विवरण', + 'skills.meetingBots.bannerTitle': 'बैनर शीर्षक', 'skills.meetingBots.busyTitle': 'OpenHuman व्यस्त है', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'जल्द आ रहा है', + 'skills.meetingBots.couldNotStartTitle': 'OpenHuman प्रारंभ नहीं हो सका', 'skills.meetingBots.displayName': 'डिस्प्ले नाम', 'skills.meetingBots.failedToStart': 'OpenHuman शुरू नहीं हो पाया।', 'skills.meetingBots.joiningMessage': @@ -256,22 +258,22 @@ const hi5: TranslationMap = { 'skills.meetingBots.joiningTitle': 'OpenHuman मीटिंग जॉइन कर रहा है', 'skills.meetingBots.meetingLink': 'मीटिंग लिंक', 'skills.meetingBots.modalAriaLabel': 'OpenHuman को मीटिंग में भेजें', - 'skills.meetingBots.modalDesc': 'Modal desc', + 'skills.meetingBots.modalDesc': 'मोडल विवरण', 'skills.meetingBots.modalTitle': 'OpenHuman को मीटिंग में भेजें', 'skills.meetingBots.newBadge': 'नया', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'भेजें', 'skills.meetingBots.starting': 'शुरू हो रहा है…', 'skills.resource.preview.closeAriaLabel': 'प्रीव्यू बंद करें', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'पूर्वावलोकन विफल', 'skills.resource.preview.loading': 'प्रीव्यू लोड हो रहा है…', 'skills.resource.tree.empty': 'कोई बंडल्ड रिसोर्स नहीं।', - 'skills.search.placeholder': 'Placeholder', - 'skills.setup.autocomplete.acceptKey': 'Accept key', - 'skills.setup.autocomplete.activeDesc': 'Active desc', + 'skills.search.placeholder': 'प्लेसहोल्डर', + 'skills.setup.autocomplete.acceptKey': 'स्वीकार कुंजी', + 'skills.setup.autocomplete.activeDesc': 'सक्रिय विवरण', 'skills.setup.autocomplete.activeTitle': 'Auto-Complete एक्टिव है', 'skills.setup.autocomplete.customizeSettings': 'सेटिंग्स कस्टमाइज़ करें', - 'skills.setup.autocomplete.debounce': 'Debounce', - 'skills.setup.autocomplete.description': 'Description', + 'skills.setup.autocomplete.debounce': 'डिबाउंस', + 'skills.setup.autocomplete.description': 'विवरण', 'skills.setup.autocomplete.enableBtn': 'चालू हो रहा है...', 'skills.setup.autocomplete.enableError': 'ऑटोकम्पलीट चालू नहीं हो पाया', 'skills.setup.autocomplete.enabling': 'चालू हो रहा है...', @@ -281,7 +283,7 @@ const hi5: TranslationMap = { 'skills.setup.autocomplete.stylePreset': 'स्टाइल प्रीसेट', 'skills.setup.autocomplete.stylePresetValue': 'Balanced (बाद में बदल सकते हैं)', 'skills.setup.autocomplete.title': 'टेक्स्ट Auto-Complete', - 'skills.setup.screenIntel.activeDesc': 'Active desc', + 'skills.setup.screenIntel.activeDesc': 'सक्रिय विवरण', 'skills.setup.screenIntel.activeTitle': 'Screen Intelligence चालू है', 'skills.setup.screenIntel.advancedSettings': 'एडवांस्ड सेटिंग्स', 'skills.setup.screenIntel.allGranted': 'सभी परमिशन मिल गईं', @@ -295,29 +297,29 @@ const hi5: TranslationMap = { 'skills.setup.screenIntel.enabling': 'चालू हो रहा है...', 'skills.setup.screenIntel.grant': 'खुल रहा है...', 'skills.setup.screenIntel.granted': 'मिल गई', - 'skills.setup.screenIntel.macosOnly': 'Macos only', + 'skills.setup.screenIntel.macosOnly': 'केवल macOS', 'skills.setup.screenIntel.opening': 'खुल रहा है...', - 'skills.setup.screenIntel.panicHotkey': 'Panic hotkey', - 'skills.setup.screenIntel.permAccessibility': 'Accessibility', - 'skills.setup.screenIntel.permInputMonitoring': 'Input Monitoring', - 'skills.setup.screenIntel.permScreenRecording': 'Screen Recording', - 'skills.setup.screenIntel.permissionsDesc': 'Permissions desc', + 'skills.setup.screenIntel.panicHotkey': 'पैनिक हॉटकी', + 'skills.setup.screenIntel.permAccessibility': 'एक्सेसिबिलिटी', + 'skills.setup.screenIntel.permInputMonitoring': 'इनपुट मॉनिटरिंग', + 'skills.setup.screenIntel.permScreenRecording': 'स्क्रीन रिकॉर्डिंग', + 'skills.setup.screenIntel.permissionsDesc': 'अनुमतियाँ विवरण', 'skills.setup.screenIntel.refreshStatus': 'स्टेटस रिफ्रेश करें', 'skills.setup.screenIntel.restartRefresh': 'रीस्टार्ट हो रहा है...', 'skills.setup.screenIntel.restarting': 'रीस्टार्ट हो रहा है...', 'skills.setup.screenIntel.stepEnable': 'स्किल चालू करें', 'skills.setup.screenIntel.stepPermissions': 'परमिशन दें', 'skills.setup.screenIntel.stepSuccess': 'तैयार है', - 'skills.setup.screenIntel.title': 'Screen Intelligence', + 'skills.setup.screenIntel.title': 'स्क्रीन इंटेलिजेंस', 'skills.setup.screenIntel.visionModel': 'विज़न मॉडल', 'skills.setup.voice.activation': 'एक्टिवेशन', 'skills.setup.voice.activeDescPrefix': 'Fn', 'skills.setup.voice.activeDescSuffix': 'Fn', 'skills.setup.voice.activeTitle': 'Voice Intelligence एक्टिव है', 'skills.setup.voice.customizeSettings': 'सेटिंग्स कस्टमाइज़ करें', - 'skills.setup.voice.downloadSttBtn': 'Download stt btn', - 'skills.setup.voice.enableDesc': 'Enable desc', - 'skills.setup.voice.hotkey': 'Hotkey', + 'skills.setup.voice.downloadSttBtn': 'STT डाउनलोड करें', + 'skills.setup.voice.enableDesc': 'सक्षम विवरण', + 'skills.setup.voice.hotkey': 'हॉटकी', 'skills.setup.voice.startBtn': 'शुरू हो रहा है...', 'skills.setup.voice.startError': 'वॉइस सर्वर शुरू नहीं हो पाया', 'skills.setup.voice.starting': 'शुरू हो रहा है...', @@ -328,47 +330,47 @@ const hi5: TranslationMap = { 'skills.setup.voice.sttNotReadyDesc': 'Voice Intelligence को ट्रांसक्रिप्शन के लिए लोकल Whisper मॉडल चाहिए। इसे Local Model सेटिंग्स से डाउनलोड करें।', 'skills.setup.voice.sttReady': 'Speech-to-text मॉडल तैयार है', - 'skills.setup.voice.sttReturnHint': 'Stt return hint', - 'skills.setup.voice.title': 'Voice Intelligence', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.setup.voice.sttReturnHint': 'STT रिटर्न संकेत', + 'skills.setup.voice.title': 'वॉइस इंटेलिजेंस', + 'skills.uninstall.couldNotUninstall': 'अनइंस्टॉल नहीं हो सका', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'यह स्किल डायरेक्टरी और उसके सभी बंडल किए गए संसाधनों को स्थायी रूप से हटा देता है। एजेंट अगले टर्न पर इसे देखना बंद कर देगा।', + 'skills.uninstall.title': 'अनइंस्टॉल', + 'skills.uninstall.uninstallBtn': 'अनइंस्टॉल', + 'skills.uninstall.uninstalling': 'अनइंस्टॉल हो रहा है…', 'upsell.global.limitMessage': 'जारी रखने के लिए अपना प्लान अपग्रेड करें या क्रेडिट टॉप अप करें', 'upsell.global.limitTitle': 'आप', 'upsell.global.nearLimitMessage': 'आपने अपनी उपयोग सीमा का {pct}% इस्तेमाल कर लिया है। ज़्यादा सीमा के लिए अपग्रेड करें।', 'upsell.global.nearLimitTitle': 'उपयोग सीमा के करीब', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'आपने अपनी साप्ताहिक सीमा प्राप्त कर ली है।{reset} सीमाओं से बचने के लिए अपनी योजना अपग्रेड करें या क्रेडिट टॉप अप करें।', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'आपने अपनी 10-घंटे की इन्फ़रेंस दर सीमा प्राप्त कर ली है।{reset} उच्च सीमा के लिए अपग्रेड करें।', 'upsell.usageLimit.heading': 'उपयोग सीमा पहुँच गई', 'upsell.usageLimit.notNow': 'अभी नहीं', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'यह {time} रीसेट होती है।', 'upsell.usageLimit.upgradePlan': 'प्लान अपग्रेड करें', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'चलिए शुरू करें!', + 'walkthrough.tooltip.next': 'अगला →', + 'walkthrough.tooltip.skip': 'टूर छोड़ें', + 'walkthrough.tooltip.stepCounter': '{total} में से {n}', 'webhooks.activity.empty': 'खाली है', 'webhooks.activity.title': 'हाल की एक्टिविटी', 'webhooks.composioHistory.empty': 'खाली है', - 'webhooks.composioHistory.metadataId': 'Metadata ID', - 'webhooks.composioHistory.metadataUuid': 'Metadata UUID', - 'webhooks.composioHistory.payload': 'Payload', + 'webhooks.composioHistory.metadataId': 'मेटाडेटा ID', + 'webhooks.composioHistory.metadataUuid': 'मेटाडेटा UUID', + 'webhooks.composioHistory.payload': 'पेलोड', 'webhooks.composioHistory.title': 'ComposeIO ट्रिगर हिस्ट्री', 'webhooks.tunnels.active': 'एक्टिव', 'webhooks.tunnels.createFailed': 'टनल बनाने में दिक्कत', 'webhooks.tunnels.creating': 'बन रहा है...', 'webhooks.tunnels.deleteFailed': 'टनल डिलीट करने में दिक्कत', 'webhooks.tunnels.descriptionPlaceholder': 'विवरण (वैकल्पिक)', - 'webhooks.tunnels.echo': 'Echo', + 'webhooks.tunnels.echo': 'इको', 'webhooks.tunnels.empty': 'खाली है', 'webhooks.tunnels.enableEcho': 'Echo हटाएं', 'webhooks.tunnels.inactive': 'एक्टिव', @@ -377,26 +379,27 @@ const hi5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'Echo हटाएं', 'webhooks.tunnels.title': 'Webhook टनल', 'webhooks.tunnels.toggleFailed': 'Echo टॉगल करने में दिक्कत', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'प्रमाणीकरण समाप्त', + 'composio.reconnect': 'पुनः कनेक्ट करें', + 'composio.directModeRequiresKey': + 'सहेजने में विफल। डायरेक्ट मोड के लिए गैर-रिक्त API कुंजी आवश्यक है।', + 'composio.notYetRouted': 'अभी तक रूट नहीं हुआ', + 'composio.triggers.loading': 'लोड हो रहा है…', + 'conversations.taskKanban.todo': 'करना है', + 'settings.composio.loading': 'लोड हो रहा है…', + 'settings.mascot.noCharactersAvailable': 'अभी तक कोई OpenHuman कैरेक्टर उपलब्ध नहीं है', + 'skills.uninstall.confirmTitle': '{name} अनइंस्टॉल करें?', + 'conversations.taskKanban.blocked': 'अवरुद्ध', + 'conversations.taskKanban.done': 'पूर्ण', + 'conversations.taskKanban.inProgress': 'प्रगति पर', + 'intelligence.memoryChunk.detail.copiedHint': 'कॉपी हो गया', + 'settings.composio.notYetRouted': 'अभी तक रूट नहीं हुआ', + 'settings.localModel.download.manageExternal': 'इस मॉडल को अपने बाहरी रनटाइम में प्रबंधित करें।', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'OpenHuman के बाहर Ollama प्रक्रिया और मॉडल पुल प्रबंधित करें, फिर डायग्नोस्टिक्स पुनः चलाएँ।', + 'settings.localModel.status.ollamaDocs': 'Ollama दस्तावेज़', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'सेटअप निर्देशों के लिए, फिर आपका रनटाइम पहुँच योग्य होने के बाद पुनः प्रयास करें।', }; export default hi5; diff --git a/app/src/lib/i18n/chunks/id-1.ts b/app/src/lib/i18n/chunks/id-1.ts index 3d40ed4d9..8621db22c 100644 --- a/app/src/lib/i18n/chunks/id-1.ts +++ b/app/src/lib/i18n/chunks/id-1.ts @@ -1,6 +1,6 @@ import type { TranslationMap } from '../types'; -// Bahasa Indonesia chunk 1/5. Translated from chunks/en-1.ts. +// Indonesian (Bahasa Indonesia) chunk 1/5. Translated from chunks/en-1.ts. const id1: TranslationMap = { 'nav.home': 'Beranda', 'nav.human': 'Human', @@ -17,7 +17,7 @@ const id1: TranslationMap = { 'common.edit': 'Edit', 'common.create': 'Buat', 'common.search': 'Cari', - 'common.loading': 'loading…', + 'common.loading': 'memuat…', 'common.error': 'Error', 'common.success': 'Berhasil', 'common.back': 'Kembali', @@ -31,9 +31,9 @@ const id1: TranslationMap = { 'common.yes': 'Ya', 'common.no': 'Tidak', 'common.ok': 'Mengerti', - 'common.retry': 'Try again', + 'common.retry': 'Coba lagi', 'common.copy': 'Salin', - 'common.copied': 'Copied', + 'common.copied': 'Disalin', 'common.learnMore': 'Pelajari lagi', 'common.seeAll': 'Lihat', 'common.dismiss': 'Abaikan', diff --git a/app/src/lib/i18n/chunks/id-2.ts b/app/src/lib/i18n/chunks/id-2.ts index f273108fe..206527453 100644 --- a/app/src/lib/i18n/chunks/id-2.ts +++ b/app/src/lib/i18n/chunks/id-2.ts @@ -1,6 +1,6 @@ import type { TranslationMap } from '../types'; -// Bahasa Indonesia chunk 2/5. Translated from chunks/en-2.ts. +// Indonesian (Bahasa Indonesia) chunk 2/5. Translated from chunks/en-2.ts. const id2: TranslationMap = { 'settings.ai.configStatus': 'Status Konfigurasi', 'settings.ai.fallbackMode': 'Mode Fallback', @@ -171,7 +171,7 @@ const id2: TranslationMap = { 'voice.title': 'Dikte Suara', 'voice.settings': 'Pengaturan Suara', 'voice.settingsDesc': 'Tahan hotkey untuk mendiktekan dan memasukkan teks ke kolom aktif.', - 'voice.hotkey': 'Hotkey', + 'voice.hotkey': 'Pintasan', 'voice.activationMode': 'Mode Aktivasi', 'voice.tapToToggle': 'Ketuk untuk mengalihkan', 'voice.writingStyle': 'Gaya Penulisan', @@ -231,7 +231,7 @@ const id2: TranslationMap = { 'composio.triggersStillRecorded': 'Pemicu tetap dicatat ke riwayat — tidak ada giliran LLM yang dijalankan.', 'composio.disableSpecificIntegrations': 'Nonaktifkan triase AI untuk integrasi tertentu', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'Pengaturan disimpan', 'composio.saveFailed': 'Gagal menyimpan. Coba lagi.', 'cron.title': 'Cron Job', 'cron.scheduledJobs': 'Job Terjadwal', @@ -278,7 +278,7 @@ const id2: TranslationMap = { 'chat.thinkingDots': 'Berpikir...', 'chat.approachingLimit': 'Mendekati batas pemakaian', 'chat.approachingLimitMsg': 'Anda telah memakai {pct}% dari kuota yang tersedia.', - 'chat.upgrade': 'Upgrade', + 'chat.upgrade': 'Tingkatkan', 'chat.weeklyLimitHit': 'Anda telah mencapai batas mingguan.', 'chat.resets': 'Reset', 'chat.topUpToContinue': 'Isi ulang untuk melanjutkan.', diff --git a/app/src/lib/i18n/chunks/id-3.ts b/app/src/lib/i18n/chunks/id-3.ts index 54e2619df..d723958ac 100644 --- a/app/src/lib/i18n/chunks/id-3.ts +++ b/app/src/lib/i18n/chunks/id-3.ts @@ -1,6 +1,6 @@ import type { TranslationMap } from '../types'; -// Bahasa Indonesia chunk 3/5. Translated from chunks/en-3.ts. +// Indonesian (Bahasa Indonesia) chunk 3/5. Translated from chunks/en-3.ts. const id3: TranslationMap = { 'insights.other': 'Lainnya', 'insights.title': 'Wawasan', @@ -157,7 +157,7 @@ const id3: TranslationMap = { 'bootCheck.cannotReachDesc': 'Kami tidak dapat terhubung ke runtime Anda. Ingin mencoba yang berbeda?', 'bootCheck.switchMode': 'Pilih Runtime Berbeda', - 'bootCheck.quit': 'Quit', + 'bootCheck.quit': 'Keluar', 'bootCheck.legacyDetected': 'Runtime Latar Belakang Lama Terdeteksi', 'bootCheck.legacyDescription': 'Daemon OpenHuman yang diinstal terpisah sudah berjalan di perangkat ini. Kami perlu membersihkannya sebelum runtime bawaan dapat mengambil alih.', @@ -251,9 +251,11 @@ const id3: TranslationMap = { 'accounts.addModal.allConnected': 'Semua terhubung', 'accounts.addModal.title': 'Tambah akun', 'accounts.respondQueue.empty': 'Kosong', + 'accounts.respondQueue.hide': 'Sembunyikan antrean balasan', 'accounts.respondQueue.loadFailed': 'Gagal memuat antrean respons', 'accounts.respondQueue.loading': 'Memuat antrean...', 'accounts.respondQueue.pending': 'Tertunda', + 'accounts.respondQueue.show': 'Tampilkan antrean balasan', 'accounts.respondQueue.title': 'Antrean respons', 'accounts.webviewHost.almostReady': 'Hampir siap...', 'accounts.webviewHost.loadTimeout': 'Waktu muat webview habis', @@ -271,7 +273,7 @@ const id3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'Core offline', 'app.connectionIndicator.disconnected': 'Terputus', 'app.connectionIndicator.offline': 'Offline', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'Menyambung ulang…', 'app.errorFallback.componentStack': 'Stack komponen', 'app.errorFallback.downloadLatest': 'Unduh terbaru', 'app.errorFallback.heading': 'Judul', @@ -281,7 +283,7 @@ const id3: TranslationMap = { 'app.errorFallback.tryRecover': 'Coba pulihkan', 'app.localAiDownload.installing': 'Menginstal...', 'app.localAiDownload.preparing': 'Mempersiapkan...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'Lanjutkan dengan masuk {label}', 'app.openhumanLink.accounts.done': 'Selesai', 'app.openhumanLink.accounts.intro': 'Intro', 'app.openhumanLink.accounts.webviewNote': 'Catatan webview', @@ -309,9 +311,9 @@ const id3: TranslationMap = { 'app.openhumanLink.notifications.promptHint': 'Petunjuk prompt', 'app.openhumanLink.notifications.retry': 'Coba ulang notifikasi tes', 'app.openhumanLink.notifications.send': 'Kirim notifikasi tes', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'Tidak bisa mengirim: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'Notifikasi uji telah dikirim. Jika Anda tidak menerimanya, buka System Settings → Notifications → OpenHuman, aktifkan Allow Notifications, dan atur Banner Style ke Persistent.', 'app.openhumanLink.skipForNow': 'Lewati untuk sekarang', 'app.openhumanLink.telegramUnavailable': 'Telegram tidak tersedia', 'app.openhumanLink.title.accounts': 'Hubungkan aplikasi Anda', @@ -323,7 +325,7 @@ const id3: TranslationMap = { 'app.persistRehydration.heading': 'Judul', 'app.persistRehydration.resetCta': 'Mereset...', 'app.persistRehydration.resetting': 'Mereset...', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'Menginisialisasi OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'Terjadi kesalahan saat memperbarui.', 'app.update.header.default': 'Perbarui', @@ -333,7 +335,7 @@ const id3: TranslationMap = { 'app.update.header.restarting': 'Memulai ulang...', 'app.update.later': 'Nanti', 'app.update.newVersionReady': 'Versi baru siap diinstal.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} diunduh', 'app.update.progress.installing': 'Menginstal versi baru...', 'app.update.progress.restarting': 'Meluncurkan ulang aplikasi...', 'app.update.progress.working': '{percent}%', @@ -349,7 +351,7 @@ const id3: TranslationMap = { 'channels.discord.picker.allPermissionsOk': 'Bot memiliki semua izin yang diperlukan di kanal ini.', 'channels.discord.picker.botNotInServers': 'Bot tidak ada di server', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'Kategori', 'channels.discord.picker.channel': 'Kanal', 'channels.discord.picker.checkingPermissions': 'Memeriksa izin', 'channels.discord.picker.loadingChannels': 'Memuat kanal...', @@ -360,7 +362,7 @@ const id3: TranslationMap = { 'channels.discord.picker.selectChannel': 'Pilih kanal', 'channels.discord.picker.selectServer': 'Pilih server', 'channels.discord.picker.server': 'Server', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'Pemilihan Server & Channel', 'channels.discord.savedRestartRequired': 'Kanal tersimpan. Mulai ulang aplikasi untuk mengaktifkannya.', 'channels.telegram.connect': 'Hubungkan', diff --git a/app/src/lib/i18n/chunks/id-4.ts b/app/src/lib/i18n/chunks/id-4.ts index ec5ffb423..927b8f0f4 100644 --- a/app/src/lib/i18n/chunks/id-4.ts +++ b/app/src/lib/i18n/chunks/id-4.ts @@ -1,70 +1,70 @@ import type { TranslationMap } from '../types'; -// Bahasa Indonesia chunk 4/5. Translated from chunks/en-4.ts. +// Indonesian (Bahasa Indonesia) chunk 4/5. Translated from chunks/en-4.ts. const id4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'Setujui & Berhenti Berlangganan', + 'chat.unsubscribeApproval.approved': '✓ Berhasil berhenti berlangganan.', 'chat.unsubscribeApproval.denied': '✕ Permintaan ditolak.', 'chat.unsubscribeApproval.deny': 'Tolak', 'chat.unsubscribeApproval.processing': 'Memproses...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'Permintaan Berhenti Berlangganan', 'commandPalette.ariaLabel': 'Palet perintah', 'commandPalette.description': 'Deskripsi', 'commandPalette.label': 'Perintah', 'commandPalette.noResults': 'Tidak ada hasil', 'commandPalette.placeholder': 'Ketik perintah atau cari...', 'commandPalette.searchAria': 'Cari perintah', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'Tekan ? untuk semua pintasan', 'commandPalette.title': 'Palet perintah', 'composio.connect.additionalConfigRequired': 'Konfigurasi tambahan diperlukan', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Label subdomain Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'Hubungkan', + 'composio.connect.connectionFailed': 'Koneksi gagal (status: {status}).', 'composio.connect.disconnectFailed': 'Putus koneksi gagal: {msg}', 'composio.connect.disconnecting': 'Memutus koneksi...', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'Hubungkan', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'akun Anda. Kami akan membuka jendela browser, Anda menyetujui akses di sana, dan aplikasi ini akan mendeteksi koneksi secara otomatis.', + 'composio.connect.isConnected': 'terhubung.', + 'composio.connect.manage': 'Kelola', + 'composio.connect.needsSubdomain': 'Untuk menghubungkan', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'masukkan subdomain Atlassian Anda (mis. acme untuk acme.atlassian.net) lalu coba lagi.', + 'composio.connect.oauthComplete': 'OAuth untuk diselesaikan…', 'composio.connect.oauthTimeout': 'Waktu OAuth habis', 'composio.connect.permissions': 'Izin', 'composio.connect.permissionsDefault': 'Baca + Tulis diaktifkan secara default', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'dapat mengekspos', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'Izin agen milik OpenHuman dikendalikan di bawah sebagai sakelar read, write, dan admin.', 'composio.connect.reopenBrowser': 'Buka ulang browser', 'composio.connect.requestingUrl': 'Meminta URL koneksi...', 'composio.connect.retryConnection': 'Coba koneksi lagi', 'composio.connect.scopeLoadError': 'Tidak dapat memuat preferensi scope: {msg}', 'composio.connect.scopeSaveError': 'Tidak dapat menyimpan scope {key}: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'Masukkan hanya subdomain pendek (mis. "acme"), bukan URL lengkap. Hanya boleh berisi huruf, angka, dan tanda hubung.', 'composio.connect.subdomainRequired': 'Masukkan subdomain Atlassian Anda untuk melanjutkan.', 'composio.connect.wabaIdLabel': 'Label ID WABA', 'composio.connect.wabaIdRequired': 'Masukkan ID Akun Bisnis WhatsApp (WABA ID) Anda untuk melanjutkan.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'Menunggu', 'composio.connect.waitingHint': 'Petunjuk menunggu', 'composio.triggers.heading': 'Pemicu', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'Dengarkan event dari', + 'composio.triggers.loadError': 'Tidak bisa memuat trigger', 'composio.triggers.needsConfiguration': 'Perlu konfigurasi', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'Tidak ada trigger yang tersedia saat ini untuk', 'conversations.taskKanban.moveLeft': 'Pindah ke kiri', 'conversations.taskKanban.moveRight': 'Pindah ke kanan', 'conversations.taskKanban.title': 'Tugas', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'giliran', 'conversations.toolTimeline.workerThread': 'thread worker', 'daemon.serviceBlockingGate.body': 'Isi', 'daemon.serviceBlockingGate.downloadHint': 'Petunjuk unduhan', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'Unduh Versi Terbaru', + 'daemon.serviceBlockingGate.retryCore': 'Coba Ulang Core', 'daemon.serviceBlockingGate.retryFailed': 'Coba ulang gagal. Unduh build aplikasi terbaru dan coba lagi.', 'daemon.serviceBlockingGate.retrying': 'Mencoba ulang...', @@ -72,11 +72,11 @@ const id4: TranslationMap = { 'home.banners.discordSubtitle': 'Subtitle Discord', 'home.banners.discordTitle': 'Bergabung ke Discord Kami', 'home.banners.earlyBirdDismiss': 'Abaikan banner early bird', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'langganan pertama.', 'home.banners.earlyBirdOn': 'Early bird aktif', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': '1.000 pengguna pertama dapat diskon 60%.', 'home.banners.earlyBirdUseCode': 'Gunakan kode early bird', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'dapatkan langganan', 'home.banners.promoCreditsBody': 'Isi kredit promo', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'Penggunaan kredit promo', @@ -87,20 +87,20 @@ const id4: TranslationMap = { 'intelligence.memoryChunk.letterhead.from': 'dari', 'intelligence.memoryChunk.letterhead.to': 'ke', 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunk', 'intelligence.memoryChunk.mentioned.heading': 'd i s e b u t k a n', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} skor {pct} persen', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'pada {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'dibuang', 'intelligence.memoryChunk.scoreBars.heading': 'm e n g a p a d i s i m p a n', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'dipertahankan', + 'intelligence.memoryText.entityTypePrefix': 'Tipe entitas', 'intelligence.screenDebug.active': 'Aktif', 'intelligence.screenDebug.app': 'Aplikasi', 'intelligence.screenDebug.bounds': 'Batas', 'intelligence.screenDebug.captureAlt': 'Hasil tes tangkapan', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'Gagal', + 'intelligence.screenDebug.captureSuccess': 'Berhasil', 'intelligence.screenDebug.captureTest': 'Tes tangkapan', 'intelligence.screenDebug.capturing': 'Menangkap', 'intelligence.screenDebug.frames': 'Frame', @@ -122,16 +122,16 @@ const id4: TranslationMap = { 'intelligence.screenDebug.unknown': 'Tidak diketahui', 'intelligence.screenDebug.visionQueue': 'Antrean Visi', 'intelligence.screenDebug.visionState': 'Status Visi', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 board aktif di seluruh percakapan', + 'intelligence.tasks.activeBoardOther': '{count} board aktif di seluruh percakapan', 'intelligence.tasks.empty': 'Belum ada papan tugas agen', 'intelligence.tasks.emptyHint': 'Petunjuk kosong', 'intelligence.tasks.failedToLoad': 'Gagal memuat', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'langsung', 'intelligence.tasks.loadingBoards': 'Memuat papan tugas...', 'intelligence.tasks.threadPrefix': 'Thread {thread}', 'notifications.card.dismiss': 'Abaikan notifikasi', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'Tingkat penting: {pct}%', 'notifications.center.empty': 'Belum ada notifikasi', 'notifications.center.emptyHint': 'Petunjuk kosong', 'notifications.center.filterAll': 'Filter semua', @@ -143,7 +143,7 @@ const id4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'Membangun profil Anda...', 'onboarding.contextGathering.continueToChat': 'Lanjutkan ke chat', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'Kami tidak bisa membangun profil lengkap Anda sekarang, tapi tidak apa-apa — Anda bisa lanjut dan profil Anda akan terbentuk seiring waktu.', 'onboarding.contextGathering.title': 'Pengumpulan Konteks', 'openhuman.team_list_teams': 'Daftar tim', 'overlay.ariaAttention': 'Pesan perhatian', @@ -183,20 +183,20 @@ const id4: TranslationMap = { 'privacy.dataKind.diagnostics': 'Diagnostik', 'privacy.dataKind.metadata': 'Metadata', 'privacy.dataKind.raw': 'Mentah', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'Apa yang keluar dari komputer saya?', + 'rewards.community.achievementsUnlocked': '{unlocked} dari {total} pencapaian terbuka', 'rewards.community.connectDiscord': 'Hubungkan Discord', 'rewards.community.cumulativeTokens': 'Token kumulatif', 'rewards.community.currentStreak': 'Streak saat ini', 'rewards.community.discordLinkedNotInGuild': 'Discord terhubung tidak ada di guild', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'Bergabung ke server', 'rewards.community.discordNotLinked': 'Discord belum terhubung', 'rewards.community.discordServer': 'Server Discord', 'rewards.community.discordStatusUnavailable': 'Status Discord tidak tersedia', 'rewards.community.discordWaiting': 'Menunggu Discord', 'rewards.community.heroSubtitle': 'Subtitle hero', 'rewards.community.heroTitle': 'Judul hero', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'Gabung Discord', 'rewards.community.loadingRewards': 'Memuat hadiah...', 'rewards.community.locked': 'Terbuka', 'rewards.community.retrying': 'Mencoba ulang...', @@ -214,21 +214,21 @@ const id4: TranslationMap = { 'rewards.coupon.colReward': 'Hadiah', 'rewards.coupon.colStatus': 'Status', 'rewards.coupon.loadingHistory': 'Memuat riwayat hadiah...', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'Belum ada kode hadiah yang ditukarkan.', 'rewards.coupon.pending': 'Tertunda', 'rewards.coupon.placeholder': 'Kode kupon', 'rewards.coupon.promoCredits': 'Kredit promo', 'rewards.coupon.recentRedemptions': 'Penukaran terbaru', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} diterima. {amount} akan terbuka setelah tindakan yang diperlukan diselesaikan.', + 'rewards.coupon.redeemButton': 'Tukarkan Kode', + 'rewards.coupon.redeemSuccess': '{code} ditukarkan. {amount} telah ditambahkan ke kredit Anda.', 'rewards.coupon.redeemedCodes': 'Kode yang ditukarkan', 'rewards.coupon.redeeming': 'Menukarkan...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', - 'rewards.coupon.subtitle': 'Subtitle', + 'rewards.coupon.statusApplied': 'Diterapkan', + 'rewards.coupon.statusPendingAction': 'Menunggu tindakan', + 'rewards.coupon.statusRedeemed': 'Ditukarkan', + 'rewards.coupon.subtitle': 'Subjudul', 'rewards.coupon.title': 'Tukarkan kode kupon', 'rewards.referralSection.activity': 'Aktivitas referral', 'rewards.referralSection.apply': 'Menerapkan...', @@ -243,7 +243,7 @@ const id4: TranslationMap = { 'rewards.referralSection.haveCode': 'Punya kode referral?', 'rewards.referralSection.haveCodeDesc': 'Deskripsi punya kode', 'rewards.referralSection.linked': 'Terhubung', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(kode {code})', 'rewards.referralSection.loading': 'Memuat program referral...', 'rewards.referralSection.noReferrals': 'Tidak ada referral', 'rewards.referralSection.pendingReferrals': 'Referral tertunda', @@ -252,22 +252,22 @@ const id4: TranslationMap = { 'rewards.referralSection.statusCompleted': 'Status selesai', 'rewards.referralSection.statusExpired': 'Status kedaluwarsa', 'rewards.referralSection.statusJoined': 'Status bergabung', - 'rewards.referralSection.subtitle': 'Subtitle', + 'rewards.referralSection.subtitle': 'Subjudul', 'rewards.referralSection.title': 'Undang teman, dapatkan kredit', 'rewards.referralSection.totalEarned': 'Total diperoleh', 'rewards.referralSection.yourCode': 'Kode Anda', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'Tambah penyedia cloud', 'settings.ai.addProvider': 'Menyimpan...', 'settings.ai.apiKeyFieldLabel': 'Label kolom API key', 'settings.ai.apiKeyRequired': 'Tempelkan API key Anda untuk melanjutkan.', 'settings.ai.apiKeyStoredEncrypted': 'API key disimpan terenkripsi', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'Hapus key tersimpan', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'Hubungkan penyedia', 'settings.ai.customRouting': 'Routing kustom', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'Buang', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'Edit penyedia', 'settings.ai.llmProviders': 'Penyedia LLM', 'settings.ai.llmProvidersDesc': 'Deskripsi penyedia LLM', 'settings.ai.localOllama': 'Lokal (Ollama)', @@ -280,8 +280,8 @@ const id4: TranslationMap = { 'settings.ai.routingDesc': 'Deskripsi routing', 'settings.ai.saveChanges': 'Menyimpan...', 'settings.ai.saving': 'Menyimpan...', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'perubahan belum disimpan', + 'settings.ai.unsavedChanges': 'perubahan belum disimpan', 'settings.ai.workloadGroupBackground': 'Grup beban kerja latar', 'settings.ai.workloadGroupChat': 'Grup beban kerja chat', 'settings.autocomplete.appFilter.acceptSuggestion': 'Terima saran', @@ -295,9 +295,9 @@ const id4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'Runtime', 'settings.autocomplete.appFilter.test': 'Tes', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count} pelengkapan diterima tersimpan — digunakan untuk mempersonalisasi saran berikutnya.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count} pelengkapan diterima tersimpan — digunakan untuk mempersonalisasi saran berikutnya.', 'settings.autocomplete.completionStyle.clearHistory': 'Membersihkan...', 'settings.autocomplete.completionStyle.clearing': 'Membersihkan...', 'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)', @@ -322,7 +322,7 @@ const id4: TranslationMap = { 'settings.billing.autoRecharge.saveSettings': 'Menyimpan...', 'settings.billing.autoRecharge.saving': 'Menyimpan...', 'settings.billing.autoRecharge.setDefault': ':', - 'settings.billing.autoRecharge.subtitle': 'Subtitle', + 'settings.billing.autoRecharge.subtitle': 'Subjudul', 'settings.billing.autoRecharge.title': 'Aktifkan Isi Ulang Otomatis', 'settings.billing.autoRecharge.toggleAriaLabel': 'Alihkan isi ulang otomatis', 'settings.billing.autoRecharge.weeklyLimit': 'Batas pengeluaran mingguan', @@ -347,7 +347,7 @@ const id4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'Judul saldo kredit', 'settings.billing.payAsYouGo.customAmount': 'Jumlah kustom', 'settings.billing.payAsYouGo.enterAmount': 'Masukkan jumlah', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'Membuka', 'settings.billing.payAsYouGo.promotionalCredits': 'Kredit Promosi', 'settings.billing.payAsYouGo.topUpBalance': 'Isi Ulang Saldo', 'settings.billing.payAsYouGo.topUpCredits': 'Isi Ulang Kredit', diff --git a/app/src/lib/i18n/chunks/id-5.ts b/app/src/lib/i18n/chunks/id-5.ts index b3e6f1ff0..50f728975 100644 --- a/app/src/lib/i18n/chunks/id-5.ts +++ b/app/src/lib/i18n/chunks/id-5.ts @@ -1,54 +1,55 @@ import type { TranslationMap } from '../types'; -// Bahasa Indonesia chunk 5/5. Translated from chunks/en-5.ts. +// Indonesian (Bahasa Indonesia) chunk 5/5. Translated from chunks/en-5.ts. const id5: TranslationMap = { 'settings.billing.subscription.save': '{pct}', - 'settings.billing.subscription.upgrade': 'Upgrade', + 'settings.billing.subscription.upgrade': 'Tingkatkan', 'settings.billing.subscription.waiting': 'Menunggu', 'settings.billing.subscription.waitingPayment': 'Menunggu pembayaran', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': 'API key Composio saat ini tersimpan di perangkat ini.', + 'settings.composio.apiKeyLabel': 'API key Composio', + 'settings.composio.apiKeyStored': 'API key tersimpan', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Beralih ke mode Backend', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'Akun di app.composio.dev dengan API key', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'Menghubungkan ulang setiap integrasi melalui akun Composio pribadi Anda', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'Catatan: trigger Composio (webhook real-time) belum berjalan di mode Direct — hanya pemanggilan tool sinkron', + 'settings.composio.confirmNeedItems': 'Anda akan butuh:', + 'settings.composio.confirmSwitch': 'Saya mengerti, beralih ke Direct', + 'settings.composio.confirmTitle': '⚠️ Beralih ke mode Direct', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'Integrasi Anda yang sudah ada (Gmail, Slack, GitHub, dll. yang terhubung melalui OpenHuman) tidak akan terlihat — mereka berada di tenant Composio yang dikelola OpenHuman.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio mengintegrasikan 250+ aplikasi eksternal sebagai tool yang dapat dipanggil agen Anda. Pilih cara pemanggilan tool tersebut dirutekan.', 'settings.composio.modeDirect': 'Langsung (bawa API key Anda sendiri)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'Panggilan langsung ke backend.composio.dev. Berdaulat / ramah offline. Eksekusi tool berjalan sinkron; webhook trigger real-time belum dirutekan dalam mode direct (isu lanjutan).', 'settings.composio.modeManaged': 'Terkelola (OpenHuman menanganinya untuk Anda)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman mem-proxy pemanggilan tool melalui backend kami (disarankan). Autentikasi dibrokerkan; Anda tidak perlu menempel API key Composio. Webhook dirutekan sepenuhnya.', 'settings.composio.routingMode': 'Mode routing', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + 'Gagal menyimpan. Mode Direct memerlukan API key yang tidak kosong.', 'settings.composio.saving': 'Menyimpan...', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'Mengalihkan…', 'settings.cron.jobs.desc': 'Deskripsi', 'settings.cron.jobs.empty': 'Tidak ada cron job core ditemukan.', 'settings.cron.jobs.lastStatus': 'Status terakhir', 'settings.cron.jobs.loading': 'Memuat cron job...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'Memuat run', 'settings.cron.jobs.nextRun': 'Jalan berikutnya', 'settings.cron.jobs.pause': 'Jeda', 'settings.cron.jobs.paused': 'Diaktifkan', 'settings.cron.jobs.recentRuns': 'Jalan terbaru', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'Menghapus', 'settings.cron.jobs.resume': 'Lanjutkan', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'Sedang berjalan', 'settings.cron.jobs.saving': 'Menyimpan...', 'settings.cron.jobs.schedule': 'Jadwal', 'settings.cron.jobs.title': 'Cron Job Core', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'Lihat run', 'settings.localModel.deviceCapability.active': 'Aktif', 'settings.localModel.deviceCapability.appliedTier': 'Tingkat yang diterapkan', 'settings.localModel.deviceCapability.applying': 'Menerapkan', @@ -67,10 +68,11 @@ const id5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Instalasi Ollama gagal', 'settings.localModel.deviceCapability.installFailedDesc': 'Penginstal keluar sebelum Ollama dapat digunakan. Klik coba ulang, atau instal manual dari ollama.com.', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'Jalankan Ollama terlebih dahulu.', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'Tier lokal bergantung pada endpoint Ollama yang dikelola eksternal. Jalankan sendiri, tarik model yang Anda inginkan, dan tetap gunakan "Disabled (cloud fallback)" hingga runtime dapat dijangkau.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'Jalankan Ollama terlebih dahulu untuk menggunakan tier ini', 'settings.localModel.deviceCapability.installingOllama': 'Menginstal Ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'Memuat info perangkat', 'settings.localModel.deviceCapability.localAiDisabled': @@ -92,8 +94,8 @@ const id5: TranslationMap = { 'Ketik prompt apa saja dan jalankan terhadap model lokal...', 'settings.localModel.download.quantizationPref': 'Preferensi kuantisasi', 'settings.localModel.download.runEmbeddingTest': 'Menjalankan...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'Jalankan Uji Prompt', + 'settings.localModel.download.runSummaryTest': 'Jalankan Uji Ringkasan', 'settings.localModel.download.runTranscriptionTest': 'Menjalankan...', 'settings.localModel.download.runTtsTest': 'Menjalankan...', 'settings.localModel.download.runVisionTest': 'Menjalankan...', @@ -122,11 +124,11 @@ const id5: TranslationMap = { 'settings.localModel.status.customLocation': 'Lokasi kustom', 'settings.localModel.status.customLocationDesc': 'Deskripsi lokasi kustom', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Klik "Run Diagnostics" untuk memverifikasi Ollama berjalan dan model telah terinstal.', 'settings.localModel.status.downloadingUnknown': 'Mengunduh (ukuran tidak diketahui)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'Model yang diharapkan', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'Paksa Re-bootstrap', 'settings.localModel.status.generationTps': 'TPS Generasi', 'settings.localModel.status.hideErrorDetails': 'Sembunyikan detail error', 'settings.localModel.status.installManually': 'Instal manual', @@ -136,16 +138,16 @@ const id5: TranslationMap = { 'settings.localModel.status.installing': 'Menginstal...', 'settings.localModel.status.installingOllama': 'Menginstal runtime Ollama...', 'settings.localModel.status.issues': 'Masalah', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '{count} masalah ditemukan', 'settings.localModel.status.lastLatency': 'Latensi Terakhir', 'settings.localModel.status.model': 'Model', 'settings.localModel.status.notFound': 'Tidak ditemukan', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'Tidak berjalan', 'settings.localModel.status.ollamaBinaryPath': 'Path biner Ollama', 'settings.localModel.status.ollamaDiagnostics': 'Diagnostik Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Runtime Ollama tidak tersedia', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman kini memperlakukan Ollama sebagai runtime inferensi eksternal. Jalankan server Ollama Anda sendiri, tarik model yang diinginkan, lalu arahkan routing workload ke sana.', 'settings.localModel.status.progress': 'Progres', 'settings.localModel.status.provider': 'Penyedia', 'settings.localModel.status.retryBootstrap': 'Coba Ulang Bootstrap', @@ -170,25 +172,25 @@ const id5: TranslationMap = { 'settings.mascot.colorHeading': 'Judul warna', 'settings.mascot.loadingLibrary': 'Memuat perpustakaan OpenHuman...', 'settings.mascot.localDefault': 'OpenHuman Lokal (default)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'Belum ada karakter OpenHuman yang tersedia', 'settings.mascot.noColorVariants': 'Tidak ada varian warna', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'Direkomendasikan', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'Default yang masuk akal — kontinuitas yang baik tanpa membakar token tambahan di setiap run.', + 'settings.memoryWindow.balanced.label': 'Seimbang', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'Seberapa banyak konteks yang diingat OpenHuman dimasukkan ke setiap run agen baru. Jendela yang lebih besar terasa lebih sadar akan percakapan sebelumnya, tetapi menggunakan lebih banyak token — dan biaya lebih mahal — di setiap run.', + 'settings.memoryWindow.extended.badge': 'Lebih banyak konteks', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'Lebih banyak memori jangka panjang yang dimasukkan ke setiap run. Biaya token per giliran lebih tinggi.', + 'settings.memoryWindow.extended.label': 'Diperluas', + 'settings.memoryWindow.maximum.badge': 'Biaya tertinggi', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'Jendela teraman terbesar. Kontinuitas terbaik, tagihan token per run jauh lebih tinggi.', + 'settings.memoryWindow.maximum.label': 'Maksimum', + 'settings.memoryWindow.minimal.badge': 'Termurah', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', + 'Jendela memori terkecil. Termurah, tercepat, kontinuitas paling sedikit antar run.', 'settings.memoryWindow.minimal.label': 'Minimal', 'settings.memoryWindow.title': 'Jendela memori jangka panjang', 'settings.screenIntel.permissions.accessibility': 'Aksesibilitas', @@ -206,26 +208,26 @@ const id5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'Perekaman Layar', 'settings.screenIntel.permissions.title': 'Izin', 'skills.card.moreActions': 'Tindakan lainnya', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'Tool yang diizinkan', + 'skills.create.author': 'Penulis', 'skills.create.authorPlaceholder': 'Nama Anda', 'skills.create.commaSeparated': '(dipisahkan koma)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'Buat skill', 'skills.create.createError': 'Tidak dapat membuat skill', 'skills.create.creating': 'Membuat...', - 'skills.create.description': 'Description', + 'skills.create.description': 'Deskripsi', 'skills.create.descriptionPlaceholder': 'Apa fungsi skill ini?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'Lisensi', + 'skills.create.name': 'Nama', 'skills.create.namePlaceholder': 'mis. Jurnal Trading', - 'skills.create.scope': 'Scope', + 'skills.create.scope': 'Cakupan', 'skills.create.scopeProjectHint': '/.openhuman/skills/', 'skills.create.scopeUserHint': 'Ditulis ke ~/.openhuman/skills//SKILL.md — tersedia di semua workspace.', 'skills.create.slugLabel': 'Label slug', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'Tag', + 'skills.create.title': 'Skill baru', 'skills.detail.allowedTools': 'Alat yang diizinkan', 'skills.detail.author': 'Penulis', 'skills.detail.bundledResources': 'Sumber daya bundel', @@ -242,13 +244,13 @@ const id5: TranslationMap = { 'skills.install.rawError': 'Error mentah', 'skills.install.timeoutHint': '(detik, opsional)', 'skills.install.timeoutLabel': 'Label waktu habis', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'Pasang skill dari URL', + 'skills.install.urlLabel': 'URL skill', 'skills.meetingBots.bannerDesc': 'Deskripsi banner', 'skills.meetingBots.bannerTitle': 'Judul banner', 'skills.meetingBots.busyTitle': 'OpenHuman sedang sibuk', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'Segera hadir', + 'skills.meetingBots.couldNotStartTitle': 'Tidak bisa memulai OpenHuman', 'skills.meetingBots.displayName': 'Nama tampilan', 'skills.meetingBots.failedToStart': 'Gagal memulai OpenHuman.', 'skills.meetingBots.joiningMessage': 'Seharusnya muncul sebagai peserta dalam beberapa detik.', @@ -258,10 +260,10 @@ const id5: TranslationMap = { 'skills.meetingBots.modalDesc': 'Deskripsi modal', 'skills.meetingBots.modalTitle': 'Kirim OpenHuman ke rapat', 'skills.meetingBots.newBadge': 'Lencana baru', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'Kirim ke', 'skills.meetingBots.starting': 'Memulai...', 'skills.resource.preview.closeAriaLabel': 'Tutup pratinjau', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'Pratinjau gagal', 'skills.resource.preview.loading': 'Memuat pratinjau...', 'skills.resource.tree.empty': 'Tidak ada sumber daya bundel.', 'skills.search.placeholder': 'Placeholder', @@ -317,7 +319,7 @@ const id5: TranslationMap = { 'skills.setup.voice.customizeSettings': 'Sesuaikan pengaturan', 'skills.setup.voice.downloadSttBtn': 'Unduh tombol STT', 'skills.setup.voice.enableDesc': 'Deskripsi aktifkan', - 'skills.setup.voice.hotkey': 'Hotkey', + 'skills.setup.voice.hotkey': 'Pintasan', 'skills.setup.voice.startBtn': 'Memulai...', 'skills.setup.voice.startError': 'Gagal memulai server suara', 'skills.setup.voice.starting': 'Memulai...', @@ -330,32 +332,32 @@ const id5: TranslationMap = { 'skills.setup.voice.sttReady': 'Model speech-to-text siap', 'skills.setup.voice.sttReturnHint': 'Petunjuk kembali STT', 'skills.setup.voice.title': 'Kecerdasan Suara', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'Tidak bisa mencopot', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'Ini akan menghapus permanen direktori skill dan semua resource yang dibundel. Agen akan berhenti melihatnya pada giliran berikutnya.', + 'skills.uninstall.title': 'Copot', + 'skills.uninstall.uninstallBtn': 'Copot', + 'skills.uninstall.uninstalling': 'Mencopot…', 'upsell.global.limitMessage': 'Upgrade paket atau isi ulang kredit untuk melanjutkan', 'upsell.global.limitTitle': 'Anda', 'upsell.global.nearLimitMessage': 'Anda telah menggunakan {pct}% dari batas pemakaian. Upgrade untuk batas lebih tinggi.', 'upsell.global.nearLimitTitle': 'Mendekati batas pemakaian', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'Anda telah mencapai batas mingguan.{reset} Tingkatkan paket Anda atau isi ulang kredit untuk menghindari batas.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'Anda telah mencapai batas laju inferensi 10 jam.{reset} Tingkatkan untuk batas yang lebih tinggi.', 'upsell.usageLimit.heading': 'Batas Pemakaian Tercapai', 'upsell.usageLimit.notNow': 'Tidak sekarang', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'Akan direset {time}.', 'upsell.usageLimit.upgradePlan': 'Upgrade paket', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'Ayo mulai!', + 'walkthrough.tooltip.next': 'Berikutnya →', + 'walkthrough.tooltip.skip': 'Lewati tur', + 'walkthrough.tooltip.stepCounter': '{n} dari {total}', 'webhooks.activity.empty': 'Kosong', 'webhooks.activity.title': 'Aktivitas Terbaru', 'webhooks.composioHistory.empty': 'Kosong', @@ -377,26 +379,27 @@ const id5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'Hapus Echo', 'webhooks.tunnels.title': 'Tunnel Webhook', 'webhooks.tunnels.toggleFailed': 'Gagal mengalihkan echo', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'Autentikasi kedaluwarsa', + 'composio.reconnect': 'Hubungkan ulang', + 'composio.directModeRequiresKey': + 'Gagal menyimpan. Mode Direct memerlukan API key yang tidak kosong.', + 'composio.notYetRouted': 'belum dirutekan', + 'composio.triggers.loading': 'Memuat…', + 'conversations.taskKanban.todo': 'Akan dikerjakan', + 'settings.composio.loading': 'Memuat…', + 'settings.mascot.noCharactersAvailable': 'Belum ada karakter OpenHuman yang tersedia', + 'skills.uninstall.confirmTitle': 'Copot {name}?', + 'conversations.taskKanban.blocked': 'Terhambat', + 'conversations.taskKanban.done': 'Selesai', + 'conversations.taskKanban.inProgress': 'Sedang berjalan', + 'intelligence.memoryChunk.detail.copiedHint': 'disalin', + 'settings.composio.notYetRouted': 'belum dirutekan', + 'settings.localModel.download.manageExternal': 'Kelola model ini di runtime eksternal Anda.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'Kelola proses Ollama dan unduhan model di luar OpenHuman, lalu jalankan ulang diagnostik.', + 'settings.localModel.status.ollamaDocs': 'Dokumentasi Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'untuk instruksi pengaturan, lalu coba lagi setelah runtime Anda dapat dijangkau.', }; export default id5; diff --git a/app/src/lib/i18n/chunks/it-1.ts b/app/src/lib/i18n/chunks/it-1.ts new file mode 100644 index 000000000..c6b1d0d96 --- /dev/null +++ b/app/src/lib/i18n/chunks/it-1.ts @@ -0,0 +1,390 @@ +import type { TranslationMap } from '../types'; + +// Italian (Italiano) chunk 1/5. Translated from chunks/en-1.ts. +const it1: TranslationMap = { + 'nav.home': 'Home', + 'nav.human': 'Human', + 'nav.chat': 'Chat', + 'nav.connections': 'Connessioni', + 'nav.memory': 'Intelligence', + 'nav.alerts': 'Avvisi', + 'nav.rewards': 'Premi', + 'nav.settings': 'Impostazioni', + 'common.cancel': 'Annulla', + 'common.save': 'Salva', + 'common.confirm': 'Conferma', + 'common.delete': 'Elimina', + 'common.edit': 'Modifica', + 'common.create': 'Crea', + 'common.search': 'Cerca', + 'common.loading': 'caricamento…', + 'common.error': 'Errore', + 'common.success': 'Successo', + 'common.back': 'Indietro', + 'common.next': 'Avanti', + 'common.finish': 'Fine', + 'common.close': 'Chiudi', + 'common.enabled': 'Abilitato', + 'common.disabled': 'Disabilitato', + 'common.on': 'On', + 'common.off': 'Off', + 'common.yes': 'Sì', + 'common.no': 'No', + 'common.ok': 'Ok', + 'common.retry': 'Riprova', + 'common.copy': 'Copia', + 'common.copied': 'Copiato', + 'common.learnMore': 'Scopri di più', + 'common.seeAll': 'Visualizza', + 'common.dismiss': 'Ignora', + 'common.clear': 'Cancella', + 'common.reset': 'Ripristina', + 'common.refresh': 'Aggiorna', + 'common.export': 'Esporta', + 'common.import': 'Importa', + 'common.upload': 'Carica', + 'common.download': 'Scarica', + 'common.add': 'Aggiungi', + 'common.remove': 'Rimuovi', + 'common.showMore': 'Mostra di più', + 'common.showLess': 'Mostra meno', + 'common.submit': 'Invia', + 'common.continue': 'Continua', + 'settings.general': 'Generale', + 'settings.featuresAndAI': 'Funzionalità e AI', + 'settings.billingAndRewards': 'Fatturazione e premi', + 'settings.support': 'Supporto', + 'settings.advanced': 'Avanzate', + 'settings.dangerZone': 'Zona pericolosa', + 'settings.account': 'Account', + 'settings.accountDesc': 'Frase di recupero, team, connessioni e privacy', + 'settings.notifications': 'Notifiche', + 'settings.notificationsDesc': 'Non disturbare e controlli notifiche per account', + 'settings.features': 'Funzionalità', + 'settings.featuresDesc': 'Consapevolezza schermo, messaggistica e strumenti', + 'settings.aiModels': 'AI e modelli', + 'settings.aiModelsDesc': 'Configurazione modello AI locale, download e provider LLM', + 'settings.ai': 'Configurazione AI', + 'settings.aiDesc': 'Provider cloud, modelli Ollama locali e instradamento per carico di lavoro', + 'settings.billingUsage': 'Fatturazione e utilizzo', + 'settings.billingUsageDesc': 'Piano di abbonamento, crediti e metodi di pagamento', + 'settings.rewards': 'Premi', + 'settings.rewardsDesc': 'Referral, coupon e crediti guadagnati', + 'settings.restartTour': 'Riavvia tour', + 'settings.restartTourDesc': "Riproduci la presentazione del prodotto dall'inizio", + 'settings.about': 'Informazioni', + 'settings.aboutDesc': 'Versione app e aggiornamenti software', + 'settings.developerOptions': 'Avanzate', + 'settings.developerOptionsDesc': + 'Configurazione AI, canali di messaggistica, strumenti, diagnostica e pannelli di debug', + 'settings.clearAppData': 'Cancella dati app', + 'settings.clearAppDataDesc': + "Disconnetti e cancella permanentemente tutti i dati locali dell'app", + 'settings.logOut': 'Disconnetti', + 'settings.logOutDesc': 'Disconnetti dal tuo account', + 'settings.language': 'Lingua', + 'settings.languageDesc': "Lingua di visualizzazione dell'interfaccia dell'app", + 'settings.alerts': 'Avvisi', + 'settings.alertsDesc': 'Visualizza avvisi recenti e attività nella tua posta', + 'settings.account.recoveryPhrase': 'Frase di recupero', + 'settings.account.recoveryPhraseDesc': 'Visualizza e fai il backup della frase di recupero', + 'settings.account.team': 'Team', + 'settings.account.teamDesc': 'Gestisci membri del team e autorizzazioni', + 'settings.account.connections': 'Connessioni', + 'settings.account.connectionsDesc': 'Gestisci account e servizi collegati', + 'settings.account.privacy': 'Privacy', + 'settings.account.privacyDesc': 'Controlla quali dati escono dal tuo computer', + 'settings.notifications.doNotDisturb': 'Non disturbare', + 'settings.notifications.doNotDisturbDesc': + 'Metti in pausa tutte le notifiche per un periodo prefissato', + 'settings.notifications.channelControls': 'Controlli per canale', + 'settings.notifications.channelControlsDesc': + 'Configura le preferenze di notifica per ogni canale', + 'settings.features.screenAwareness': 'Consapevolezza schermo', + 'settings.features.screenAwarenessDesc': "Consenti all'assistente di vedere la finestra attiva", + 'settings.features.messaging': 'Messaggistica', + 'settings.features.messagingDesc': 'Impostazioni canale e integrazione messaggistica', + 'settings.features.tools': 'Strumenti', + 'settings.features.toolsDesc': 'Gestisci strumenti e integrazioni connessi', + 'settings.ai.localSetup': 'Configurazione AI locale', + 'settings.ai.localSetupDesc': 'Scarica e configura modelli AI locali', + 'settings.ai.llmProvider': 'Provider LLM', + 'settings.ai.llmProviderDesc': 'Scegli e configura il tuo provider AI', + 'clearData.title': 'Cancella dati app', + 'clearData.warning': + "Verrai disconnesso e i dati locali dell'app verranno eliminati permanentemente, compresi:", + 'clearData.bulletSettings': "Impostazioni e conversazioni dell'app", + 'clearData.bulletCache': 'Tutti i dati di cache delle integrazioni locali', + 'clearData.bulletWorkspace': 'Dati del workspace', + 'clearData.bulletOther': 'Tutti gli altri dati locali', + 'clearData.irreversible': 'Questa azione non può essere annullata.', + 'clearData.clearing': 'Cancellazione dati app...', + 'clearData.failed': 'Impossibile cancellare i dati ed effettuare il logout. Riprova.', + 'clearData.failedLogout': 'Impossibile effettuare il logout. Riprova.', + 'clearData.failedPersist': "Impossibile cancellare lo stato persistente dell'app. Riprova.", + 'welcome.title': 'Benvenuto in OpenHuman', + 'welcome.subtitle': + 'La tua super intelligenza AI personale. Privata, semplice ed estremamente potente.', + 'welcome.connectPrompt': 'Configura URL RPC (Avanzato)', + 'welcome.selectRuntime': 'Seleziona un runtime', + 'welcome.urlPlaceholder': 'http://localhost:8089', + 'welcome.invalidUrl': 'Inserisci un URL HTTP o HTTPS valido', + 'welcome.connecting': 'Test', + 'welcome.connect': 'Test', + 'home.greeting': 'Buongiorno', + 'home.greetingAfternoon': 'Buon pomeriggio', + 'home.greetingEvening': 'Buonasera', + 'home.askAssistant': 'Chiedi qualsiasi cosa al tuo assistente...', + 'home.statusOk': + "Il tuo dispositivo è connesso. Tieni l'app in esecuzione per mantenere la connessione attiva. Scrivi al tuo agente con il pulsante sotto.", + 'home.statusBackendOnly': 'Riconnessione al backend… il tuo agente sarà disponibile a breve.', + 'home.statusCoreUnreachable': + 'Il sidecar core locale non risponde. Il processo in background di OpenHuman potrebbe essersi bloccato o non essere partito.', + 'home.statusInternetOffline': + "Il tuo dispositivo è offline. Controlla la rete o riavvia l'app per riconnetterti.", + 'home.restartCore': 'Riavvia core', + 'home.restartingCore': 'Riavvio core…', + 'chat.newThread': 'Nuovo thread', + 'chat.typeMessage': 'Scrivi un messaggio...', + 'chat.send': 'Invia messaggio', + 'chat.thinking': 'Sto pensando...', + 'chat.noMessages': 'Nessun messaggio', + 'chat.startConversation': 'Inizia una conversazione', + 'chat.regenerate': 'Rigenera', + 'chat.copyResponse': 'Copia risposta', + 'chat.citations': 'Citazioni', + 'chat.toolUsed': 'Strumento usato', + 'scope.legacy': 'Legacy', + 'scope.user': 'Utente', + 'scope.project': 'Progetto', + 'skills.title': 'Connessioni', + 'skills.search': 'Cerca connessioni...', + 'skills.noResults': 'Nessuna connessione trovata', + 'skills.connect': 'Connetti', + 'skills.disconnect': 'Disconnetti', + 'skills.configure': 'Gestisci', + 'skills.connected': 'Connesso', + 'skills.available': 'Disponibile', + 'skills.addAccount': 'Aggiungi account', + 'skills.channels': 'Canali', + 'skills.integrations': 'Integrazioni', + 'memory.title': 'Memoria', + 'memory.search': 'Cerca memorie...', + 'memory.noResults': 'Nessuna memoria trovata', + 'memory.empty': + 'Nessuna memoria ancora. Le memorie vengono create automaticamente mentre interagisci.', + 'memory.tab.memory': 'Memoria', + 'memory.tab.subconscious': 'Subconscio', + 'memory.tab.dreams': 'Sogni', + 'memory.tab.calls': 'Chiamate', + 'memory.tab.settings': 'Impostazioni', + 'memory.analyzeNow': 'Analizza ora', + 'alerts.title': 'Avvisi', + 'alerts.empty': 'Nessun avviso', + 'alerts.markAllRead': 'Segna tutti come letti', + 'alerts.unread': 'non letti', + 'rewards.title': 'Premi', + 'rewards.referrals': 'Referral', + 'rewards.coupons': 'Riscatta', + 'rewards.credits': 'Crediti', + 'rewards.referralCode': 'Il tuo codice referral', + 'rewards.copyCode': 'Copia codice', + 'rewards.share': 'Condividi', + 'onboarding.welcome': 'Ciao. Sono OpenHuman.', + 'onboarding.welcomeDesc': + 'Il tuo assistente AI super intelligente che gira sul tuo computer. Privato, semplice ed estremamente potente.', + 'onboarding.context': 'Raccolta del contesto', + 'onboarding.contextDesc': 'Connetti gli strumenti e i servizi che usi ogni giorno.', + 'onboarding.localAI': 'AI locale', + 'onboarding.localAIDesc': 'Configura un modello AI locale che gira sulla tua macchina.', + 'onboarding.chatProvider': 'Provider chat', + 'onboarding.chatProviderDesc': 'Scegli come vuoi interagire con il tuo assistente.', + 'onboarding.referral': 'Codice referral', + 'onboarding.referralDesc': 'Applica un codice referral se ne hai uno.', + 'onboarding.finish': 'Termina configurazione', + 'onboarding.finishDesc': 'Tutto pronto! Inizia a usare OpenHuman.', + 'onboarding.skip': 'Salta', + 'onboarding.getStarted': 'Inizia', + 'onboarding.runtimeChoice.title': 'Come vuoi eseguire OpenHuman?', + 'onboarding.runtimeChoice.subtitle': + 'Scegli la configurazione che fa per te. Puoi cambiarla in seguito nelle Impostazioni.', + 'onboarding.runtimeChoice.cloud.title': 'Semplice', + 'onboarding.runtimeChoice.cloud.tagline': 'Lascia che OpenHuman gestisca tutto per te.', + 'onboarding.runtimeChoice.cloud.f1': 'Sicurezza integrata', + 'onboarding.runtimeChoice.cloud.f2': 'Compressione token per allungare il tuo utilizzo', + 'onboarding.runtimeChoice.cloud.f3': 'Un solo abbonamento, tutti i modelli inclusi', + 'onboarding.runtimeChoice.cloud.f4': 'Nessuna chiave API da gestire', + 'onboarding.runtimeChoice.cloud.f5': 'Configurazione semplice', + 'onboarding.runtimeChoice.custom.title': 'Esegui personalizzato', + 'onboarding.runtimeChoice.custom.tagline': 'Porta le tue chiavi. Pieno controllo di ciò che usi.', + 'onboarding.runtimeChoice.custom.f1': 'Avrai bisogno di chiavi API per quasi tutto', + 'onboarding.runtimeChoice.custom.f2': 'Riutilizza servizi che già paghi', + 'onboarding.runtimeChoice.custom.f3': 'Può essere gratis se esegui tutto localmente', + 'onboarding.runtimeChoice.custom.f4': 'Più configurazione, più parametri', + 'onboarding.runtimeChoice.custom.f5': 'Ideale per power user e sviluppatori', + 'onboarding.runtimeChoice.cloud.creditHighlight': '1$ di credito gratuito per provarlo', + 'onboarding.runtimeChoice.continueCloud': 'Continua con Semplice', + 'onboarding.runtimeChoice.continueCustom': 'Continua con Personalizzato', + 'onboarding.runtimeChoice.recommended': 'Consigliato', + 'onboarding.apiKeys.title': 'Aggiungiamo le tue chiavi API', + 'onboarding.apiKeys.subtitle': + 'Puoi incollarle ora o saltare e aggiungerle dopo in Impostazioni › AI. Le chiavi sono memorizzate su questo dispositivo, crittografate a riposo.', + 'onboarding.apiKeys.openaiLabel': 'Chiave API OpenAI', + 'onboarding.apiKeys.openaiPlaceholder': 'sk-...', + 'onboarding.apiKeys.anthropicLabel': 'Chiave API Anthropic', + 'onboarding.apiKeys.anthropicPlaceholder': 'sk-ant-...', + 'onboarding.apiKeys.saveError': 'Impossibile salvare la chiave. Controllala e riprova.', + 'onboarding.apiKeys.skipForNow': 'Salta per ora', + 'onboarding.apiKeys.continue': 'Salva e continua', + 'onboarding.apiKeys.saving': 'Salvataggio…', + 'onboarding.custom.stepperInference': 'Inferenza', + 'onboarding.custom.stepperVoice': 'Voce', + 'onboarding.custom.stepperOAuth': 'OAuth', + 'onboarding.custom.stepperSearch': 'Ricerca', + 'onboarding.custom.stepperMemory': 'Memoria', + 'onboarding.custom.stepCounter': 'Passo {n} di {total}', + 'onboarding.custom.defaultTitle': 'Predefinito', + 'onboarding.custom.defaultSubtitle': 'Lascia che OpenHuman lo gestisca per te.', + 'onboarding.custom.configureTitle': 'Configura', + 'onboarding.custom.configureSubtitle': 'Scelgo io cosa usare.', + 'onboarding.custom.progressAriaLabel': 'Avanzamento onboarding', + 'onboarding.custom.continue': 'Continua', + 'onboarding.custom.back': 'Indietro', + 'onboarding.custom.finish': 'Termina configurazione', + 'onboarding.custom.configureLater': + "Puoi finire di configurare dopo l'onboarding. Ti porteremo alla pagina Impostazioni corrispondente al termine.", + 'onboarding.custom.openSettings': 'Apri in Impostazioni', + 'onboarding.custom.inference.title': 'Inferenza (testo)', + 'onboarding.custom.inference.subtitle': + 'Quale modello linguistico dovrebbe rispondere alle tue domande ed eseguire i tuoi agenti?', + 'onboarding.custom.inference.defaultDesc': + 'OpenHuman instrada ogni carico di lavoro a un modello predefinito sensato. Niente chiavi, niente configurazione.', + 'onboarding.custom.inference.configureDesc': + 'Porta la tua chiave OpenAI o Anthropic. La useremo per ogni carico di lavoro testuale.', + 'onboarding.custom.voice.title': 'Voce', + 'onboarding.custom.voice.subtitle': 'Speech-to-text e text-to-speech per la modalità vocale.', + 'onboarding.custom.voice.defaultDesc': + 'OpenHuman include STT/TTS gestiti che funzionano subito. Niente da configurare.', + 'onboarding.custom.voice.configureDesc': + 'Usa il tuo ElevenLabs / OpenAI Whisper / ecc. Configura in Impostazioni › Voce.', + 'onboarding.custom.oauth.title': 'Connessioni (OAuth)', + 'onboarding.custom.oauth.subtitle': + 'Gmail, Slack, Notion e altri servizi connessi che richiedono OAuth.', + 'onboarding.custom.oauth.defaultDesc': + 'OpenHuman gestisce un workspace Composio gestito. Un clic per connettere ogni servizio in seguito.', + 'onboarding.custom.oauth.configureDesc': + 'Porta il tuo account Composio / chiave API. Configura in Impostazioni › Connessioni.', + 'onboarding.custom.search.title': 'Ricerca web', + 'onboarding.custom.search.subtitle': 'Come OpenHuman cerca sul web per tuo conto.', + 'onboarding.custom.search.defaultDesc': + 'OpenHuman usa un backend di ricerca gestito. Nessuna chiave necessaria.', + 'onboarding.custom.search.configureDesc': + 'Porta la tua chiave di provider di ricerca (Tavily, Brave, ecc.). Configura in Impostazioni › Strumenti.', + 'onboarding.custom.memory.title': 'Memoria', + 'onboarding.custom.memory.subtitle': + 'Come OpenHuman ricorda il tuo contesto, le preferenze e le conversazioni precedenti.', + 'onboarding.custom.memory.defaultDesc': + "OpenHuman gestisce automaticamente l'archiviazione e il recupero della memoria. Niente da configurare.", + 'onboarding.custom.memory.configureDesc': + 'Ispeziona, esporta o cancella la memoria da solo. Configura in Impostazioni › Memoria.', + 'accounts.addAccount': 'Aggiungi account', + 'accounts.manageAccounts': 'Gestisci account', + 'accounts.noAccounts': 'Nessun account connesso', + 'accounts.connectAccount': 'Connetti un account per iniziare', + 'accounts.agent': 'Agente', + 'accounts.respondQueue': 'Coda di risposta', + 'accounts.disconnect': 'Disconnetti', + 'accounts.disconnectConfirm': 'Sei sicuro di voler disconnettere questo account?', + 'accounts.searchAccounts': 'Cerca account...', + 'channels.title': 'Canali', + 'channels.configure': 'Configura canale', + 'channels.setup': 'Configura', + 'channels.noChannels': 'Nessun canale configurato', + 'channels.addChannel': 'Aggiungi canale', + 'channels.status.connected': 'Connesso', + 'channels.status.disconnected': 'Disconnesso', + 'channels.status.error': 'Errore', + 'channels.status.configuring': 'Configurazione', + 'channels.defaultMessaging': 'Canale di messaggistica predefinito', + 'webhooks.title': 'Webhook', + 'webhooks.create': 'Crea webhook', + 'webhooks.noWebhooks': 'Nessun webhook configurato', + 'webhooks.url': 'URL', + 'webhooks.secret': 'Segreto', + 'webhooks.events': 'Eventi', + 'webhooks.archiveDirectory': 'Directory di archivio', + 'webhooks.todayFile': 'File di oggi', + 'invites.title': 'Inviti', + 'invites.create': 'Crea invito', + 'invites.noInvites': 'Nessun invito in sospeso', + 'invites.code': 'Codice invito', + 'invites.copyLink': 'Copia link', + 'devOptions.title': 'Avanzate', + 'devOptions.diagnostics': 'Diagnostica', + 'devOptions.diagnosticsDesc': 'Stato del sistema, log e metriche di performance', + 'devOptions.debugPanels': 'Pannelli di debug', + 'devOptions.debugPanelsDesc': 'Feature flag, ispezione dello stato e strumenti di debug', + 'devOptions.webhooks': 'Webhook', + 'devOptions.webhooksDesc': 'Configura e testa le integrazioni webhook', + 'devOptions.memoryInspection': 'Ispezione memoria', + 'devOptions.memoryInspectionDesc': 'Esplora, interroga e gestisci le voci di memoria', + 'voice.pushToTalk': 'Push to talk', + 'voice.recording': 'Registrazione...', + 'voice.processing': 'Elaborazione...', + 'voice.languageHint': 'Lingua', + 'misc.rehydrating': 'Caricamento dei tuoi dati...', + 'misc.checkingServices': 'Verifica servizi...', + 'misc.serviceUnavailable': 'Servizio non disponibile', + 'misc.somethingWentWrong': 'Qualcosa è andato storto', + 'misc.tryAgainLater': 'Riprova più tardi.', + 'misc.restartApp': 'Riavvia app', + 'misc.updateAvailable': 'Aggiornamento disponibile', + 'misc.updateNow': 'Aggiorna ora', + 'misc.updateLater': 'Più tardi', + 'misc.downloading': 'Download in corso...', + 'misc.installing': 'Installazione...', + 'misc.beta': + 'OpenHuman è in beta iniziale. Sentiti libero di condividere feedback o segnalare bug che incontri — ogni segnalazione ci aiuta a rilasciare più velocemente.', + 'misc.betaFeedback': 'Invia feedback', + 'mnemonic.title': 'Frase di recupero', + 'mnemonic.warning': 'Scrivi queste parole in ordine e conservale in un luogo sicuro.', + 'mnemonic.copyWarning': + 'Non condividere mai la tua frase di recupero. Chiunque abbia queste parole può accedere al tuo account.', + 'mnemonic.copied': 'Frase di recupero copiata negli appunti', + 'mnemonic.reveal': 'Mostra frase', + 'mnemonic.hidden': 'La frase di recupero è nascosta', + 'privacy.title': 'Privacy e sicurezza', + 'privacy.description': 'Report di trasparenza sui dati inviati a servizi esterni.', + 'privacy.empty': 'Nessun trasferimento di dati esterno rilevato.', + 'privacy.whatLeavesComputer': 'Cosa esce dal tuo computer', + 'privacy.loading': 'Caricamento dettagli privacy...', + 'privacy.loadError': + "Impossibile caricare l'elenco privacy in tempo reale. I controlli analytics sottostanti funzionano comunque.", + 'privacy.noCapabilities': 'Nessuna capacità attualmente divulga movimenti di dati.', + 'privacy.sentTo': 'Inviato a', + 'privacy.leavesDevice': 'Esce dal dispositivo', + 'privacy.staysLocal': 'Rimane locale', + 'privacy.anonymizedAnalytics': 'Analisi anonimizzate', + 'privacy.shareAnonymizedData': 'Condividi dati di utilizzo anonimizzati', + 'privacy.shareAnonymizedDataDesc': + 'Aiuta a migliorare OpenHuman condividendo report di crash anonimi e analisi di utilizzo. Tutti i dati sono completamente anonimizzati — nessun dato personale, messaggio, chiave wallet o informazione di sessione viene mai raccolto.', + 'privacy.meetingFollowUps': 'Follow-up delle riunioni', + 'privacy.autoHandoffMeet': + "Trasferimento automatico delle trascrizioni Google Meet all'orchestratore", + 'privacy.autoHandoffMeetDesc': + "Quando termina una chiamata Google Meet, l'orchestratore di OpenHuman può leggere la trascrizione e svolgere azioni come redigere messaggi, pianificare follow-up o pubblicare riassunti nel tuo workspace Slack connesso. Disattivato di default.", + 'privacy.analyticsDisclaimer': + 'Tutti i report analitici e bug sono completamente anonimi. Quando abilitati, raccogliamo solo informazioni sui crash, tipo di dispositivo e percorso file degli errori. Non accediamo mai ai tuoi messaggi, dati di sessione, chiavi del wallet, chiavi API o informazioni personali identificabili. Puoi cambiare questa impostazione in qualsiasi momento.', + 'settings.about.version': 'Versione', + 'settings.about.updateAvailable': 'è disponibile', + 'settings.about.softwareUpdates': 'Aggiornamenti software', + 'settings.about.lastChecked': 'Ultima verifica', + 'settings.about.checking': 'Verifica in corso...', + 'settings.about.checkForUpdates': 'Verifica aggiornamenti', + 'settings.about.releases': 'Release', + 'settings.about.releasesDesc': 'Sfoglia le note di rilascio e le build precedenti su GitHub.', + 'settings.about.openReleases': 'Apri release GitHub', + 'settings.ai.overview': 'Panoramica sistema AI', +}; + +export default it1; diff --git a/app/src/lib/i18n/chunks/it-2.ts b/app/src/lib/i18n/chunks/it-2.ts new file mode 100644 index 000000000..f4427d326 --- /dev/null +++ b/app/src/lib/i18n/chunks/it-2.ts @@ -0,0 +1,385 @@ +import type { TranslationMap } from '../types'; + +// Italian (Italiano) chunk 2/5. Translated from chunks/en-2.ts. +const it2: TranslationMap = { + 'settings.ai.configStatus': 'Stato configurazione', + 'settings.ai.fallbackMode': 'Modalità di fallback', + 'settings.ai.loadedFromRuntime': 'Caricato dal runtime', + 'settings.ai.loadingDuration': 'Durata caricamento', + 'settings.ai.localRuntime': 'Runtime modello locale', + 'settings.ai.openManager': 'Apri manager', + 'settings.ai.retryDownload': 'Riprova download', + 'settings.ai.state': 'Stato', + 'settings.ai.targetModel': 'Modello target', + 'settings.ai.download': 'Scarica', + 'settings.ai.localModelUnavailable': 'Stato modello locale non disponibile.', + 'settings.ai.soulConfig': 'Configurazione persona SOUL', + 'settings.ai.refreshing': 'Aggiornamento...', + 'settings.ai.refreshSoul': 'Aggiorna SOUL', + 'settings.ai.loadingSoul': 'Caricamento configurazione SOUL...', + 'settings.ai.identity': 'Identità', + 'settings.ai.personality': 'Personalità', + 'settings.ai.safetyRules': 'Regole di sicurezza', + 'settings.ai.source': 'Origine', + 'settings.ai.loaded': 'Caricato', + 'settings.ai.toolsConfig': 'Configurazione TOOLS', + 'settings.ai.refreshTools': 'Aggiorna TOOLS', + 'settings.ai.toolsAvailable': 'Strumenti disponibili', + 'settings.ai.tools': 'strumenti', + 'settings.ai.activeSkills': 'Skill attive', + 'settings.ai.skills': 'skill', + 'settings.ai.skillsOverview': 'Panoramica skill', + 'settings.ai.refreshingAll': 'Aggiornamento totale...', + 'settings.ai.refreshAll': 'Aggiorna tutta la configurazione AI', + 'settings.notifications.suppressAll': 'Sopprimi tutte le notifiche', + 'settings.notifications.suppressAllDesc': + "Blocca tutti i toast di notifica dell'OS dalle app integrate indipendentemente dallo stato di focus.", + 'settings.notifications.toggleDnd': 'Attiva/disattiva Non disturbare', + 'settings.notifications.categories': 'Categorie', + 'settings.notifications.categoryFooter': + 'Disabilitare una categoria impedisce alle nuove notifiche di quel tipo di apparire nel centro notifiche. Le notifiche esistenti rimangono finché non vengono cancellate.', + 'settings.billing.movedToWeb': 'La fatturazione è stata spostata sul web', + 'settings.billing.openDashboard': 'Apri dashboard fatturazione', + 'settings.billing.movedToWebDesc': + "Le modifiche all'abbonamento, i metodi di pagamento, i crediti e le fatture sono ora gestiti su TinyHumans sul web.", + 'settings.billing.backToSettings': 'Torna alle impostazioni', + 'settings.billing.openingBrowser': 'Apertura del browser...', + 'settings.billing.browserNotOpen': 'Se il browser non si è aperto, usa il pulsante sopra.', + 'settings.billing.browserOpenFailed': + 'Impossibile aprire automaticamente il browser. Usa il pulsante sopra.', + 'settings.tools.chooseCapabilities': 'Scegli quali capacità OpenHuman può usare per tuo conto.', + 'settings.tools.saveChanges': 'Salva modifiche', + 'settings.tools.preferencesSaved': 'Preferenze salvate', + 'settings.tools.saveFailed': 'Salvataggio preferenze fallito. Riprova.', + 'settings.screenAwareness.mode': 'Modalità', + 'settings.screenAwareness.allExceptBlacklist': 'Tutti tranne blacklist', + 'settings.screenAwareness.whitelistOnly': 'Solo whitelist', + 'settings.screenAwareness.screenMonitoring': 'Monitoraggio schermo', + 'settings.screenAwareness.saveSettings': 'Salva impostazioni', + 'settings.screenAwareness.session': 'Sessione', + 'settings.screenAwareness.status': 'Stato', + 'settings.screenAwareness.active': 'Attivo', + 'settings.screenAwareness.stopped': 'Fermato', + 'settings.screenAwareness.remaining': 'Rimanente', + 'settings.screenAwareness.startSession': 'Avvia sessione', + 'settings.screenAwareness.stopSession': 'Ferma sessione', + 'settings.screenAwareness.analyzeNow': 'Analizza ora', + 'settings.screenAwareness.macosOnly': + 'La cattura desktop di Consapevolezza schermo e i controlli dei permessi sono attualmente supportati solo su macOS.', + 'connections.comingSoon': 'In arrivo', + 'connections.setUp': 'Configura', + 'connections.configured': 'Configurato', + 'connections.unavailable': 'Non disponibile', + 'connections.checking': 'Verifica…', + 'connections.walletConfigured': + 'Le identità locali EVM, BTC, Solana e Tron sono configurate dalla tua frase di recupero.', + 'connections.walletReady': + "Configura identità locali EVM, BTC, Solana e Tron da un'unica frase di recupero.", + 'connections.walletError': + 'Impossibile verificare lo stato del wallet. Tocca per riprovare dal pannello Frase di recupero.', + 'connections.walletChecking': 'Verifica stato wallet...', + 'connections.walletIdentities': 'Identità wallet', + 'connections.walletDerived': + 'Derivato localmente dalla tua frase di recupero e memorizzato solo come metadato sicuro.', + 'connections.privacySecurity': 'Privacy e sicurezza', + 'connections.privacySecurityDesc': + 'Tutti i dati e le credenziali sono memorizzati localmente con una politica di zero conservazione. Le tue informazioni sono crittografate e mai condivise con terze parti.', + 'channels.status.connecting': 'Connessione', + 'channels.status.notConfigured': 'Non configurato', + 'channels.noActiveRoute': 'Nessuna route attiva', + 'channels.activeRoute': 'Route attiva', + 'channels.loadingDefinitions': 'Caricamento definizioni canali...', + 'channels.channelConnections': 'Connessioni dei canali', + 'channels.configureAuthModes': + 'Configura le modalità di autenticazione per ciascun canale di messaggistica.', + 'channels.configNotAvailable': 'Configurazione per', + 'channels.channel': 'canale', + 'devOptions.coreModeNotSet': 'Modalità core: non impostata', + 'devOptions.coreModeNotSetDesc': + 'Il selettore del controllo di avvio non è stato ancora confermato. Usa Cambia modalità sul selettore per scegliere Locale o Cloud.', + 'devOptions.local': 'Locale', + 'devOptions.embeddedCoreSidecar': 'Sidecar core integrato', + 'devOptions.sidecarSpawned': "Avviato in-process dalla shell Tauri all'avvio dell'app.", + 'devOptions.cloud': 'Cloud', + 'devOptions.remoteCoreRpc': 'RPC core remoto', + 'devOptions.token': 'Token', + 'devOptions.tokenNotSet': 'non impostato — RPC restituirà 401', + 'devOptions.triggerSentryTest': 'Attiva test Sentry (staging)', + 'devOptions.triggerSentryTestDesc': + 'Genera un errore taggato per verificare la pipeline Sentry. Issue #1072 — rimuovere dopo la verifica.', + 'devOptions.sendTestEvent': 'Invia evento di test', + 'devOptions.sending': 'Invio…', + 'devOptions.eventSent': 'Evento inviato', + 'devOptions.failed': 'Fallito', + 'devOptions.appLogs': "Log dell'app", + 'devOptions.appLogsDesc': + 'Apri la cartella che contiene i file di log giornalieri. Allega il file più recente quando segnali un problema.', + 'devOptions.openLogsFolder': 'Apri cartella log', + 'mnemonic.phraseSaved': 'Frase di recupero salvata', + 'mnemonic.walletReady': + 'Le identità wallet multi-chain sono pronte. Ritorno alle impostazioni...', + 'mnemonic.writeDownWords': 'Scrivi queste', + 'mnemonic.wordsInOrder': + 'parole in ordine e conservale in un luogo sicuro. Questa frase protegge la tua chiave di crittografia locale e le identità wallet EVM, BTC, Solana e Tron.', + 'mnemonic.cannotRecover': + 'Questa frase non può mai essere recuperata se persa e dovrebbe rimanere completamente locale sul tuo dispositivo.', + 'mnemonic.copyToClipboard': 'Copia negli appunti', + 'mnemonic.alreadyHavePhrase': 'Ho già una frase di recupero', + 'mnemonic.consentSaved': + 'Ho salvato questa frase e acconsento ad usarla per la configurazione del wallet locale', + 'mnemonic.enterPhraseToRestore': + 'Inserisci la tua frase di recupero qui sotto per ripristinare le identità del wallet locale, oppure incolla la frase completa in qualsiasi campo (12 parole per i nuovi backup; le frasi a 24 parole delle versioni precedenti funzionano ancora).', + 'mnemonic.words': 'Parole', + 'mnemonic.validPhrase': 'Frase di recupero valida', + 'mnemonic.generateNewPhrase': 'Genera invece una nuova frase di recupero', + 'mnemonic.securingData': 'Protezione dei tuoi dati...', + 'mnemonic.saveRecoveryPhrase': 'Salva frase di recupero', + 'mnemonic.userNotLoaded': 'Utente non caricato. Accedi di nuovo o ricarica la pagina.', + 'mnemonic.invalidPhrase': 'Frase di recupero non valida. Controlla le parole e riprova.', + 'mnemonic.somethingWentWrong': 'Qualcosa è andato storto. Riprova.', + 'team.failedToCreate': 'Creazione team fallita', + 'team.invalidInviteCode': 'Codice invito non valido o scaduto', + 'team.failedToSwitch': 'Cambio team fallito', + 'team.failedToLeave': 'Uscita dal team fallita', + 'team.role.owner': 'Proprietario', + 'team.role.admin': 'Admin', + 'team.role.billingManager': 'Responsabile fatturazione', + 'team.role.member': 'Membro', + 'team.active': 'Attivo', + 'team.personalTeam': 'Team personale', + 'team.manageTeam': 'Gestisci team', + 'team.switching': 'Cambio...', + 'team.switch': 'Cambia', + 'team.leaving': 'Uscita...', + 'team.leave': 'Lascia', + 'team.yourTeams': 'I tuoi team', + 'team.createNewTeam': 'Crea nuovo team', + 'team.teamName': 'Nome team', + 'team.creating': 'Creazione...', + 'team.joinExistingTeam': 'Unisciti a un team esistente', + 'team.inviteCode': 'Codice invito', + 'team.joining': 'Adesione...', + 'team.join': 'Unisciti', + 'team.leaveTeam': 'Lascia team', + 'team.confirmLeave': 'Sei sicuro di voler lasciare', + 'team.leaveWarning': + "Perderai l'accesso al team e a tutte le sue risorse. Servirà un nuovo invito per rientrare.", + 'team.management': 'Gestione team', + 'team.notFound': 'Team non trovato', + 'team.accessDenied': 'Accesso negato', + 'team.members': 'Membri', + 'voice.title': 'Dettatura vocale', + 'voice.settings': 'Impostazioni voce', + 'voice.settingsDesc': "Tieni premuta l'hotkey per dettare e inserire testo nel campo attivo.", + 'voice.hotkey': 'Hotkey', + 'voice.activationMode': 'Modalità di attivazione', + 'voice.tapToToggle': 'Tocca per attivare/disattivare', + 'voice.writingStyle': 'Stile di scrittura', + 'voice.verbatimTranscription': 'Trascrizione letterale', + 'voice.naturalCleanup': 'Pulizia naturale', + 'voice.autoStart': 'Avvia il server vocale automaticamente con il core', + 'voice.customDictionary': 'Dizionario personalizzato', + 'voice.customDictionaryDesc': + "Aggiungi nomi, termini tecnici e parole di dominio per migliorare l'accuratezza del riconoscimento.", + 'voice.addWord': 'Aggiungi una parola...', + 'voice.sttDisabled': + 'La dettatura vocale è disabilitata finché il modello STT locale non è scaricato e pronto.', + 'voice.openLocalAiModel': 'Apri modello AI locale', + 'voice.serverRestarted': 'Server vocale riavviato con le nuove impostazioni.', + 'voice.settingsSaved': 'Impostazioni vocali salvate.', + 'voice.serverStarted': 'Server vocale avviato.', + 'voice.serverStopped': 'Server vocale fermato.', + 'voice.saveVoiceSettings': 'Salva impostazioni vocali', + 'voice.startVoiceServer': 'Avvia server vocale', + 'voice.stopVoiceServer': 'Ferma server vocale', + 'voice.debugTitle': 'Debug voce', + 'autocomplete.title': 'Autocompletamento', + 'autocomplete.settings': 'Impostazioni', + 'autocomplete.acceptWithTab': 'Accetta con Tab', + 'autocomplete.stylePreset': 'Preset di stile', + 'autocomplete.style.balanced': 'Bilanciato', + 'autocomplete.style.concise': 'Conciso', + 'autocomplete.style.formal': 'Formale', + 'autocomplete.style.casual': 'Informale', + 'autocomplete.style.custom': 'Personalizzato', + 'autocomplete.disabledApps': 'App disabilitate (un bundle/app token per riga)', + 'autocomplete.saveSettings': 'Salva impostazioni', + 'autocomplete.saving': 'Salvataggio…', + 'autocomplete.runtime': 'Runtime', + 'autocomplete.running': 'In esecuzione', + 'autocomplete.start': 'Avvia', + 'autocomplete.stop': 'Ferma', + 'autocomplete.settingsSaved': 'Impostazioni di autocompletamento salvate.', + 'autocomplete.started': 'Autocompletamento avviato.', + 'autocomplete.didNotStart': 'Autocompletamento non avviato. Verifica che sia abilitato.', + 'autocomplete.stopped': 'Autocompletamento fermato.', + 'autocomplete.advancedSettings': 'Impostazioni avanzate', + 'autocomplete.debugTitle': 'Debug autocompletamento', + 'chat.agentChat': 'Chat agente', + 'chat.overrides': 'Override', + 'chat.model': 'Modello', + 'chat.temperature': 'Temperatura', + 'chat.conversation': 'Conversazione', + 'chat.startAgentConversation': "Inizia una conversazione con l'agente.", + 'chat.you': 'Tu', + 'chat.agent': 'Agente', + 'chat.askAgent': "Chiedi qualsiasi cosa all'agente...", + 'chat.sendMessage': 'Invia messaggio', + 'composio.triageTitle': 'Trigger delle integrazioni', + 'composio.triageDesc': + "Quando attivo, ogni trigger Composio in arrivo passa per uno step di triage AI che classifica l'evento e può avviare azioni automatiche — un turno LLM locale per trigger. Disabilita globalmente o per singola integrazione se preferisci la revisione manuale. Se la variabile d'ambiente", + 'composio.disableAllTriage': 'Disabilita il triage AI per tutti i trigger', + 'composio.triggersStillRecorded': + 'I trigger vengono comunque registrati nella cronologia — nessun turno LLM viene eseguito.', + 'composio.disableSpecificIntegrations': 'Disabilita il triage AI per integrazioni specifiche', + 'composio.settingsSaved': 'Impostazioni salvate', + 'composio.saveFailed': 'Salvataggio fallito. Riprova.', + 'cron.title': 'Cron Job', + 'cron.scheduledJobs': 'Job pianificati', + 'cron.manageCronJobs': 'Gestisci i cron job dal core scheduler.', + 'cron.refreshCronJobs': 'Aggiorna cron job', + 'localModel.modelStatus': 'Stato del modello', + 'localModel.downloadModels': 'Scarica modelli', + 'localModel.usage': 'Utilizzo', + 'localModel.usageDesc': + 'Scegli quali sottosistemi girano sul modello locale. Quelli disattivati usano il cloud.', + 'localModel.enableRuntime': 'Abilita runtime AI locale', + 'localModel.enableRuntimeDesc': + "Interruttore principale. Disattivato di default — Ollama resta inattivo. Quando attivo, il tree summarizer, lo screen intelligence e l'autocompletamento usano sempre il modello locale.", + 'localModel.advancedSettings': 'Impostazioni avanzate', + 'localModel.debugTitle': 'Debug modello locale', + 'screenAwareness.debugTitle': 'Debug consapevolezza schermo', + 'memory.debugTitle': 'Debug memoria', + 'webhooks.debugTitle': 'Debug webhook', + 'notifications.routingTitle': 'Instradamento notifiche', + 'common.reload': 'Ricarica', + 'common.skip': 'Salta', + 'common.disable': 'Disabilita', + 'common.enable': 'Abilita', + 'chat.safetyTimeout': + "Nessuna risposta dall'agente dopo 2 minuti. Riprova o controlla la connessione.", + 'chat.filter.all': 'Tutti', + 'chat.filter.work': 'Lavoro', + 'chat.filter.briefing': 'Briefing', + 'chat.filter.notification': 'Notifica', + 'chat.filter.workers': 'Worker', + 'chat.selectThread': 'Seleziona un thread', + 'chat.threads': 'Thread', + 'chat.noThreads': 'Nessun thread', + 'chat.noLabelThreads': 'Nessun thread "{label}"', + 'chat.noWorkerThreads': 'Nessun thread worker', + 'chat.deleteThread': 'Elimina thread', + 'chat.deleteThreadConfirm': 'Sei sicuro di voler eliminare "{title}"?', + 'chat.untitledThread': 'Thread senza titolo', + 'chat.hideSidebar': 'Nascondi barra laterale', + 'chat.showSidebar': 'Mostra barra laterale', + 'chat.newThreadShortcut': 'Nuovo thread (/new)', + 'chat.new': 'Nuovo', + 'chat.failedToLoadMessages': 'Impossibile caricare i messaggi', + 'chat.thinkingIteration': 'Sto pensando... ({n})', + 'chat.thinkingDots': 'Sto pensando...', + 'chat.approachingLimit': 'Limite di utilizzo in avvicinamento', + 'chat.approachingLimitMsg': 'Hai usato il {pct}% della tua quota disponibile.', + 'chat.upgrade': 'Aggiorna', + 'chat.weeklyLimitHit': 'Hai raggiunto il limite settimanale.', + 'chat.resets': 'Reset', + 'chat.topUpToContinue': 'Ricarica per continuare.', + 'chat.budgetComplete': + 'Il tuo budget incluso è esaurito. Aggiungi crediti o passa a un piano superiore per continuare.', + 'chat.rateLimitReached': 'Limite di velocità di 10 ore raggiunto.', + 'chat.topUp': 'Ricarica', + 'chat.fiveHourLimit': 'Limite di 5 ore', + 'chat.weeklyLimit': 'Limite settimanale', + 'chat.left': 'rimasti', + 'chat.setup': 'Configura', + 'chat.switchToText': 'Passa al testo', + 'chat.transcribing': 'Trascrizione...', + 'chat.stopAndSend': 'Ferma e invia', + 'chat.startTalking': 'Inizia a parlare', + 'chat.playingVoiceReply': 'Riproduzione risposta vocale', + 'chat.voiceHint': 'Usa il microfono per parlare', + 'chat.micUnavailable': 'Microfono non disponibile', + 'chat.turn': 'turno', + 'chat.turns': 'turni', + 'chat.openWorkerThread': 'Apri thread worker', + 'memory.searchAria': 'Cerca memoria', + 'memory.searchPlaceholder': 'Cerca voci di memoria...', + 'memory.sourceFilter.all': 'Tutte le origini', + 'memory.sourceFilter.email': 'Email', + 'memory.sourceFilter.calendar': 'Calendario', + 'memory.sourceFilter.telegram': 'Telegram', + 'memory.sourceFilter.aiInsight': 'AI Insight', + 'memory.sourceFilter.system': 'Sistema', + 'memory.sourceFilter.trading': 'Trading', + 'memory.sourceFilter.security': 'Sicurezza', + 'memory.ingestionActivity': 'Attività di ingestione', + 'memory.events': 'eventi', + 'memory.event': 'evento', + 'memory.overTheLast': 'negli ultimi', + 'memory.months': 'mesi', + 'memory.peak': 'Picco', + 'memory.perDay': '/giorno', + 'memory.less': 'Meno', + 'memory.more': 'Più', + 'memory.on': 'il', + 'memory.loading': 'Caricamento memoria', + 'memory.fetching': 'Recupero delle tue voci di memoria...', + 'memory.analyzing': 'Analisi della memoria', + 'memory.analyzingHint': 'Elaborazione delle tue memorie per estrarre insight...', + 'memory.noMatches': 'Nessuna corrispondenza trovata', + 'memory.noMatchesHint': 'Prova a cambiare i termini di ricerca o i filtri.', + 'memory.allCaughtUp': 'Tutto aggiornato', + 'memory.allCaughtUpHint': 'Nessuna nuova voce di memoria da elaborare.', + 'memory.noAnalysis': 'Nessuna analisi', + 'memory.noAnalysisHint': "Esegui un'analisi per scoprire pattern nelle tue memorie.", + 'memory.emptyHint': 'Inizia a interagire per creare le tue prime memorie.', + 'mic.unavailable': 'Microfono non disponibile', + 'mic.permissionDenied': 'Permesso microfono negato', + 'mic.failedToStartRecorder': 'Avvio del registratore fallito', + 'mic.transcribing': 'Trascrizione...', + 'mic.tapToSend': 'Tocca per inviare', + 'mic.waitingForAgent': "In attesa dell'agente...", + 'mic.tapAndSpeak': 'Tocca e parla', + 'mic.stopRecording': 'Ferma registrazione e invia', + 'mic.startRecording': 'Avvia registrazione', + 'token.usageLimitReached': 'Limite di utilizzo raggiunto', + 'token.approachingLimit': 'Limite in avvicinamento', + 'token.planClickForDetails': 'piano - clicca per dettagli', + 'token.sessionTokens': 'Ingresso: {in} | Uscita: {out} | Turni: {turns}', + 'token.limit': 'Limite raggiunto', + 'catalog.noCapabilityBinding': 'Nessun binding di capacità', + 'catalog.downloadFailed': 'Download fallito', + 'catalog.active': 'Attivo', + 'catalog.installed': 'Installato', + 'catalog.notDownloaded': 'Non scaricato', + 'catalog.inUse': 'In uso', + 'catalog.use': 'Usa', + 'catalog.deleteModel': 'Elimina modello', + 'catalog.download': 'Scarica', + 'navigator.recent': 'Recenti', + 'navigator.today': 'Oggi', + 'navigator.thisWeek': 'Questa settimana', + 'navigator.sources': 'Origini', + 'navigator.email': 'Email', + 'navigator.slack': 'Slack', + 'navigator.chat': 'Chat', + 'navigator.documents': 'Documenti', + 'navigator.people': 'Persone', + 'navigator.topics': 'Argomenti', + 'dreams.description': + "I sogni sono riflessioni generate dall'AI che sintetizzano i pattern dalle tue memorie.", + 'dreams.comingSoon': 'In arrivo', + 'assignment.memoryLlm': 'LLM memoria', + 'assignment.memoryLlmAria': 'Selezione LLM memoria', + 'assignment.embedder': 'Embedder', + 'assignment.loaded': 'Caricato', + 'assignment.notDownloaded': 'Non scaricato', + 'assignment.usedForExtractSummarise': 'Usato per estrazione e riassunto', + 'insights.knownFacts': 'Fatti noti', + 'insights.preferences': 'Preferenze', + 'insights.relationships': 'Relazioni', + 'insights.skills': 'Competenze', + 'insights.opinions': 'Opinioni', +}; + +export default it2; diff --git a/app/src/lib/i18n/chunks/it-3.ts b/app/src/lib/i18n/chunks/it-3.ts new file mode 100644 index 000000000..f256c83e9 --- /dev/null +++ b/app/src/lib/i18n/chunks/it-3.ts @@ -0,0 +1,377 @@ +import type { TranslationMap } from '../types'; + +// Italian (Italiano) chunk 3/5. Translated from chunks/en-3.ts. +const it3: TranslationMap = { + 'insights.other': 'Altro', + 'insights.title': 'Insight', + 'insights.empty': + 'Nessuna insight. Le insight vengono generate man mano che la tua memoria cresce.', + 'insights.description': 'Basato su {count} relazioni nel tuo grafo di memoria.', + 'insights.items': 'elementi', + 'insights.more': 'altri', + 'calls.joiningCall': 'Accesso alla chiamata in corso', + 'calls.meetWindowOpening': 'La finestra di Meet si sta aprendo...', + 'calls.failedToStart': 'Avvio della chiamata Meet fallito', + 'calls.couldNotStart': 'Impossibile avviare la chiamata', + 'calls.failedToClose': 'Chiusura chiamata fallita', + 'calls.couldNotClose': 'Impossibile chiudere la chiamata', + 'calls.joinMeet': 'Unisciti a una chiamata Google Meet', + 'calls.joinMeetDescription': 'Inserisci un link Google Meet per unirti.', + 'calls.meetLink': 'Link Meet', + 'calls.displayName': 'Nome visualizzato', + 'calls.openingMeet': 'Apertura di Meet...', + 'calls.joinCall': 'Unisciti alla chiamata', + 'calls.activeCalls': 'Chiamate attive', + 'calls.leave': 'Esci', + 'workspace.wipeConfirm': + 'Sei sicuro di voler cancellare tutta la memoria? Questa azione non può essere annullata.', + 'workspace.resetTreeConfirm': "Sei sicuro di voler ricostruire l'albero di memoria?", + 'workspace.wipeTitle': 'Cancella memoria', + 'workspace.resetting': 'Ripristino...', + 'workspace.resetMemory': 'Ripristina memoria', + 'workspace.resetTreeTitle': 'Ricostruisci albero di memoria', + 'workspace.rebuilding': 'Ricostruzione...', + 'workspace.resetMemoryTree': 'Ripristina albero di memoria', + 'workspace.building': 'Costruzione...', + 'workspace.buildSummaryTrees': 'Costruisci alberi di riassunto', + 'workspace.viewVault': 'Visualizza vault', + 'workspace.graphLoadFailed': 'Impossibile caricare il grafo di memoria', + 'workspace.loadingGraph': 'Caricamento grafo di memoria...', + 'workspace.graphViewMode': 'Modalità di visualizzazione grafo di memoria', + 'workspace.trees': 'Alberi', + 'workspace.contacts': 'Contatti', + 'graph.noContactMentions': 'Nessuna menzione di contatto', + 'graph.noMemory': 'Nessuna memoria', + 'graph.source': 'Origine', + 'graph.topic': 'Argomento', + 'graph.global': 'Globale', + 'graph.document': 'Documento', + 'graph.contact': 'Contatto', + 'graph.nodes': 'nodi', + 'graph.parentChild': 'genitore-figlio', + 'graph.documentContact': 'documento-contatto', + 'graph.link': 'collegamento', + 'graph.links': 'collegamenti', + 'graph.children': 'figli', + 'graph.clickToOpenObsidian': 'Clic per aprire in Obsidian', + 'graph.person': 'Persona', + 'modal.dontShowAgain': 'Non mostrare suggerimenti simili', + 'reflections.loading': 'Caricamento riflessioni...', + 'reflections.empty': 'Nessuna riflessione', + 'reflections.title': 'Riflessioni', + 'reflections.proposedAction': 'Azione proposta', + 'reflections.act': 'Agisci', + 'reflections.dismiss': 'Ignora', + 'whatsapp.chatsSynced': 'chat sincronizzate', + 'whatsapp.chatSynced': 'chat sincronizzata', + 'sync.active': 'Attivo', + 'sync.recent': 'Recenti', + 'sync.idle': 'Inattivo', + 'sync.memorySources': 'Origini di memoria', + 'sync.noConnectedSources': 'Nessuna origine connessa', + 'sync.chunks': 'chunk', + 'sync.lastChunk': 'Ultimo chunk:', + 'sync.pending': 'in attesa', + 'sync.processed': 'elaborati', + 'sync.syncing': 'Sincronizzazione…', + 'sync.sync': 'Sincronizza', + 'sync.failedToLoad': 'Impossibile caricare lo stato di sincronizzazione', + 'sync.noContent': + "Nessun contenuto è stato sincronizzato nella memoria. Connetti un'integrazione per iniziare.", + 'backend.aiBackend': 'Backend AI', + 'backend.cloud': 'Cloud', + 'backend.recommended': 'Consigliato', + 'backend.cloudDescription': + "Modelli veloci e potenti ospitati sui nostri server. Pronti all'uso immediatamente.", + 'backend.privacyNote': + 'Nessun dato personale, messaggio o chiave viene mai inviato ai nostri server.', + 'backend.local': 'Locale', + 'backend.advanced': 'Avanzato', + 'backend.localDescription': + 'Esegui i modelli sulla tua macchina con Ollama. Privacy totale, richiede configurazione.', + 'backend.ramRecommended': '16GB+ di RAM consigliati', + 'subconscious.tasks': 'attività', + 'subconscious.ticks': 'tick', + 'subconscious.last': 'Ultimo', + 'subconscious.failed': 'fallito', + 'subconscious.tickInterval': 'Intervallo di tick', + 'subconscious.runNow': 'Esegui ora', + 'subconscious.approvalNeeded': 'Approvazione necessaria', + 'subconscious.requiresApproval': 'Richiede approvazione', + 'subconscious.fixInConnections': 'Correggi in Connessioni', + 'subconscious.goAhead': 'Procedi', + 'subconscious.activeTasks': 'Attività attive', + 'subconscious.noActiveTasks': 'Nessuna attività attiva', + 'subconscious.default': 'Predefinito', + 'subconscious.addTaskPlaceholder': 'Aggiungi una nuova attività...', + 'subconscious.activityLog': 'Log attività', + 'subconscious.noActivity': 'Nessuna attività', + 'subconscious.decision.nothingNew': 'Niente di nuovo', + 'subconscious.decision.completed': 'Completato', + 'subconscious.decision.evaluating': 'Valutazione', + 'subconscious.decision.waitingApproval': 'In attesa di approvazione', + 'subconscious.decision.failed': 'Fallito', + 'subconscious.decision.cancelled': 'Annullato', + 'subconscious.decision.skipped': 'Saltato', + 'actionable.complete': 'Completa', + 'actionable.dismiss': 'Ignora', + 'actionable.snooze': 'Posticipa', + 'actionable.new': 'Nuovo', + 'stats.storage': 'Archiviazione', + 'stats.files': 'file', + 'stats.documents': 'Documenti', + 'stats.today': 'oggi', + 'stats.namespaces': 'Namespace', + 'stats.relations': 'Relazioni', + 'stats.firstMemory': 'Prima memoria', + 'stats.latest': 'Ultime', + 'stats.sessions': 'Sessioni', + 'stats.tokens': 'token', + 'bootCheck.invalidUrl': 'Inserisci un URL di runtime.', + 'bootCheck.urlMustStartWith': "L'URL deve iniziare con http:// o https://", + 'bootCheck.validUrlRequired': 'Non sembra un URL valido (prova https://core.example.com/rpc)', + 'bootCheck.tokenRequired': 'Servirà un token di autenticazione per connettersi.', + 'bootCheck.chooseCoreMode': 'Seleziona un runtime', + 'bootCheck.connectToCore': 'Connetti al tuo runtime', + 'bootCheck.desktopDescription': + 'OpenHuman ha bisogno di un runtime per pensare. Scegli dove farlo girare.', + 'bootCheck.webDescription': + "Sul web, OpenHuman si connette a un runtime che controlli tu. Inserisci sotto URL e token di autenticazione, oppure scarica l'app desktop per farne girare uno direttamente sulla tua macchina.", + 'bootCheck.preferDesktop': 'Preferisci tenere tutto sul tuo dispositivo?', + 'bootCheck.downloadDesktop': "Scarica l'app desktop", + 'bootCheck.localRecommended': 'Esegui localmente (consigliato)', + 'bootCheck.localDescription': + 'Gira direttamente sul tuo computer. Più veloce, completamente privato, niente da configurare.', + 'bootCheck.cloudMode': 'Esegui sul cloud (complesso)', + 'bootCheck.cloudDescription': + 'Connettiti a un runtime che stai ospitando altrove. Resta online 24×7 così non devi tenere acceso questo dispositivo.', + 'bootCheck.coreRpcUrl': 'URL runtime', + 'bootCheck.rpcUrlPlaceholder': 'https://core.example.com/rpc', + 'bootCheck.authToken': 'Token di autenticazione', + 'bootCheck.bearerTokenPlaceholder': 'Il bearer token del tuo runtime remoto', + 'bootCheck.storedLocally': 'Conservato solo su questo dispositivo. Inviato come ', + 'bootCheck.testing': 'Test in corso…', + 'bootCheck.testConnection': 'Prova connessione', + 'bootCheck.connectedOk': 'Connesso. Tutto a posto.', + 'bootCheck.authFailed': 'Token non valido. Controllalo e riprova.', + 'bootCheck.unreachablePrefix': 'Impossibile raggiungerlo:', + 'bootCheck.checkingCore': 'Attivazione del runtime…', + 'bootCheck.cannotReach': 'Impossibile raggiungere il runtime', + 'bootCheck.cannotReachDesc': + 'Non siamo riusciti a connetterci al tuo runtime. Vuoi provarne uno diverso?', + 'bootCheck.switchMode': 'Scegli un runtime diverso', + 'bootCheck.quit': 'Esci', + 'bootCheck.legacyDetected': 'Runtime in background legacy rilevato', + 'bootCheck.legacyDescription': + 'Un daemon OpenHuman installato separatamente è già in esecuzione su questo dispositivo. Dobbiamo rimuoverlo prima che il runtime integrato possa subentrare.', + 'bootCheck.removing': 'Rimozione…', + 'bootCheck.removeContinue': 'Rimuovi e continua', + 'bootCheck.localNeedsRestart': 'Il runtime locale necessita di un riavvio', + 'bootCheck.localNeedsRestartDesc': + "Il tuo runtime locale ha una versione diversa da quella dell'app. Un riavvio rapido li riallineerà.", + 'bootCheck.restarting': 'Riavvio…', + 'bootCheck.restartCore': 'Riavvia runtime', + 'bootCheck.cloudNeedsUpdate': 'Il runtime cloud necessita di un aggiornamento', + 'bootCheck.cloudNeedsUpdateDesc': + "Il tuo runtime cloud ha una versione diversa da quella dell'app. Esegui l'updater per riallinearli.", + 'bootCheck.updating': 'Aggiornamento…', + 'bootCheck.updateCloudCore': 'Aggiorna runtime cloud', + 'bootCheck.versionCheckFailed': 'Verifica versione runtime fallita', + 'bootCheck.versionCheckFailedDesc': + 'Il runtime è attivo ma non comunica la sua versione. Potrebbe essere obsoleto. Riavvialo o aggiornalo per continuare.', + 'bootCheck.working': 'Elaborazione…', + 'bootCheck.restartUpdateCore': 'Riavvia / aggiorna runtime', + 'bootCheck.unexpectedError': 'Errore inatteso del controllo di avvio', + 'bootCheck.actionFailed': 'Qualcosa è andato storto. Riprova.', + 'notifications.justNow': 'adesso', + 'notifications.minAgo': '{n}m fa', + 'notifications.hrAgo': '{n}h fa', + 'notifications.dayAgo': '{n}g fa', + 'notifications.category.messages': 'Messaggi', + 'notifications.category.agents': 'Agenti', + 'notifications.category.skills': 'Skill', + 'notifications.category.system': 'Sistema', + 'notifications.category.meetings': 'Riunioni', + 'notifications.category.reminders': 'Promemoria', + 'notifications.category.important': 'Importanti', + 'about.update.status.checking': 'Verifica in corso...', + 'about.update.status.available': 'v{version} disponibile', + 'about.update.status.availableNoVersion': 'Aggiornamento disponibile', + 'about.update.status.downloading': 'Download in corso...', + 'about.update.status.readyToInstall': "v{version} pronta per l'installazione", + 'about.update.status.readyToInstallNoVersion': + 'Una nuova versione è stata scaricata ed è pronta. Riavvia per applicare.', + 'about.update.status.installing': 'Installazione...', + 'about.update.status.restarting': 'Riavvio in corso...', + 'about.update.status.upToDate': "Stai utilizzando l'ultima versione.", + 'about.update.status.error': 'Verifica aggiornamento fallita', + 'about.update.status.default': 'Verifica aggiornamenti', + 'welcome.connectionFailed': 'Connessione fallita: {status} {statusText}', + 'welcome.connectionFailedMsg': 'Connessione fallita: {message}', + 'chat.agentChatDesc': "Apri una sessione di chat diretta con l'agente.", + 'channels.activeRouteValue': '{channel} via {authMode}', + 'privacy.dataKind.messages': 'Messaggi', + 'privacy.dataKind.agents': 'Agenti', + 'privacy.dataKind.skills': 'Skill', + 'privacy.dataKind.system': 'Sistema', + 'privacy.dataKind.meetings': 'Riunioni', + 'privacy.dataKind.reminders': 'Promemoria', + 'privacy.dataKind.important': 'Importante', + 'onboarding.enableLocalAI': 'Abilita AI locale', + 'onboarding.skills.status.available': 'Disponibile', + 'onboarding.skills.status.connected': 'Connesso', + 'onboarding.skills.status.connecting': 'Connessione', + 'onboarding.skills.status.error': 'Errore', + 'onboarding.skills.status.unavailable': 'Non disponibile', + 'composio.statusUnavailable': 'Stato non disponibile', + 'composio.envVarOverrides': 'è impostata, sovrascrive questa impostazione.', + 'memory.day.sun': 'Dom', + 'memory.day.mon': 'Lun', + 'memory.day.tue': 'Mar', + 'memory.day.wed': 'Mer', + 'memory.day.thu': 'Gio', + 'memory.day.fri': 'Ven', + 'memory.day.sat': 'Sab', + 'memory.ingesting': 'Ingestione', + 'memory.ingestionQueued': 'In coda', + 'memory.ingestingTitle': 'Ingestione di {title}', + 'mic.noAudioCaptured': 'Nessun audio catturato', + 'mic.noSpeechDetected': 'Nessun parlato rilevato', + 'mic.failedToStopRecording': 'Impossibile fermare la registrazione: {message}', + 'mic.transcriptionFailed': 'Trascrizione fallita: {message}', + 'reflections.kind.retrospective': 'Retrospettiva', + 'reflections.kind.derivedFact': 'Fatto derivato', + 'reflections.kind.moodInsight': "Insight sull'umore", + 'reflections.kind.relationshipInsight': 'Insight relazionale', + 'graph.tooltip.summary': 'Riassunto', + 'graph.tooltip.contact': 'Contatto', + 'localModel.usage.never': 'Mai', + 'localModel.usage.mediumLoad': 'Carico medio', + 'localModel.usage.lowLoad': 'Carico basso', + 'localModel.usage.idleMode': 'Modalità inattiva', + 'localModel.rebootstrapComplete': 'Re-bootstrap del modello completato.', + 'localModel.modelsVerified': 'Modelli locali verificati.', + 'accounts.addModal.allConnected': 'Tutti connessi', + 'accounts.addModal.title': 'Aggiungi account', + 'accounts.respondQueue.empty': 'Vuota', + 'accounts.respondQueue.hide': 'Nascondi coda di risposta', + 'accounts.respondQueue.loadFailed': 'Impossibile caricare la coda di risposta', + 'accounts.respondQueue.loading': 'Caricamento coda…', + 'accounts.respondQueue.pending': 'In attesa', + 'accounts.respondQueue.show': 'Mostra coda di risposta', + 'accounts.respondQueue.title': 'Coda di risposta', + 'accounts.webviewHost.almostReady': 'Quasi pronto...', + 'accounts.webviewHost.loadTimeout': 'Timeout caricamento webview', + 'accounts.webviewHost.loading': 'Caricamento di {providerName}...', + 'accounts.webviewHost.loadingAccount': 'Caricamento account', + 'accounts.webviewHost.restoringSession': 'Ripristino sessione...', + 'accounts.webviewHost.retryLoading': 'Riprova caricamento', + 'accounts.webviewHost.takingLonger': '{providerName} sta impiegando più tempo del previsto.', + 'accounts.webviewHost.timeoutHint': 'Suggerimento timeout', + 'app.connectionBadge.composio': 'Composio', + 'app.connectionBadge.messaging': 'Messaggistica', + 'app.connectionIndicator.connected': 'Connesso a OpenHuman AI 🚀', + 'app.connectionIndicator.connecting': 'Connessione', + 'app.connectionIndicator.coreOffline': 'Core offline', + 'app.connectionIndicator.disconnected': 'Disconnesso', + 'app.connectionIndicator.offline': 'Offline', + 'app.connectionIndicator.reconnecting': 'Riconnessione…', + 'app.errorFallback.componentStack': 'Stack del componente', + 'app.errorFallback.downloadLatest': "Scarica l'ultima versione", + 'app.errorFallback.heading': 'Intestazione', + 'app.errorFallback.hint': 'Suggerimento', + 'app.errorFallback.reloadApp': 'Ricarica app', + 'app.errorFallback.subheading': 'Sottotitolo', + 'app.errorFallback.tryRecover': 'Prova a ripristinare', + 'app.localAiDownload.installing': 'Installazione...', + 'app.localAiDownload.preparing': 'Preparazione...', + 'app.openhumanLink.accounts.continueWith': 'Continua con accesso {label}', + 'app.openhumanLink.accounts.done': 'Fatto', + 'app.openhumanLink.accounts.intro': 'Introduzione', + 'app.openhumanLink.accounts.webviewNote': 'Nota webview', + 'app.openhumanLink.billing.openDashboard': 'Apri dashboard', + 'app.openhumanLink.billing.stayOnTrial': 'Rimani in prova', + 'app.openhumanLink.billing.trialCredit': 'Credito di prova', + 'app.openhumanLink.billing.trialDesc': 'Descrizione prova', + 'app.openhumanLink.defaultBody': + 'Non ancora pronto nel popup. Apri la pagina completa delle impostazioni quando ti serve.', + 'app.openhumanLink.discord.intro': 'Introduzione', + 'app.openhumanLink.discord.openInvite': 'Apri invito', + 'app.openhumanLink.discord.perk1': 'Vantaggio 1', + 'app.openhumanLink.discord.perk2': 'Vantaggio 2', + 'app.openhumanLink.discord.perk3': 'Vantaggio 3', + 'app.openhumanLink.discord.perk4': 'Vantaggio 4', + 'app.openhumanLink.done': 'Fatto', + 'app.openhumanLink.loadingChannelSetup': 'Caricamento configurazione canale', + 'app.openhumanLink.maybeLater': 'Forse più tardi', + 'app.openhumanLink.notifications.asking': 'Richiesta al tuo OS…', + 'app.openhumanLink.notifications.blocked': 'Bloccato', + 'app.openhumanLink.notifications.blockedStep1': 'Passo 1 bloccato', + 'app.openhumanLink.notifications.blockedStep2': 'Passo 2 bloccato', + 'app.openhumanLink.notifications.blockedStep3': 'Passo 3 bloccato', + 'app.openhumanLink.notifications.intro': 'Introduzione', + 'app.openhumanLink.notifications.promptHint': 'Suggerimento prompt', + 'app.openhumanLink.notifications.retry': 'Riprova notifica di test', + 'app.openhumanLink.notifications.send': 'Invia notifica di test', + 'app.openhumanLink.notifications.sendFailed': 'Impossibile inviare: {error}', + 'app.openhumanLink.notifications.sent': + "Notifica di test inviata. Se non l'hai ricevuta, vai in Impostazioni di Sistema → Notifiche → OpenHuman, attiva Consenti notifiche e imposta lo Stile banner su Persistente.", + 'app.openhumanLink.skipForNow': 'Salta per ora', + 'app.openhumanLink.telegramUnavailable': 'Telegram non disponibile', + 'app.openhumanLink.title.accounts': 'Connetti le tue app', + 'app.openhumanLink.title.billing': 'Fatturazione e crediti', + 'app.openhumanLink.title.discord': 'Unisciti alla community', + 'app.openhumanLink.title.messaging': 'Connetti un canale di chat', + 'app.openhumanLink.title.notifications': 'Consenti notifiche', + 'app.persistRehydration.body': 'Corpo', + 'app.persistRehydration.heading': 'Intestazione', + 'app.persistRehydration.resetCta': 'Ripristino…', + 'app.persistRehydration.resetting': 'Ripristino…', + 'app.routeLoading.initializing': 'Inizializzazione di OpenHuman...', + 'app.update.currentlyOn': '{version}', + 'app.update.errorFallback': "Si è verificato un errore durante l'aggiornamento.", + 'app.update.header.default': 'Aggiornamento', + 'app.update.header.error': 'Aggiornamento fallito', + 'app.update.header.installing': 'Installazione aggiornamento', + 'app.update.header.readyToInstall': "Aggiornamento pronto per l'installazione", + 'app.update.header.restarting': 'Riavvio…', + 'app.update.later': 'Più tardi', + 'app.update.newVersionReady': "Una nuova versione è pronta per l'installazione.", + 'app.update.progress.downloaded': '{amount} scaricati', + 'app.update.progress.installing': 'Installazione della nuova versione…', + 'app.update.progress.restarting': "Riavvio dell'app…", + 'app.update.progress.working': '{percent}%', + 'app.update.restartNote': 'Nota sul riavvio', + 'app.update.restartNow': 'Riavvia ora', + 'app.update.versionReady': "La versione {newVersion} è pronta per l'installazione.", + 'channels.discord.accountLinked': 'Account collegato', + 'channels.discord.connect': 'Connetti', + 'channels.discord.linkTokenExpired': 'Token di collegamento scaduto. Riprova.', + 'channels.discord.linkTokenInstruction': '{token}', + 'channels.discord.linkTokenLabel': 'Etichetta token di collegamento', + 'channels.discord.linkTokenOnce': 'Token di collegamento monouso', + 'channels.discord.picker.allPermissionsOk': + 'Il bot ha tutte le autorizzazioni richieste in questo canale.', + 'channels.discord.picker.botNotInServers': 'Bot non presente nei server', + 'channels.discord.picker.category': 'Categoria', + 'channels.discord.picker.channel': 'Canale', + 'channels.discord.picker.checkingPermissions': 'Verifica autorizzazioni', + 'channels.discord.picker.loadingChannels': 'Caricamento canali...', + 'channels.discord.picker.loadingServers': 'Caricamento server...', + 'channels.discord.picker.missingPermissions': 'Autorizzazioni mancanti', + 'channels.discord.picker.noChannels': 'Nessun canale di testo trovato', + 'channels.discord.picker.noServers': 'Nessun server trovato', + 'channels.discord.picker.selectChannel': 'Seleziona un canale', + 'channels.discord.picker.selectServer': 'Seleziona un server', + 'channels.discord.picker.server': 'Server', + 'channels.discord.picker.serverChannelSelection': 'Selezione server e canale', + 'channels.discord.savedRestartRequired': "Canale salvato. Riavvia l'app per attivarlo.", + 'channels.telegram.connect': 'Connetti', + 'channels.telegram.managedDmConnecting': 'Connessione DM gestiti', + 'channels.telegram.managedDmTimeout': 'Timeout DM gestiti', + 'channels.telegram.reconnect': 'Riconnetti', + 'channels.telegram.savedRestartRequired': "Canale salvato. Riavvia l'app per attivarlo.", + 'channels.web.alwaysAvailable': 'Sempre disponibile', +}; + +export default it3; diff --git a/app/src/lib/i18n/chunks/it-4.ts b/app/src/lib/i18n/chunks/it-4.ts new file mode 100644 index 000000000..164f67f2e --- /dev/null +++ b/app/src/lib/i18n/chunks/it-4.ts @@ -0,0 +1,370 @@ +import type { TranslationMap } from '../types'; + +// Italian (Italiano) chunk 4/5. Translated from chunks/en-4.ts. +const it4: TranslationMap = { + 'chat.unsubscribeApproval.approve': 'Approva e annulla iscrizione', + 'chat.unsubscribeApproval.approved': '✓ Iscrizione annullata con successo.', + 'chat.unsubscribeApproval.denied': '✕ Richiesta rifiutata.', + 'chat.unsubscribeApproval.deny': 'Rifiuta', + 'chat.unsubscribeApproval.processing': 'Elaborazione...', + 'chat.unsubscribeApproval.title': 'Richiesta di annullamento iscrizione', + 'commandPalette.ariaLabel': 'Palette dei comandi', + 'commandPalette.description': 'Descrizione', + 'commandPalette.label': 'Comandi', + 'commandPalette.noResults': 'Nessun risultato', + 'commandPalette.placeholder': 'Digita un comando o cerca…', + 'commandPalette.searchAria': 'Cerca comandi', + 'commandPalette.shortcutHint': 'Premi ? per tutte le scorciatoie', + 'commandPalette.title': 'Palette dei comandi', + 'composio.connect.additionalConfigRequired': 'Configurazione aggiuntiva richiesta', + 'composio.connect.atlassianSubdomainHint': 'acme', + 'composio.connect.atlassianSubdomainLabel': 'Etichetta sottodominio Atlassian', + 'composio.connect.connect': 'Connetti', + 'composio.connect.connectionFailed': 'Connessione fallita (stato: {status}).', + 'composio.connect.disconnectFailed': 'Disconnessione fallita: {msg}', + 'composio.connect.disconnecting': 'Disconnessione…', + 'composio.connect.idleDescription': 'Connetti il tuo', + 'composio.connect.idleDescriptionSuffix': + "account. Apriremo una finestra del browser, autorizzerai l'accesso lì, e l'app rileverà automaticamente la connessione.", + 'composio.connect.isConnected': 'è connesso.', + 'composio.connect.manage': 'Gestisci', + 'composio.connect.needsSubdomain': 'Per connettere', + 'composio.connect.needsSubdomainSuffix': + 'inserisci il tuo sottodominio Atlassian (es. acme per acme.atlassian.net) e riprova.', + 'composio.connect.oauthComplete': 'OAuth da completare…', + 'composio.connect.oauthTimeout': 'Timeout OAuth', + 'composio.connect.permissions': 'Autorizzazioni', + 'composio.connect.permissionsDefault': 'Lettura + scrittura abilitate di default', + 'composio.connect.permissionsNote': 'può esporre', + 'composio.connect.permissionsNoteSuffix': + "Le autorizzazioni proprie dell'agente OpenHuman sono controllate sotto come toggle di lettura, scrittura e admin.", + 'composio.connect.reopenBrowser': 'Riapri browser', + 'composio.connect.requestingUrl': 'Richiesta URL di connessione…', + 'composio.connect.retryConnection': 'Riprova connessione', + 'composio.connect.scopeLoadError': 'Impossibile caricare preferenze degli scope: {msg}', + 'composio.connect.scopeSaveError': 'Impossibile salvare lo scope {key}: {msg}', + 'composio.connect.subdomainInvalid': + 'Inserisci solo il sottodominio breve (es. "acme"), non l\'URL completo. Deve contenere solo lettere, numeri e trattini.', + 'composio.connect.subdomainRequired': 'Inserisci il tuo sottodominio Atlassian per continuare.', + 'composio.connect.wabaIdLabel': 'Etichetta WABA ID', + 'composio.connect.wabaIdRequired': + 'Inserisci il tuo ID WhatsApp Business Account (WABA ID) per continuare.', + 'composio.connect.waitingFor': 'In attesa di', + 'composio.connect.waitingHint': 'Suggerimento di attesa', + 'composio.triggers.heading': 'Trigger', + 'composio.triggers.listenFrom': 'Ascolta eventi da', + 'composio.triggers.loadError': 'Impossibile caricare i trigger', + 'composio.triggers.needsConfiguration': 'Richiede configurazione', + 'composio.triggers.noneAvailable': 'Nessun trigger attualmente disponibile per', + 'conversations.taskKanban.moveLeft': 'Sposta a sinistra', + 'conversations.taskKanban.moveRight': 'Sposta a destra', + 'conversations.taskKanban.title': 'Attività', + 'conversations.toolTimeline.turn': 'turno', + 'conversations.toolTimeline.workerThread': 'thread worker', + 'daemon.serviceBlockingGate.body': 'Corpo', + 'daemon.serviceBlockingGate.downloadHint': 'Suggerimento di download', + 'daemon.serviceBlockingGate.downloadLatest': "Scarica l'ultima versione", + 'daemon.serviceBlockingGate.retryCore': 'Riprova core', + 'daemon.serviceBlockingGate.retryFailed': + "Tentativo fallito. Scarica l'ultima build dell'app e riprova.", + 'daemon.serviceBlockingGate.retrying': 'Nuovo tentativo...', + 'daemon.serviceBlockingGate.title': 'Il core di OpenHuman non è disponibile', + 'home.banners.discordSubtitle': 'Sottotitolo Discord', + 'home.banners.discordTitle': 'Unisciti al nostro Discord', + 'home.banners.earlyBirdDismiss': 'Ignora banner early bird', + 'home.banners.earlyBirdFirstSub': 'primo abbonamento.', + 'home.banners.earlyBirdOn': 'Early bird attivo', + 'home.banners.earlyBirdTitle': 'I primi 1.000 utenti ottengono il 60% di sconto.', + 'home.banners.earlyBirdUseCode': 'Codice early bird', + 'home.banners.getSubscription': 'ottieni un abbonamento', + 'home.banners.promoCreditsBody': 'Corpo crediti promozionali', + 'home.banners.promoCreditsTitle': '{amount}', + 'home.banners.promoCreditsUsage': 'Uso crediti promozionali', + 'intelligence.memoryChunk.detail.chunk': 'Chunk', + 'intelligence.memoryChunk.detail.copyChunkId': 'Copia ID chunk', + 'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024dim', + 'intelligence.memoryChunk.detail.noEmbedding': 'Nessun embedding', + 'intelligence.memoryChunk.letterhead.from': 'da', + 'intelligence.memoryChunk.letterhead.to': 'a', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunk', + 'intelligence.memoryChunk.mentioned.heading': 'm e n z i o n a t i', + 'intelligence.memoryChunk.scoreBars.ariaScore': 'punteggio {name} {pct} percento', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'a {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'scartati', + 'intelligence.memoryChunk.scoreBars.heading': 'p e r c h é t e n u t i', + 'intelligence.memoryChunk.scoreBars.kept': 'tenuti', + 'intelligence.memoryText.entityTypePrefix': 'Tipo di entità', + 'intelligence.screenDebug.active': 'Attivo', + 'intelligence.screenDebug.app': 'App', + 'intelligence.screenDebug.bounds': 'Limiti', + 'intelligence.screenDebug.captureAlt': 'Risultato test di cattura', + 'intelligence.screenDebug.captureFailed': 'Fallito', + 'intelligence.screenDebug.captureSuccess': 'Successo', + 'intelligence.screenDebug.captureTest': 'Test di cattura', + 'intelligence.screenDebug.capturing': 'Cattura in corso', + 'intelligence.screenDebug.frames': 'Frame', + 'intelligence.screenDebug.idle': 'Inattivo', + 'intelligence.screenDebug.lastApp': 'Ultima app', + 'intelligence.screenDebug.mode': 'Modalità', + 'intelligence.screenDebug.permAccessibility': 'Permesso accessibilità', + 'intelligence.screenDebug.permInput': 'Permesso input', + 'intelligence.screenDebug.permScreen': 'Accessibilità', + 'intelligence.screenDebug.permissions': 'Permessi', + 'intelligence.screenDebug.platformNotSupported': 'Piattaforma non supportata', + 'intelligence.screenDebug.recentVisionSummaries': 'Riassunti vision recenti', + 'intelligence.screenDebug.session': 'Sessione', + 'intelligence.screenDebug.size': 'Dimensione', + 'intelligence.screenDebug.status': 'Stato', + 'intelligence.screenDebug.testCapture': 'Test cattura', + 'intelligence.screenDebug.time': 'Ora', + 'intelligence.screenDebug.title': 'Titolo', + 'intelligence.screenDebug.unknown': 'Sconosciuto', + 'intelligence.screenDebug.visionQueue': 'Coda vision', + 'intelligence.screenDebug.visionState': 'Stato vision', + 'intelligence.tasks.activeBoardOne': '1 board attiva tra le conversazioni', + 'intelligence.tasks.activeBoardOther': '{count} board attive tra le conversazioni', + 'intelligence.tasks.empty': "Nessuna board di attività dell'agente", + 'intelligence.tasks.emptyHint': 'Suggerimento vuoto', + 'intelligence.tasks.failedToLoad': 'Caricamento fallito', + 'intelligence.tasks.live': 'live', + 'intelligence.tasks.loadingBoards': 'Caricamento board attività…', + 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'notifications.card.dismiss': 'Ignora notifica', + 'notifications.card.importanceTitle': 'Importanza: {pct}%', + 'notifications.center.empty': 'Nessuna notifica', + 'notifications.center.emptyHint': 'Suggerimento vuoto', + 'notifications.center.filterAll': 'Filtra tutte', + 'notifications.center.markAllRead': 'Segna tutte come lette', + 'notifications.center.title': 'Notifiche', + 'oauth.button.connecting': 'Connessione...', + 'oauth.login.continueWith': 'Continua con', + 'onboarding.contextGathering.buildingDesc': 'Descrizione costruzione', + 'onboarding.contextGathering.buildingProfile': 'Costruzione del tuo profilo...', + 'onboarding.contextGathering.continueToChat': 'Continua alla chat', + 'onboarding.contextGathering.errorDesc': + 'Non siamo riusciti a costruire il tuo profilo completo ora, ma va bene — puoi continuare e il tuo profilo si svilupperà nel tempo.', + 'onboarding.contextGathering.title': 'Raccolta del contesto', + 'openhuman.team_list_teams': 'Elenco team', + 'overlay.ariaAttention': 'Messaggio di attenzione', + 'overlay.ariaOrb': 'Overlay OpenHuman', + 'overlay.ariaVoiceActive': 'Input vocale attivo', + 'overlay.orbTitle': 'Trascina per spostare · Doppio clic per ripristinare la posizione', + 'pages.settings.account.connections': 'Connessioni', + 'pages.settings.account.connectionsDesc': 'Descrizione connessioni', + 'pages.settings.account.privacy': 'Privacy', + 'pages.settings.account.privacyDesc': 'Descrizione privacy', + 'pages.settings.account.recoveryPhrase': 'Frase di recupero', + 'pages.settings.account.recoveryPhraseDesc': 'Descrizione frase di recupero', + 'pages.settings.account.team': 'Team', + 'pages.settings.account.teamDesc': 'Descrizione team', + 'pages.settings.accountSection.description': + 'Frase di recupero, team, connessioni e impostazioni privacy.', + 'pages.settings.accountSection.title': 'Account', + 'pages.settings.ai.llm': 'LLM', + 'pages.settings.ai.llmDesc': 'Descrizione LLM', + 'pages.settings.ai.voice': 'Voce', + 'pages.settings.ai.voiceDesc': 'Descrizione voce', + 'pages.settings.aiSection.description': + 'Provider di modelli linguistici, Ollama locale e voce (STT / TTS).', + 'pages.settings.aiSection.title': 'AI', + 'pages.settings.features.messagingChannels': 'Canali di messaggistica', + 'pages.settings.features.messagingChannelsDesc': 'Descrizione canali di messaggistica', + 'pages.settings.features.notifications': 'Notifiche', + 'pages.settings.features.notificationsDesc': 'Descrizione notifiche', + 'pages.settings.features.screenAwareness': 'Consapevolezza schermo', + 'pages.settings.features.screenAwarenessDesc': 'Descrizione consapevolezza schermo', + 'pages.settings.features.tools': 'Strumenti', + 'pages.settings.features.toolsDesc': 'Descrizione strumenti', + 'pages.settings.featuresSection.description': + 'Consapevolezza schermo, messaggistica e strumenti.', + 'pages.settings.featuresSection.title': 'Funzionalità', + 'privacy.dataKind.credentials': 'Credenziali', + 'privacy.dataKind.derived': 'Derivati', + 'privacy.dataKind.diagnostics': 'Diagnostica', + 'privacy.dataKind.metadata': 'Metadati', + 'privacy.dataKind.raw': 'Grezzi', + 'privacy.whatLeaves.link.label': 'Cosa esce dal mio computer?', + 'rewards.community.achievementsUnlocked': '{unlocked} di {total} obiettivi sbloccati', + 'rewards.community.connectDiscord': 'Connetti Discord', + 'rewards.community.cumulativeTokens': 'Token cumulativi', + 'rewards.community.currentStreak': 'Streak attuale', + 'rewards.community.discordLinkedNotInGuild': 'Discord collegato ma non nella gilda', + 'rewards.community.discordMember': 'Sei entrato nel server', + 'rewards.community.discordNotLinked': 'Discord non collegato', + 'rewards.community.discordServer': 'Server Discord', + 'rewards.community.discordStatusUnavailable': 'Stato Discord non disponibile', + 'rewards.community.discordWaiting': 'Attesa Discord', + 'rewards.community.heroSubtitle': 'Sottotitolo hero', + 'rewards.community.heroTitle': 'Titolo hero', + 'rewards.community.joinDiscord': 'Unisciti a Discord', + 'rewards.community.loadingRewards': 'Caricamento premi…', + 'rewards.community.locked': 'Bloccato', + 'rewards.community.retrying': 'Nuovo tentativo…', + 'rewards.community.rolesAndRewards': 'Ruoli e premi', + 'rewards.community.streakDays': '{n}', + 'rewards.community.syncPending': 'Sincronizzazione premi in attesa', + 'rewards.community.syncPendingDesc': 'Descrizione sincronizzazione in attesa', + 'rewards.community.syncUnavailable': 'Sincronizzazione non disponibile', + 'rewards.community.tryAgain': 'Nuovo tentativo…', + 'rewards.community.unknown': 'Sconosciuto', + 'rewards.community.unlocked': 'Sbloccato', + 'rewards.community.yourProgress': 'Il tuo progresso', + 'rewards.coupon.colCode': 'Codice', + 'rewards.coupon.colRedeemed': 'Riscattato', + 'rewards.coupon.colReward': 'Premio', + 'rewards.coupon.colStatus': 'Stato', + 'rewards.coupon.loadingHistory': 'Caricamento cronologia premi…', + 'rewards.coupon.noCodes': 'Nessun codice premio riscattato.', + 'rewards.coupon.pending': 'In attesa', + 'rewards.coupon.placeholder': 'Codice coupon', + 'rewards.coupon.promoCredits': 'Crediti promozionali', + 'rewards.coupon.recentRedemptions': 'Riscatti recenti', + 'rewards.coupon.redeemAccepted': + "{code} accettato. {amount} verrà sbloccato dopo il completamento dell'azione richiesta.", + 'rewards.coupon.redeemButton': 'Riscatta codice', + 'rewards.coupon.redeemSuccess': '{code} riscattato. {amount} è stato aggiunto ai tuoi crediti.', + 'rewards.coupon.redeemedCodes': 'Codici riscattati', + 'rewards.coupon.redeeming': 'Riscatto in corso...', + 'rewards.coupon.statusApplied': 'Applicato', + 'rewards.coupon.statusPendingAction': 'Azione in attesa', + 'rewards.coupon.statusRedeemed': 'Riscattato', + 'rewards.coupon.subtitle': 'Sottotitolo', + 'rewards.coupon.title': 'Riscatta un codice coupon', + 'rewards.referralSection.activity': 'Attività referral', + 'rewards.referralSection.apply': 'Applicazione…', + 'rewards.referralSection.applying': 'Applicazione…', + 'rewards.referralSection.colReferredUser': 'Utente referenziato', + 'rewards.referralSection.colReward': 'Premio', + 'rewards.referralSection.colStatus': 'Stato', + 'rewards.referralSection.colUpdated': 'Aggiornato', + 'rewards.referralSection.completed': 'Completato', + 'rewards.referralSection.copyCode': 'Copia codice', + 'rewards.referralSection.copyFailed': 'Copia fallita', + 'rewards.referralSection.haveCode': 'Hai un codice referral?', + 'rewards.referralSection.haveCodeDesc': 'Descrizione codice', + 'rewards.referralSection.linked': 'Collegato', + 'rewards.referralSection.linkedCode': '(codice {code})', + 'rewards.referralSection.loading': 'Caricamento programma referral…', + 'rewards.referralSection.noReferrals': 'Nessun referral', + 'rewards.referralSection.pendingReferrals': 'Referral in attesa', + 'rewards.referralSection.placeholder': 'Codice referral', + 'rewards.referralSection.share': 'Condividi', + 'rewards.referralSection.statusCompleted': 'Stato completato', + 'rewards.referralSection.statusExpired': 'Stato scaduto', + 'rewards.referralSection.statusJoined': 'Stato iscritto', + 'rewards.referralSection.subtitle': 'Sottotitolo', + 'rewards.referralSection.title': 'Invita amici, guadagna crediti', + 'rewards.referralSection.totalEarned': 'Totale guadagnato', + 'rewards.referralSection.yourCode': 'Il tuo codice', + 'settings.ai.addCloudProvider': 'Aggiungi provider cloud', + 'settings.ai.addProvider': 'Salvataggio…', + 'settings.ai.apiKeyFieldLabel': 'Etichetta campo chiave API', + 'settings.ai.apiKeyRequired': 'Incolla la tua chiave API per continuare.', + 'settings.ai.apiKeyStoredEncrypted': 'Chiave API memorizzata crittografata', + 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', + 'settings.ai.clearStoredKey': 'Cancella chiave memorizzata', + 'settings.ai.connectProvider': 'Connetti provider', + 'settings.ai.customRouting': 'Instradamento personalizzato', + 'settings.ai.defaultResolvesTo': 'OpenHuman', + 'settings.ai.discard': 'Scarta', + 'settings.ai.editProvider': 'Modifica provider', + 'settings.ai.llmProviders': 'Provider LLM', + 'settings.ai.llmProvidersDesc': 'Descrizione provider LLM', + 'settings.ai.localOllama': 'Locale (Ollama)', + 'settings.ai.modelLabel': 'Modello', + 'settings.ai.noCustomProviders': 'Nessun provider personalizzato', + 'settings.ai.providerLabel': 'Provider', + 'settings.ai.routing': 'Instradamento', + 'settings.ai.routingCustom': 'Instradamento personalizzato', + 'settings.ai.routingDefault': 'Predefinito', + 'settings.ai.routingDesc': 'Descrizione instradamento', + 'settings.ai.saveChanges': 'Salvataggio…', + 'settings.ai.saving': 'Salvataggio…', + 'settings.ai.unsavedChange': 'modifica non salvata', + 'settings.ai.unsavedChanges': 'modifiche non salvate', + 'settings.ai.workloadGroupBackground': 'Gruppo carico di lavoro background', + 'settings.ai.workloadGroupChat': 'Gruppo carico di lavoro chat', + 'settings.autocomplete.appFilter.acceptSuggestion': 'Accetta suggerimento', + 'settings.autocomplete.appFilter.contextOverride': 'Override contesto (opzionale)', + 'settings.autocomplete.appFilter.debugFocus': 'Focus debug', + 'settings.autocomplete.appFilter.getSuggestion': 'Ottieni suggerimento', + 'settings.autocomplete.appFilter.liveLogs': 'Log live', + 'settings.autocomplete.appFilter.noLogs': 'Nessun log', + 'settings.autocomplete.appFilter.refreshStatus': 'Aggiornamento…', + 'settings.autocomplete.appFilter.refreshing': 'Aggiornamento…', + 'settings.autocomplete.appFilter.runtime': 'Runtime', + 'settings.autocomplete.appFilter.test': 'Test', + 'settings.autocomplete.completionStyle.acceptedCompletion': + '{count} completamento accettato memorizzato — usato per personalizzare i futuri suggerimenti.', + 'settings.autocomplete.completionStyle.acceptedCompletions': + '{count} completamenti accettati memorizzati — usati per personalizzare i futuri suggerimenti.', + 'settings.autocomplete.completionStyle.clearHistory': 'Cancellazione…', + 'settings.autocomplete.completionStyle.clearing': 'Cancellazione…', + 'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)', + 'settings.autocomplete.completionStyle.enabled': 'Abilitato', + 'settings.autocomplete.completionStyle.maxChars': 'Caratteri max', + 'settings.autocomplete.completionStyle.noHistory': + 'Nessun completamento accettato. Accetta i suggerimenti con Tab per iniziare a personalizzare.', + 'settings.autocomplete.completionStyle.overlayTtl': 'TTL overlay (ms)', + 'settings.autocomplete.completionStyle.personalizationHistory': 'Cronologia personalizzazione', + 'settings.autocomplete.completionStyle.styleExamples': 'Esempi di stile (uno per riga)', + 'settings.autocomplete.completionStyle.styleInstructions': 'Istruzioni di stile', + 'settings.billing.autoRecharge.addAmount': 'Aggiungi questo importo', + 'settings.billing.autoRecharge.addCard': 'Aggiungi carta', + 'settings.billing.autoRecharge.amountHint': 'Suggerimento importo', + 'settings.billing.autoRecharge.defaultCard': 'Carta predefinita', + 'settings.billing.autoRecharge.lastRechargeFailed': 'Ultima ricarica fallita', + 'settings.billing.autoRecharge.lastRecharged': 'Ultima ricarica', + 'settings.billing.autoRecharge.noCards': 'Nessuna carta', + 'settings.billing.autoRecharge.paymentMethods': 'Metodi di pagamento', + 'settings.billing.autoRecharge.rechargeInProgress': 'Ricarica in corso', + 'settings.billing.autoRecharge.rechargeWhen': 'Ricarica quando il saldo scende sotto', + 'settings.billing.autoRecharge.saveSettings': 'Salvataggio…', + 'settings.billing.autoRecharge.saving': 'Salvataggio…', + 'settings.billing.autoRecharge.setDefault': 'Imposta come predefinita', + 'settings.billing.autoRecharge.subtitle': 'Sottotitolo', + 'settings.billing.autoRecharge.title': 'Abilita ricarica automatica', + 'settings.billing.autoRecharge.toggleAriaLabel': 'Attiva/disattiva ricarica automatica', + 'settings.billing.autoRecharge.weeklyLimit': 'Limite di spesa settimanale', + 'settings.billing.history.desc': 'Descrizione', + 'settings.billing.history.empty': 'Vuoto', + 'settings.billing.history.openPortal': 'Apri portale', + 'settings.billing.history.posted': 'Registrato', + 'settings.billing.history.title': 'Titolo', + 'settings.billing.inferenceBudget.cycleEnds': 'Fine ciclo', + 'settings.billing.inferenceBudget.exhausted': 'Esaurito', + 'settings.billing.inferenceBudget.loadError': 'Errore di caricamento', + 'settings.billing.inferenceBudget.noBudgetDesc': 'Nessuna descrizione budget', + 'settings.billing.inferenceBudget.noRecurringBudget': 'Nessun budget ricorrente', + 'settings.billing.inferenceBudget.remaining': 'Rimanente', + 'settings.billing.inferenceBudget.tenHourCap': 'Limite di 10 ore', + 'settings.billing.inferenceBudget.title': 'Titolo', + 'settings.billing.payAsYouGo.available': 'Disponibile', + 'settings.billing.payAsYouGo.chargeCustomAmount': 'Apertura…', + 'settings.billing.payAsYouGo.chooseTopUpDesc': 'Descrizione scelta ricarica', + 'settings.billing.payAsYouGo.chooseTopUpTitle': 'Titolo scelta ricarica', + 'settings.billing.payAsYouGo.creditBalanceDesc': 'Descrizione saldo crediti', + 'settings.billing.payAsYouGo.creditBalanceTitle': 'Titolo saldo crediti', + 'settings.billing.payAsYouGo.customAmount': 'Importo personalizzato', + 'settings.billing.payAsYouGo.enterAmount': 'Inserisci importo', + 'settings.billing.payAsYouGo.opening': 'Apertura', + 'settings.billing.payAsYouGo.promotionalCredits': 'Crediti promozionali', + 'settings.billing.payAsYouGo.topUpBalance': 'Saldo ricarica', + 'settings.billing.payAsYouGo.topUpCredits': 'Ricarica crediti', + 'settings.billing.payAsYouGo.unableToLoad': 'Impossibile caricare il saldo.', + 'settings.billing.subscription.annual': 'Annuale', + 'settings.billing.subscription.billedAnnually': 'Fatturato annualmente', + 'settings.billing.subscription.chooseSubtitle': 'Sottotitolo scelta', + 'settings.billing.subscription.chooseTitle': 'Titolo scelta', + 'settings.billing.subscription.cryptoDesc': 'Descrizione crypto', + 'settings.billing.subscription.cryptoQuestion': 'Domanda crypto', + 'settings.billing.subscription.current': 'Attuale', + 'settings.billing.subscription.currentPlan': 'Piano attuale', + 'settings.billing.subscription.monthly': 'Mensile', + 'settings.billing.subscription.paymentConfirmed': 'Pagamento confermato', + 'settings.billing.subscription.perMonth': 'Al mese', + 'settings.billing.subscription.popular': 'Popolare', +}; + +export default it4; diff --git a/app/src/lib/i18n/chunks/it-5.ts b/app/src/lib/i18n/chunks/it-5.ts new file mode 100644 index 000000000..27c05a91f --- /dev/null +++ b/app/src/lib/i18n/chunks/it-5.ts @@ -0,0 +1,407 @@ +import type { TranslationMap } from '../types'; + +// Italian (Italiano) chunk 5/5. Translated from chunks/en-5.ts. +const it5: TranslationMap = { + 'settings.billing.subscription.save': '{pct}', + 'settings.billing.subscription.upgrade': 'Aggiorna', + 'settings.billing.subscription.waiting': 'In attesa', + 'settings.billing.subscription.waitingPayment': 'In attesa di pagamento', + 'settings.composio.apiKeyDesc': + 'Una chiave API Composio è attualmente memorizzata su questo dispositivo.', + 'settings.composio.apiKeyLabel': 'Chiave API Composio', + 'settings.composio.apiKeyStored': 'Chiave API memorizzata', + 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', + 'settings.composio.clearedToBackend': 'Passato alla modalità Backend', + 'settings.composio.confirmItem1': 'Un account su app.composio.dev con una chiave API', + 'settings.composio.confirmItem2': + 'Per ricollegare ogni integrazione tramite il tuo account Composio personale', + 'settings.composio.confirmItem3': + 'Nota: i trigger Composio (webhook in tempo reale) non funzionano ancora in modalità Diretta — solo le chiamate sincrone agli strumenti', + 'settings.composio.confirmNeedItems': 'Ti serviranno:', + 'settings.composio.confirmSwitch': 'Ho capito, passa a Diretta', + 'settings.composio.confirmTitle': '⚠️ Passaggio alla modalità Diretta', + 'settings.composio.confirmWarning': + 'Le tue integrazioni esistenti (Gmail, Slack, GitHub, ecc. collegate tramite OpenHuman) non saranno visibili — risiedono nel tenant Composio gestito da OpenHuman.', + 'settings.composio.intro': + 'Composio integra oltre 250 app esterne come strumenti che il tuo agente può chiamare. Scegli come instradare queste chiamate.', + 'settings.composio.modeDirect': 'Diretta (usa la tua chiave API)', + 'settings.composio.modeDirectDesc': + "Le chiamate vanno direttamente a backend.composio.dev. Sovrana / offline-friendly. L'esecuzione degli strumenti funziona in modo sincrono; i webhook dei trigger in tempo reale non sono ancora instradati in modalità diretta (issue di follow-up).", + 'settings.composio.modeManaged': 'Gestita (OpenHuman lo gestisce per te)', + 'settings.composio.modeManagedDesc': + "OpenHuman fa da proxy per le chiamate degli strumenti tramite il nostro backend (consigliato). L'autenticazione è mediata; non incolli mai una chiave API Composio. I webhook sono completamente instradati.", + 'settings.composio.routingMode': 'Modalità di instradamento', + 'settings.composio.saveErrorNoKey': + 'Salvataggio fallito. La modalità Diretta richiede una chiave API non vuota.', + 'settings.composio.saving': 'Salvataggio…', + 'settings.composio.switching': 'Passaggio…', + 'settings.cron.jobs.desc': 'Descrizione', + 'settings.cron.jobs.empty': 'Nessun cron job core trovato.', + 'settings.cron.jobs.lastStatus': 'Ultimo stato', + 'settings.cron.jobs.loading': 'Caricamento cron job...', + 'settings.cron.jobs.loadingRuns': 'Caricamento esecuzioni', + 'settings.cron.jobs.nextRun': 'Prossima esecuzione', + 'settings.cron.jobs.pause': 'Pausa', + 'settings.cron.jobs.paused': 'In pausa', + 'settings.cron.jobs.recentRuns': 'Esecuzioni recenti', + 'settings.cron.jobs.removing': 'Rimozione', + 'settings.cron.jobs.resume': 'Riprendi', + 'settings.cron.jobs.runningNow': 'In esecuzione ora', + 'settings.cron.jobs.saving': 'Salvataggio…', + 'settings.cron.jobs.schedule': 'Pianificazione', + 'settings.cron.jobs.title': 'Cron Job core', + 'settings.cron.jobs.viewRuns': 'Visualizza esecuzioni', + 'settings.localModel.deviceCapability.active': 'Attivo', + 'settings.localModel.deviceCapability.appliedTier': 'Tier applicato', + 'settings.localModel.deviceCapability.applying': 'Applicazione', + 'settings.localModel.deviceCapability.cores': '{count}', + 'settings.localModel.deviceCapability.couldNotLoadPresets': 'Impossibile caricare i preset', + 'settings.localModel.deviceCapability.cpu': 'CPU', + 'settings.localModel.deviceCapability.customModelIds': 'ID modello personalizzati', + 'settings.localModel.deviceCapability.detected': 'Rilevato', + 'settings.localModel.deviceCapability.disabled': 'Disabilitato', + 'settings.localModel.deviceCapability.disabledDesc': 'Descrizione disabilitato', + 'settings.localModel.deviceCapability.downloadingModels': '(download modelli)', + 'settings.localModel.deviceCapability.downloadingSetupDesc': + "Download dell'installer OllamaSetup (~2 GB) e scompattazione. Al primo avvio può richiedere un minuto.", + 'settings.localModel.deviceCapability.failedToApplyPreset': 'Impossibile applicare il preset', + 'settings.localModel.deviceCapability.gpu': 'GPU', + 'settings.localModel.deviceCapability.installFailed': 'Installazione Ollama fallita', + 'settings.localModel.deviceCapability.installFailedDesc': + "L'installer è uscito prima che Ollama fosse utilizzabile. Clicca riprova oppure installa manualmente da ollama.com.", + 'settings.localModel.deviceCapability.installFirst': 'Esegui prima Ollama.', + 'settings.localModel.deviceCapability.installFirstDesc': + 'I tier locali dipendono da un endpoint Ollama gestito esternamente. Avvialo tu, scarica i modelli che vuoi e continua a usare "Disabilitato (fallback cloud)" finché il runtime non è raggiungibile.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'Esegui prima Ollama per usare questo tier', + 'settings.localModel.deviceCapability.installingOllama': 'Installazione Ollama', + 'settings.localModel.deviceCapability.loadingDeviceInfo': 'Caricamento info dispositivo', + 'settings.localModel.deviceCapability.localAiDisabled': + 'AI locale disabilitata — uso il fallback cloud.', + 'settings.localModel.deviceCapability.modelTier': 'Tier del modello', + 'settings.localModel.deviceCapability.needsOllama': 'Richiede Ollama', + 'settings.localModel.deviceCapability.notDetected': 'Non rilevato', + 'settings.localModel.deviceCapability.ram': 'RAM', + 'settings.localModel.deviceCapability.recommended': 'Consigliato', + 'settings.localModel.deviceCapability.retryInstall': 'Nuovo tentativo…', + 'settings.localModel.deviceCapability.retrying': 'Nuovo tentativo…', + 'settings.localModel.deviceCapability.starting': 'Avvio…', + 'settings.localModel.download.audioPathPlaceholder': 'Percorso assoluto al file audio', + 'settings.localModel.download.capabilityAssets': 'Asset di capacità', + 'settings.localModel.download.downloading': 'Download in corso...', + 'settings.localModel.download.embeddingPlaceholder': 'Una stringa di input per riga...', + 'settings.localModel.download.noThinkMode': 'Modalità no-think', + 'settings.localModel.download.promptPlaceholder': + 'Scrivi un prompt qualsiasi ed eseguilo sul modello locale...', + 'settings.localModel.download.quantizationPref': 'Preferenza quantizzazione', + 'settings.localModel.download.runEmbeddingTest': 'Esecuzione...', + 'settings.localModel.download.runPromptTest': 'Esegui test prompt', + 'settings.localModel.download.runSummaryTest': 'Esegui test riassunto', + 'settings.localModel.download.runTranscriptionTest': 'Esecuzione...', + 'settings.localModel.download.runTtsTest': 'Esecuzione...', + 'settings.localModel.download.runVisionTest': 'Esecuzione...', + 'settings.localModel.download.running': 'Esecuzione...', + 'settings.localModel.download.runningPrompt': 'Esecuzione prompt', + 'settings.localModel.download.summarizePlaceholder': + 'Incolla il testo da riassumere con il modello locale...', + 'settings.localModel.download.testCustomPrompt': 'Test prompt personalizzato', + 'settings.localModel.download.testEmbeddings': 'Test embedding', + 'settings.localModel.download.testSummarization': 'Test riassunto', + 'settings.localModel.download.testVisionPrompt': 'Test prompt vision', + 'settings.localModel.download.testVoiceInput': 'Test input vocale (STT)', + 'settings.localModel.download.testVoiceOutput': 'Test output vocale (TTS)', + 'settings.localModel.download.ttsOutputPlaceholder': 'Percorso WAV di output opzionale', + 'settings.localModel.download.ttsPlaceholder': 'Inserisci il testo da sintetizzare...', + 'settings.localModel.download.visionImagePlaceholder': + 'Un riferimento immagine per riga (data URI, URL o marcatore di percorso locale)', + 'settings.localModel.download.visionPromptPlaceholder': + 'Inserisci un prompt per il modello vision...', + 'settings.localModel.status.allChecksPassed': 'Tutti i controlli superati', + 'settings.localModel.status.artifact': 'Artefatto', + 'settings.localModel.status.backend': 'Backend', + 'settings.localModel.status.binary': 'Binario', + 'settings.localModel.status.bootstrapResume': 'Bootstrap / ripresa', + 'settings.localModel.status.checking': 'Verifica in corso...', + 'settings.localModel.status.checkingOllama': 'Verifica Ollama', + 'settings.localModel.status.customLocation': 'Posizione personalizzata', + 'settings.localModel.status.customLocationDesc': 'Descrizione posizione personalizzata', + 'settings.localModel.status.diagnosticsHint': + 'Clicca "Esegui diagnostica" per verificare che Ollama sia in esecuzione e i modelli installati.', + 'settings.localModel.status.downloadingUnknown': 'Download (dimensione sconosciuta)', + 'settings.localModel.status.eta': 'ETA', + 'settings.localModel.status.expectedModels': 'Modelli attesi', + 'settings.localModel.status.forceRebootstrap': 'Forza re-bootstrap', + 'settings.localModel.status.generationTps': 'TPS di generazione', + 'settings.localModel.status.hideErrorDetails': 'Nascondi dettagli errore', + 'settings.localModel.status.installManually': 'Installa manualmente', + 'settings.localModel.status.installManuallyFrom': 'Installa manualmente da', + 'settings.localModel.status.installOllama': 'Avvio…', + 'settings.localModel.status.installedModels': 'Modelli installati', + 'settings.localModel.status.installing': 'Installazione...', + 'settings.localModel.status.installingOllama': 'Installazione runtime Ollama...', + 'settings.localModel.status.issues': 'Problemi', + 'settings.localModel.status.issuesFound': '{count} problema/i trovato/i', + 'settings.localModel.status.lastLatency': 'Ultima latenza', + 'settings.localModel.status.model': 'Modello', + 'settings.localModel.status.notFound': 'Non trovato', + 'settings.localModel.status.notRunning': 'Non in esecuzione', + 'settings.localModel.status.ollamaBinaryPath': 'Percorso binario Ollama', + 'settings.localModel.status.ollamaDiagnostics': 'Diagnostica Ollama', + 'settings.localModel.status.ollamaNotInstalled': 'Runtime Ollama non disponibile', + 'settings.localModel.status.ollamaNotInstalledDesc': + "OpenHuman ora tratta Ollama come un runtime di inferenza esterno. Avvia il tuo server Ollama, scarica i modelli che vuoi e punta l'instradamento dei carichi di lavoro su di esso.", + 'settings.localModel.status.progress': 'Progresso', + 'settings.localModel.status.provider': 'Provider', + 'settings.localModel.status.retryBootstrap': 'Riprova bootstrap', + 'settings.localModel.status.runDiagnostics': 'Verifica in corso...', + 'settings.localModel.status.running': 'In esecuzione', + 'settings.localModel.status.runningExternalProcess': 'In esecuzione tramite processo esterno', + 'settings.localModel.status.runtimeStatus': 'Stato runtime', + 'settings.localModel.status.server': 'Server', + 'settings.localModel.status.setPath': 'Impostazione...', + 'settings.localModel.status.setting': 'Impostazione...', + 'settings.localModel.status.showErrorDetails': 'Mostra dettagli errore', + 'settings.localModel.status.showInstallErrorDetails': 'Mostra dettagli errore di installazione', + 'settings.localModel.status.suggestedFixes': 'Soluzioni suggerite', + 'settings.localModel.status.thenSetPath': 'Poi imposta il percorso', + 'settings.localModel.status.triggering': 'Attivazione...', + 'settings.localModel.status.unavailable': 'Non disponibile', + 'settings.localModel.status.working': 'Elaborazione...', + 'settings.mascot.active': 'Attivo', + 'settings.mascot.characterDesc': 'Descrizione personaggio', + 'settings.mascot.characterHeading': 'Intestazione personaggio', + 'settings.mascot.colorDesc': 'Descrizione colore', + 'settings.mascot.colorHeading': 'Intestazione colore', + 'settings.mascot.loadingLibrary': 'Caricamento libreria OpenHuman…', + 'settings.mascot.localDefault': 'OpenHuman locale (predefinito)', + 'settings.mascot.noCharacters': 'Nessun personaggio OpenHuman disponibile', + 'settings.mascot.noColorVariants': 'Nessuna variante di colore', + 'settings.memoryWindow.balanced.badge': 'Consigliato', + 'settings.memoryWindow.balanced.hint': + 'Predefinito sensato — buona continuità senza bruciare token extra a ogni esecuzione.', + 'settings.memoryWindow.balanced.label': 'Bilanciato', + 'settings.memoryWindow.description': + "Quanto contesto ricordato OpenHuman inietta in ogni nuova esecuzione dell'agente. Finestre più grandi fanno sentire l'agente più consapevole delle conversazioni passate ma usano più token — e costano di più — a ogni esecuzione.", + 'settings.memoryWindow.extended.badge': 'Più contesto', + 'settings.memoryWindow.extended.hint': + 'Più memoria a lungo termine iniettata in ogni esecuzione. Costo token più alto per turno.', + 'settings.memoryWindow.extended.label': 'Esteso', + 'settings.memoryWindow.maximum.badge': 'Costo più alto', + 'settings.memoryWindow.maximum.hint': + 'La più grande finestra sicura. Migliore continuità, bolletta token significativamente più alta a ogni esecuzione.', + 'settings.memoryWindow.maximum.label': 'Massimo', + 'settings.memoryWindow.minimal.badge': 'Più economico', + 'settings.memoryWindow.minimal.hint': + 'Finestra di memoria minima. Più economico, più veloce, minore continuità tra esecuzioni.', + 'settings.memoryWindow.minimal.label': 'Minimo', + 'settings.memoryWindow.title': 'Finestra di memoria a lungo termine', + 'settings.screenIntel.permissions.accessibility': 'Accessibilità', + 'settings.screenIntel.permissions.grantHint': 'Suggerimento concessione', + 'settings.screenIntel.permissions.inputMonitoring': 'Monitoraggio input', + 'settings.screenIntel.permissions.macosAppliesPrivacy': 'macOS applica privacy', + 'settings.screenIntel.permissions.openInputMonitoring': 'Richiesta…', + 'settings.screenIntel.permissions.refreshStatus': 'Aggiornamento…', + 'settings.screenIntel.permissions.refreshing': 'Aggiornamento…', + 'settings.screenIntel.permissions.requestAccessibility': 'Richiesta…', + 'settings.screenIntel.permissions.requestScreenRecording': 'Richiesta…', + 'settings.screenIntel.permissions.requesting': 'Richiesta…', + 'settings.screenIntel.permissions.restartRefresh': 'Riavvio core…', + 'settings.screenIntel.permissions.restartingCore': 'Riavvio core…', + 'settings.screenIntel.permissions.screenRecording': 'Registrazione schermo', + 'settings.screenIntel.permissions.title': 'Permessi', + 'skills.card.moreActions': 'Altre azioni', + 'skills.create.allowedTools': 'Strumenti consentiti', + 'skills.create.author': 'Autore', + 'skills.create.authorPlaceholder': 'Il tuo nome', + 'skills.create.commaSeparated': '(separati da virgole)', + 'skills.create.createBtn': 'Crea skill', + 'skills.create.createError': 'Impossibile creare la skill', + 'skills.create.creating': 'Creazione…', + 'skills.create.description': 'Descrizione', + 'skills.create.descriptionPlaceholder': 'Cosa fa questa skill?', + 'skills.create.license': 'Licenza', + 'skills.create.name': 'Nome', + 'skills.create.namePlaceholder': 'es. Trade Journal', + 'skills.create.scope': 'Ambito', + 'skills.create.scopeProjectHint': '/.openhuman/skills/', + 'skills.create.scopeUserHint': + 'Scritto in ~/.openhuman/skills//SKILL.md — disponibile in tutti i workspace.', + 'skills.create.slugLabel': 'Etichetta slug', + 'skills.create.subtitle': 'SKILL.md', + 'skills.create.tags': 'Tag', + 'skills.create.title': 'Nuova skill', + 'skills.detail.allowedTools': 'Strumenti consentiti', + 'skills.detail.author': 'Autore', + 'skills.detail.bundledResources': 'Risorse incluse', + 'skills.detail.closeAriaLabel': 'Chiudi dettagli skill', + 'skills.detail.location': 'Posizione', + 'skills.detail.noBundledResources': 'Nessuna risorsa inclusa.', + 'skills.detail.tags': 'Tag', + 'skills.detail.warnings': 'Avvertenze', + 'skills.install.fetchLog': 'Log di fetch', + 'skills.install.installBtn': 'Installazione…', + 'skills.install.installComplete': 'Installazione completata', + 'skills.install.installing': 'Installazione…', + 'skills.install.parseWarnings': 'Avvertenze di parsing', + 'skills.install.rawError': 'Errore grezzo', + 'skills.install.timeoutHint': '(secondi, opzionale)', + 'skills.install.timeoutLabel': 'Etichetta timeout', + 'skills.install.title': 'Installa skill da URL', + 'skills.install.urlLabel': 'URL skill', + 'skills.meetingBots.bannerDesc': 'Descrizione banner', + 'skills.meetingBots.bannerTitle': 'Titolo banner', + 'skills.meetingBots.busyTitle': 'OpenHuman è occupato', + 'skills.meetingBots.comingSoon': 'In arrivo', + 'skills.meetingBots.couldNotStartTitle': 'Impossibile avviare OpenHuman', + 'skills.meetingBots.displayName': 'Nome visualizzato', + 'skills.meetingBots.failedToStart': 'Avvio di OpenHuman fallito.', + 'skills.meetingBots.joiningMessage': 'Apparirà come partecipante tra qualche secondo.', + 'skills.meetingBots.joiningTitle': 'OpenHuman si sta unendo alla riunione', + 'skills.meetingBots.meetingLink': 'Link della riunione', + 'skills.meetingBots.modalAriaLabel': 'Invia OpenHuman a una riunione', + 'skills.meetingBots.modalDesc': 'Descrizione modale', + 'skills.meetingBots.modalTitle': 'Invia OpenHuman a una riunione', + 'skills.meetingBots.newBadge': 'Nuovo', + 'skills.meetingBots.sendTo': 'Invia a', + 'skills.meetingBots.starting': 'Avvio…', + 'skills.resource.preview.closeAriaLabel': 'Chiudi anteprima', + 'skills.resource.preview.failed': 'Anteprima fallita', + 'skills.resource.preview.loading': 'Caricamento anteprima…', + 'skills.resource.tree.empty': 'Nessuna risorsa inclusa.', + 'skills.search.placeholder': 'Placeholder', + 'skills.setup.autocomplete.acceptKey': 'Tasto di accettazione', + 'skills.setup.autocomplete.activeDesc': 'Descrizione attivo', + 'skills.setup.autocomplete.activeTitle': 'Autocompletamento attivo', + 'skills.setup.autocomplete.customizeSettings': 'Personalizza impostazioni', + 'skills.setup.autocomplete.debounce': 'Debounce', + 'skills.setup.autocomplete.description': 'Descrizione', + 'skills.setup.autocomplete.enableBtn': 'Abilitazione...', + 'skills.setup.autocomplete.enableError': 'Abilitazione autocompletamento fallita', + 'skills.setup.autocomplete.enabling': 'Abilitazione...', + 'skills.setup.autocomplete.notSupported': 'Non supportato', + 'skills.setup.autocomplete.stepEnable': 'Abilita completamenti inline', + 'skills.setup.autocomplete.stepSuccess': 'Pronto', + 'skills.setup.autocomplete.stylePreset': 'Preset di stile', + 'skills.setup.autocomplete.stylePresetValue': 'Bilanciato (configurabile in seguito)', + 'skills.setup.autocomplete.title': 'Autocompletamento testo', + 'skills.setup.screenIntel.activeDesc': 'Descrizione attivo', + 'skills.setup.screenIntel.activeTitle': 'Screen Intelligence abilitato', + 'skills.setup.screenIntel.advancedSettings': 'Impostazioni avanzate', + 'skills.setup.screenIntel.allGranted': 'Tutti i permessi concessi', + 'skills.setup.screenIntel.captureMode': 'Modalità di cattura', + 'skills.setup.screenIntel.captureModeValue': 'Tutte le finestre (configurabile in seguito)', + 'skills.setup.screenIntel.deniedHint': + 'Dopo aver concesso i permessi in Impostazioni di sistema, clicca sotto per riavviare e raccogliere le modifiche.', + 'skills.setup.screenIntel.enableBtn': 'Abilitazione...', + 'skills.setup.screenIntel.enableDesc': + 's sul tuo schermo e fornisce contesto utile al tuo agente', + 'skills.setup.screenIntel.enableError': 'Abilitazione Screen Intelligence fallita', + 'skills.setup.screenIntel.enabling': 'Abilitazione...', + 'skills.setup.screenIntel.grant': 'Apertura...', + 'skills.setup.screenIntel.granted': 'Concesso', + 'skills.setup.screenIntel.macosOnly': 'Solo macOS', + 'skills.setup.screenIntel.opening': 'Apertura...', + 'skills.setup.screenIntel.panicHotkey': 'Hotkey panico', + 'skills.setup.screenIntel.permAccessibility': 'Accessibilità', + 'skills.setup.screenIntel.permInputMonitoring': 'Monitoraggio input', + 'skills.setup.screenIntel.permScreenRecording': 'Registrazione schermo', + 'skills.setup.screenIntel.permissionsDesc': 'Descrizione permessi', + 'skills.setup.screenIntel.refreshStatus': 'Aggiorna stato', + 'skills.setup.screenIntel.restartRefresh': 'Riavvio...', + 'skills.setup.screenIntel.restarting': 'Riavvio...', + 'skills.setup.screenIntel.stepEnable': 'Abilita la skill', + 'skills.setup.screenIntel.stepPermissions': 'Concedi permessi', + 'skills.setup.screenIntel.stepSuccess': 'Pronto', + 'skills.setup.screenIntel.title': 'Screen Intelligence', + 'skills.setup.screenIntel.visionModel': 'Modello vision', + 'skills.setup.voice.activation': 'Attivazione', + 'skills.setup.voice.activeDescPrefix': 'Fn', + 'skills.setup.voice.activeDescSuffix': 'Fn', + 'skills.setup.voice.activeTitle': 'Voice Intelligence attivo', + 'skills.setup.voice.customizeSettings': 'Personalizza impostazioni', + 'skills.setup.voice.downloadSttBtn': 'Scarica STT', + 'skills.setup.voice.enableDesc': 'Descrizione abilitazione', + 'skills.setup.voice.hotkey': 'Hotkey', + 'skills.setup.voice.startBtn': 'Avvio...', + 'skills.setup.voice.startError': 'Avvio del server vocale fallito', + 'skills.setup.voice.starting': 'Avvio...', + 'skills.setup.voice.stepEnable': 'Avvia il server vocale', + 'skills.setup.voice.stepSetup': 'Download modello richiesto', + 'skills.setup.voice.stepSuccess': 'Pronto', + 'skills.setup.voice.sttNotReady': 'Modello speech-to-text non pronto', + 'skills.setup.voice.sttNotReadyDesc': + 'Voice Intelligence richiede un modello Whisper locale per la trascrizione. Scaricalo dalle impostazioni Modello locale.', + 'skills.setup.voice.sttReady': 'Modello speech-to-text pronto', + 'skills.setup.voice.sttReturnHint': 'Suggerimento ritorno STT', + 'skills.setup.voice.title': 'Voice Intelligence', + 'skills.uninstall.couldNotUninstall': 'Impossibile disinstallare', + 'skills.uninstall.description': + "Questa operazione elimina permanentemente la directory della skill e tutte le sue risorse incluse. L'agente smetterà di vederla al turno successivo.", + 'skills.uninstall.title': 'Disinstalla', + 'skills.uninstall.uninstallBtn': 'Disinstalla', + 'skills.uninstall.uninstalling': 'Disinstallazione…', + 'upsell.global.limitMessage': 'Aggiorna il tuo piano o ricarica i crediti per continuare', + 'upsell.global.limitTitle': 'Tu', + 'upsell.global.nearLimitMessage': + 'Hai usato il {pct}% del tuo limite di utilizzo. Aggiorna per limiti più alti.', + 'upsell.global.nearLimitTitle': 'Limite di utilizzo in avvicinamento', + 'upsell.usageLimit.bodyBudget': + 'Hai raggiunto il limite settimanale.{reset} Aggiorna il piano o ricarica crediti per evitare i limiti.', + 'upsell.usageLimit.bodyRate': + 'Hai raggiunto il limite di velocità di inferenza di 10 ore.{reset} Aggiorna per limiti più alti.', + 'upsell.usageLimit.heading': 'Limite di utilizzo raggiunto', + 'upsell.usageLimit.notNow': 'Non ora', + 'upsell.usageLimit.perWindow': '{amount}', + 'upsell.usageLimit.planIncludes': '{plan}', + 'upsell.usageLimit.resetsIn': 'Si resetta {time}.', + 'upsell.usageLimit.upgradePlan': 'Aggiorna piano', + 'upsell.usageLimit.weeklyInference': '{amount}', + 'walkthrough.tooltip.letsGo': 'Andiamo!', + 'walkthrough.tooltip.next': 'Avanti →', + 'walkthrough.tooltip.skip': 'Salta tour', + 'walkthrough.tooltip.stepCounter': '{n} di {total}', + 'webhooks.activity.empty': 'Vuoto', + 'webhooks.activity.title': 'Attività recente', + 'webhooks.composioHistory.empty': 'Vuoto', + 'webhooks.composioHistory.metadataId': 'ID metadati', + 'webhooks.composioHistory.metadataUuid': 'UUID metadati', + 'webhooks.composioHistory.payload': 'Payload', + 'webhooks.composioHistory.title': 'Cronologia trigger Composio', + 'webhooks.tunnels.active': 'Attivo', + 'webhooks.tunnels.createFailed': 'Creazione tunnel fallita', + 'webhooks.tunnels.creating': 'Creazione...', + 'webhooks.tunnels.deleteFailed': 'Eliminazione tunnel fallita', + 'webhooks.tunnels.descriptionPlaceholder': 'Descrizione (opzionale)', + 'webhooks.tunnels.echo': 'Echo', + 'webhooks.tunnels.empty': 'Vuoto', + 'webhooks.tunnels.enableEcho': 'Abilita echo', + 'webhooks.tunnels.inactive': 'Inattivo', + 'webhooks.tunnels.namePlaceholder': 'Nome tunnel (es. telegram-bot)', + 'webhooks.tunnels.newTunnel': 'Nuovo tunnel', + 'webhooks.tunnels.removeEcho': 'Rimuovi echo', + 'webhooks.tunnels.title': 'Tunnel webhook', + 'webhooks.tunnels.toggleFailed': 'Attivazione echo fallita', + 'composio.authExpired': 'Autenticazione scaduta', + 'composio.reconnect': 'Riconnetti', + 'composio.directModeRequiresKey': + 'Salvataggio fallito. La modalità Diretta richiede una chiave API non vuota.', + 'composio.notYetRouted': 'non ancora instradato', + 'composio.triggers.loading': 'Caricamento…', + 'conversations.taskKanban.todo': 'Da fare', + 'settings.composio.loading': 'Caricamento…', + 'settings.mascot.noCharactersAvailable': 'Nessun personaggio OpenHuman disponibile', + 'skills.uninstall.confirmTitle': 'Disinstallare {name}?', + 'conversations.taskKanban.blocked': 'Bloccato', + 'conversations.taskKanban.done': 'Fatto', + 'conversations.taskKanban.inProgress': 'In corso', + 'intelligence.memoryChunk.detail.copiedHint': 'copiato', + 'settings.composio.notYetRouted': 'non ancora instradato', + 'settings.localModel.download.manageExternal': 'Gestisci questo modello nel tuo runtime esterno.', + 'settings.localModel.status.manageOllamaExternal': + 'Gestisci il processo Ollama e i pull dei modelli al di fuori di OpenHuman, poi riesegui la diagnostica.', + 'settings.localModel.status.ollamaDocs': 'Documentazione Ollama', + 'settings.localModel.status.thenRetry': + 'per le istruzioni di configurazione, poi riprova quando il runtime è raggiungibile.', +}; + +export default it5; diff --git a/app/src/lib/i18n/chunks/pt-1.ts b/app/src/lib/i18n/chunks/pt-1.ts index 5c9ce518b..f6a78a4f4 100644 --- a/app/src/lib/i18n/chunks/pt-1.ts +++ b/app/src/lib/i18n/chunks/pt-1.ts @@ -17,7 +17,7 @@ const pt1: TranslationMap = { 'common.edit': 'Editar', 'common.create': 'Criar', 'common.search': 'Pesquisar', - 'common.loading': 'loading…', + 'common.loading': 'carregando…', 'common.error': 'Erro', 'common.success': 'Sucesso', 'common.back': 'Voltar', @@ -31,9 +31,9 @@ const pt1: TranslationMap = { 'common.yes': 'Sim', 'common.no': 'Não', 'common.ok': 'Entendi', - 'common.retry': 'Try again', + 'common.retry': 'Tentar novamente', 'common.copy': 'Copiar', - 'common.copied': 'Copied', + 'common.copied': 'Copiado', 'common.learnMore': 'Saiba mais', 'common.seeAll': 'Ver', 'common.dismiss': 'Dispensar', diff --git a/app/src/lib/i18n/chunks/pt-2.ts b/app/src/lib/i18n/chunks/pt-2.ts index 37bd586bb..d9acd8349 100644 --- a/app/src/lib/i18n/chunks/pt-2.ts +++ b/app/src/lib/i18n/chunks/pt-2.ts @@ -100,7 +100,7 @@ const pt2: TranslationMap = { 'devOptions.local': 'Local', 'devOptions.embeddedCoreSidecar': 'Core sidecar incorporado', 'devOptions.sidecarSpawned': 'Iniciado em processo pelo shell Tauri na abertura do app.', - 'devOptions.cloud': 'Cloud', + 'devOptions.cloud': 'Nuvem', 'devOptions.remoteCoreRpc': 'RPC do core remoto', 'devOptions.token': 'Token', 'devOptions.tokenNotSet': 'não definido — RPC retornará 401', @@ -235,7 +235,7 @@ const pt2: TranslationMap = { 'composio.triggersStillRecorded': 'Os gatilhos ainda são registrados no histórico — nenhum turno de LLM é executado.', 'composio.disableSpecificIntegrations': 'Desativar triagem de IA para integrações específicas', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'Configurações salvas', 'composio.saveFailed': 'Falha ao salvar. Tente novamente.', 'cron.title': 'Tarefas Cron', 'cron.scheduledJobs': 'Tarefas Agendadas', @@ -263,7 +263,7 @@ const pt2: TranslationMap = { 'Nenhuma resposta do agente após 2 minutos. Tente novamente ou verifique sua conexão.', 'chat.filter.all': 'Todos', 'chat.filter.work': 'Trabalho', - 'chat.filter.briefing': 'Briefing', + 'chat.filter.briefing': 'Resumo', 'chat.filter.notification': 'Notificação', 'chat.filter.workers': 'Workers', 'chat.selectThread': 'Selecione uma conversa', diff --git a/app/src/lib/i18n/chunks/pt-3.ts b/app/src/lib/i18n/chunks/pt-3.ts index d8d22a9da..3a49c47dd 100644 --- a/app/src/lib/i18n/chunks/pt-3.ts +++ b/app/src/lib/i18n/chunks/pt-3.ts @@ -253,9 +253,11 @@ const pt3: TranslationMap = { 'accounts.addModal.allConnected': 'Todos conectados', 'accounts.addModal.title': 'Adicionar conta', 'accounts.respondQueue.empty': 'Vazio', + 'accounts.respondQueue.hide': 'Ocultar fila de respostas', 'accounts.respondQueue.loadFailed': 'Falha ao carregar fila de respostas', 'accounts.respondQueue.loading': 'Carregando fila…', 'accounts.respondQueue.pending': 'Pendente', + 'accounts.respondQueue.show': 'Mostrar fila de respostas', 'accounts.respondQueue.title': 'Fila de respostas', 'accounts.webviewHost.almostReady': 'Quase pronto...', 'accounts.webviewHost.loadTimeout': 'Tempo limite de carregamento do webview', @@ -272,7 +274,7 @@ const pt3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'Core offline', 'app.connectionIndicator.disconnected': 'Desconectado', 'app.connectionIndicator.offline': 'Offline', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'Reconectando…', 'app.errorFallback.componentStack': 'Pilha de componentes', 'app.errorFallback.downloadLatest': 'Baixar mais recente', 'app.errorFallback.heading': 'Título', @@ -282,22 +284,22 @@ const pt3: TranslationMap = { 'app.errorFallback.tryRecover': 'Tentar recuperar', 'app.localAiDownload.installing': 'Instalando...', 'app.localAiDownload.preparing': 'Preparando...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'Continuar com login de {label}', 'app.openhumanLink.accounts.done': 'Concluído', - 'app.openhumanLink.accounts.intro': 'Intro', + 'app.openhumanLink.accounts.intro': 'Introdução', 'app.openhumanLink.accounts.webviewNote': 'Nota do webview', 'app.openhumanLink.billing.openDashboard': 'Abrir painel', 'app.openhumanLink.billing.stayOnTrial': 'Ficar no período de teste', 'app.openhumanLink.billing.trialCredit': 'Crédito de teste', 'app.openhumanLink.billing.trialDesc': 'Descrição do teste', 'app.openhumanLink.defaultBody': - 'Not ready in the popup yet. Open the full settings page when you need it.', - 'app.openhumanLink.discord.intro': 'Intro', + 'Ainda não disponível no popup. Abra a página completa de configurações quando precisar.', + 'app.openhumanLink.discord.intro': 'Introdução', 'app.openhumanLink.discord.openInvite': 'Abrir convite', - 'app.openhumanLink.discord.perk1': 'Perk1', - 'app.openhumanLink.discord.perk2': 'Perk2', - 'app.openhumanLink.discord.perk3': 'Perk3', - 'app.openhumanLink.discord.perk4': 'Perk4', + 'app.openhumanLink.discord.perk1': 'Benefício 1', + 'app.openhumanLink.discord.perk2': 'Benefício 2', + 'app.openhumanLink.discord.perk3': 'Benefício 3', + 'app.openhumanLink.discord.perk4': 'Benefício 4', 'app.openhumanLink.done': 'Concluído', 'app.openhumanLink.loadingChannelSetup': 'Carregando configuração do canal', 'app.openhumanLink.maybeLater': 'Talvez depois', @@ -306,13 +308,13 @@ const pt3: TranslationMap = { 'app.openhumanLink.notifications.blockedStep1': 'Passo 1 bloqueado', 'app.openhumanLink.notifications.blockedStep2': 'Passo 2 bloqueado', 'app.openhumanLink.notifications.blockedStep3': 'Passo 3 bloqueado', - 'app.openhumanLink.notifications.intro': 'Intro', + 'app.openhumanLink.notifications.intro': 'Introdução', 'app.openhumanLink.notifications.promptHint': 'Dica de solicitação', 'app.openhumanLink.notifications.retry': 'Tentar notificação de teste novamente', 'app.openhumanLink.notifications.send': 'Enviar notificação de teste', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'Não foi possível enviar: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'Notificação de teste enviada. Se você não a recebeu, vá em Configurações do Sistema → Notificações → OpenHuman, ative Permitir Notificações e defina o Estilo de Banner como Persistente.', 'app.openhumanLink.skipForNow': 'Pular por enquanto', 'app.openhumanLink.telegramUnavailable': 'Telegram indisponível', 'app.openhumanLink.title.accounts': 'Conecte seus apps', @@ -324,7 +326,7 @@ const pt3: TranslationMap = { 'app.persistRehydration.heading': 'Título', 'app.persistRehydration.resetCta': 'Redefinindo…', 'app.persistRehydration.resetting': 'Redefinindo…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'Inicializando OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'Algo deu errado durante a atualização.', 'app.update.header.default': 'Atualizar', @@ -334,7 +336,7 @@ const pt3: TranslationMap = { 'app.update.header.restarting': 'Reiniciando…', 'app.update.later': 'Depois', 'app.update.newVersionReady': 'Uma nova versão está pronta para instalar.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': '{amount} baixados', 'app.update.progress.installing': 'Instalando a nova versão…', 'app.update.progress.restarting': 'Relançando o app…', 'app.update.progress.working': '{percent}%', @@ -350,7 +352,7 @@ const pt3: TranslationMap = { 'channels.discord.picker.allPermissionsOk': 'O bot tem todas as permissões necessárias neste canal.', 'channels.discord.picker.botNotInServers': 'Bot não está nos servidores', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'Categoria', 'channels.discord.picker.channel': 'Canal', 'channels.discord.picker.checkingPermissions': 'Verificando permissões', 'channels.discord.picker.loadingChannels': 'Carregando canais...', @@ -361,7 +363,7 @@ const pt3: TranslationMap = { 'channels.discord.picker.selectChannel': 'Selecione um canal', 'channels.discord.picker.selectServer': 'Selecione um servidor', 'channels.discord.picker.server': 'Servidor', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'Seleção de Servidor e Canal', 'channels.discord.savedRestartRequired': 'Canal salvo. Reinicie o app para ativá-lo.', 'channels.telegram.connect': 'Conectar', 'channels.telegram.managedDmConnecting': 'DM gerenciado conectando', diff --git a/app/src/lib/i18n/chunks/pt-4.ts b/app/src/lib/i18n/chunks/pt-4.ts index f9eb8e0b4..94e27abf0 100644 --- a/app/src/lib/i18n/chunks/pt-4.ts +++ b/app/src/lib/i18n/chunks/pt-4.ts @@ -2,70 +2,70 @@ import type { TranslationMap } from '../types'; // Portuguese (Português) chunk 4/5. Translated from chunks/en-4.ts. const pt4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'Aprovar e Cancelar Inscrição', + 'chat.unsubscribeApproval.approved': '✓ Inscrição cancelada com sucesso.', 'chat.unsubscribeApproval.denied': '✕ Solicitação negada.', 'chat.unsubscribeApproval.deny': 'Negar', 'chat.unsubscribeApproval.processing': 'Processando...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'Solicitação de Cancelamento', 'commandPalette.ariaLabel': 'Paleta de comandos', 'commandPalette.description': 'Descrição', 'commandPalette.label': 'Comandos', 'commandPalette.noResults': 'Sem resultados', 'commandPalette.placeholder': 'Digite um comando ou pesquise…', 'commandPalette.searchAria': 'Pesquisar comandos', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'Pressione ? para ver todos os atalhos', 'commandPalette.title': 'Paleta de comandos', 'composio.connect.additionalConfigRequired': 'Configuração adicional necessária', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Rótulo de subdomínio Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'Conectar', + 'composio.connect.connectionFailed': 'Falha na conexão (status: {status}).', 'composio.connect.disconnectFailed': 'Falha ao desconectar: {msg}', 'composio.connect.disconnecting': 'Desconectando…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'Conecte sua', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'conta. Abriremos uma janela do navegador, você aprova o acesso lá, e este app detectará a conexão automaticamente.', + 'composio.connect.isConnected': 'está conectado.', + 'composio.connect.manage': 'Gerenciar', + 'composio.connect.needsSubdomain': 'Para conectar', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'informe seu subdomínio Atlassian (ex.: acme para acme.atlassian.net) e tente novamente.', + 'composio.connect.oauthComplete': 'OAuth a concluir…', 'composio.connect.oauthTimeout': 'Timeout de OAuth', 'composio.connect.permissions': 'Permissões', 'composio.connect.permissionsDefault': 'Leitura + Escrita ativadas por padrão', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'pode expor', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'As permissões do agente do OpenHuman são controladas abaixo como botões de leitura, escrita e admin.', 'composio.connect.reopenBrowser': 'Reabrir navegador', 'composio.connect.requestingUrl': 'Solicitando URL de conexão…', 'composio.connect.retryConnection': 'Tentar conexão novamente', 'composio.connect.scopeLoadError': 'Não foi possível carregar preferências de escopo: {msg}', 'composio.connect.scopeSaveError': 'Não foi possível salvar escopo {key}: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'Informe apenas o subdomínio curto (ex.: "acme"), não a URL completa. Deve conter apenas letras, números e hífens.', 'composio.connect.subdomainRequired': 'Por favor, insira seu subdomínio Atlassian para continuar.', 'composio.connect.wabaIdLabel': 'Rótulo de ID WABA', 'composio.connect.wabaIdRequired': 'Por favor, insira seu ID de Conta Empresarial do WhatsApp (WABA ID) para continuar.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'Aguardando', 'composio.connect.waitingHint': 'Dica de espera', 'composio.triggers.heading': 'Gatilhos', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'Ouvir eventos de', + 'composio.triggers.loadError': 'Não foi possível carregar os gatilhos', 'composio.triggers.needsConfiguration': 'Precisa de configuração', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'Nenhum gatilho disponível no momento para', 'conversations.taskKanban.moveLeft': 'Mover para esquerda', 'conversations.taskKanban.moveRight': 'Mover para direita', 'conversations.taskKanban.title': 'Tarefas', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'turno', 'conversations.toolTimeline.workerThread': 'thread de worker', 'daemon.serviceBlockingGate.body': 'Corpo', 'daemon.serviceBlockingGate.downloadHint': 'Dica de download', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'Baixar Versão Mais Recente', + 'daemon.serviceBlockingGate.retryCore': 'Tentar Core Novamente', 'daemon.serviceBlockingGate.retryFailed': 'Nova tentativa falhou. Baixe a versão mais recente do app e tente novamente.', 'daemon.serviceBlockingGate.retrying': 'Tentando novamente...', @@ -73,11 +73,11 @@ const pt4: TranslationMap = { 'home.banners.discordSubtitle': 'Subtítulo do Discord', 'home.banners.discordTitle': 'Entre no Nosso Discord', 'home.banners.earlyBirdDismiss': 'Dispensar banner de early bird', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': 'primeira assinatura.', 'home.banners.earlyBirdOn': 'Early bird ativo', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': 'Os primeiros 1.000 usuários ganham 60% de desconto.', 'home.banners.earlyBirdUseCode': 'Usar código early bird', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': 'fazer uma assinatura', 'home.banners.promoCreditsBody': 'Corpo dos créditos promocionais', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': 'Uso dos créditos promocionais', @@ -90,18 +90,18 @@ const pt4: TranslationMap = { 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', 'intelligence.memoryChunk.mentioned.heading': 'm e n c i o n a d o', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} pontuação {pct} por cento', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'em {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'descartado', 'intelligence.memoryChunk.scoreBars.heading': 'p o r q u ê m a n t i d o', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'mantido', + 'intelligence.memoryText.entityTypePrefix': 'Tipo de entidade', 'intelligence.screenDebug.active': 'Ativo', 'intelligence.screenDebug.app': 'App', 'intelligence.screenDebug.bounds': 'Limites', 'intelligence.screenDebug.captureAlt': 'Resultado do teste de captura', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'Falhou', + 'intelligence.screenDebug.captureSuccess': 'Sucesso', 'intelligence.screenDebug.captureTest': 'Teste de captura', 'intelligence.screenDebug.capturing': 'Capturando', 'intelligence.screenDebug.frames': 'Quadros', @@ -123,16 +123,16 @@ const pt4: TranslationMap = { 'intelligence.screenDebug.unknown': 'Desconhecido', 'intelligence.screenDebug.visionQueue': 'Fila de Visão', 'intelligence.screenDebug.visionState': 'Estado de Visão', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 quadro ativo entre conversas', + 'intelligence.tasks.activeBoardOther': '{count} quadros ativos entre conversas', 'intelligence.tasks.empty': 'Nenhum quadro de tarefas de agente ainda', 'intelligence.tasks.emptyHint': 'Dica de vazio', 'intelligence.tasks.failedToLoad': 'Falha ao carregar', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'ao vivo', 'intelligence.tasks.loadingBoards': 'Carregando quadros de tarefas…', 'intelligence.tasks.threadPrefix': 'Thread {thread}', 'notifications.card.dismiss': 'Dispensar notificação', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'Importância: {pct}%', 'notifications.center.empty': 'Nenhuma notificação ainda', 'notifications.center.emptyHint': 'Dica de vazio', 'notifications.center.filterAll': 'Filtrar todos', @@ -144,7 +144,7 @@ const pt4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': 'Construindo seu perfil...', 'onboarding.contextGathering.continueToChat': 'Continuar para o chat', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'Não conseguimos montar seu perfil completo agora, mas tudo bem — você pode continuar e seu perfil será construído ao longo do tempo.', 'onboarding.contextGathering.title': 'Coleta de Contexto', 'openhuman.team_list_teams': 'Listar equipes', 'overlay.ariaAttention': 'Mensagem de atenção', @@ -184,20 +184,20 @@ const pt4: TranslationMap = { 'privacy.dataKind.diagnostics': 'Diagnósticos', 'privacy.dataKind.metadata': 'Metadados', 'privacy.dataKind.raw': 'Bruto', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'O que sai do meu computador?', + 'rewards.community.achievementsUnlocked': '{unlocked} de {total} conquistas desbloqueadas', 'rewards.community.connectDiscord': 'Conectar Discord', 'rewards.community.cumulativeTokens': 'Tokens acumulados', 'rewards.community.currentStreak': 'Sequência atual', 'rewards.community.discordLinkedNotInGuild': 'Discord vinculado mas não no servidor', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'Entrou no servidor', 'rewards.community.discordNotLinked': 'Discord não vinculado', 'rewards.community.discordServer': 'Servidor do Discord', 'rewards.community.discordStatusUnavailable': 'Status do Discord indisponível', 'rewards.community.discordWaiting': 'Aguardando Discord', 'rewards.community.heroSubtitle': 'Subtítulo do herói', 'rewards.community.heroTitle': 'Título do herói', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': 'Entrar no Discord', 'rewards.community.loadingRewards': 'Carregando recompensas…', 'rewards.community.locked': 'Desbloqueado', 'rewards.community.retrying': 'Tentando novamente…', @@ -215,20 +215,20 @@ const pt4: TranslationMap = { 'rewards.coupon.colReward': 'Recompensa', 'rewards.coupon.colStatus': 'Status', 'rewards.coupon.loadingHistory': 'Carregando histórico de recompensas…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'Nenhum código de recompensa resgatado ainda.', 'rewards.coupon.pending': 'Pendente', 'rewards.coupon.placeholder': 'Código de cupom', 'rewards.coupon.promoCredits': 'Créditos promocionais', 'rewards.coupon.recentRedemptions': 'Resgates recentes', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} aceito. {amount} será desbloqueado após a ação necessária ser concluída.', + 'rewards.coupon.redeemButton': 'Resgatar Código', + 'rewards.coupon.redeemSuccess': '{code} resgatado. {amount} foi adicionado aos seus créditos.', 'rewards.coupon.redeemedCodes': 'Códigos resgatados', 'rewards.coupon.redeeming': 'Resgatando...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': 'Aplicado', + 'rewards.coupon.statusPendingAction': 'Ação pendente', + 'rewards.coupon.statusRedeemed': 'Resgatado', 'rewards.coupon.subtitle': 'Subtítulo', 'rewards.coupon.title': 'Resgatar um código de cupom', 'rewards.referralSection.activity': 'Atividade de indicações', @@ -244,7 +244,7 @@ const pt4: TranslationMap = { 'rewards.referralSection.haveCode': 'Tem um código de indicação?', 'rewards.referralSection.haveCodeDesc': 'Descrição do código', 'rewards.referralSection.linked': 'Vinculado', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(código {code})', 'rewards.referralSection.loading': 'Carregando programa de indicações…', 'rewards.referralSection.noReferrals': 'Sem indicações', 'rewards.referralSection.pendingReferrals': 'Indicações pendentes', @@ -257,18 +257,18 @@ const pt4: TranslationMap = { 'rewards.referralSection.title': 'Convide amigos, ganhe créditos', 'rewards.referralSection.totalEarned': 'Total ganho', 'rewards.referralSection.yourCode': 'Seu código', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'Adicionar provedor de nuvem', 'settings.ai.addProvider': 'Salvando…', 'settings.ai.apiKeyFieldLabel': 'Rótulo do campo de chave de API', 'settings.ai.apiKeyRequired': 'Por favor, cole sua chave de API para continuar.', 'settings.ai.apiKeyStoredEncrypted': 'Chave de API armazenada criptografada', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'Limpar chave armazenada', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'Conectar provedor', 'settings.ai.customRouting': 'Roteamento personalizado', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'Descartar', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'Editar provedor', 'settings.ai.llmProviders': 'Provedores LLM', 'settings.ai.llmProvidersDesc': 'Descrição dos provedores LLM', 'settings.ai.localOllama': 'Local (Ollama)', @@ -277,12 +277,12 @@ const pt4: TranslationMap = { 'settings.ai.providerLabel': 'Provedor', 'settings.ai.routing': 'Roteamento', 'settings.ai.routingCustom': 'Roteamento personalizado', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': 'Padrão', 'settings.ai.routingDesc': 'Descrição do roteamento', 'settings.ai.saveChanges': 'Salvando…', 'settings.ai.saving': 'Salvando…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'alteração não salva', + 'settings.ai.unsavedChanges': 'alterações não salvas', 'settings.ai.workloadGroupBackground': 'Grupo de carga de trabalho em segundo plano', 'settings.ai.workloadGroupChat': 'Grupo de carga de trabalho de chat', 'settings.autocomplete.appFilter.acceptSuggestion': 'Aceitar sugestão', @@ -296,9 +296,9 @@ const pt4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'Runtime', 'settings.autocomplete.appFilter.test': 'Testar', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + '{count} complemento aceito armazenado — usado para personalizar sugestões futuras.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + '{count} complementos aceitos armazenados — usados para personalizar sugestões futuras.', 'settings.autocomplete.completionStyle.clearHistory': 'Limpando…', 'settings.autocomplete.completionStyle.clearing': 'Limpando…', 'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)', @@ -348,7 +348,7 @@ const pt4: TranslationMap = { 'settings.billing.payAsYouGo.creditBalanceTitle': 'Título do saldo de crédito', 'settings.billing.payAsYouGo.customAmount': 'Valor personalizado', 'settings.billing.payAsYouGo.enterAmount': 'Inserir valor', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'Abrindo', 'settings.billing.payAsYouGo.promotionalCredits': 'Créditos Promocionais', 'settings.billing.payAsYouGo.topUpBalance': 'Recarregar Saldo', 'settings.billing.payAsYouGo.topUpCredits': 'Recarregar Créditos', diff --git a/app/src/lib/i18n/chunks/pt-5.ts b/app/src/lib/i18n/chunks/pt-5.ts index a1e97469e..f4f12da6a 100644 --- a/app/src/lib/i18n/chunks/pt-5.ts +++ b/app/src/lib/i18n/chunks/pt-5.ts @@ -6,49 +6,51 @@ const pt5: TranslationMap = { 'settings.billing.subscription.upgrade': 'Fazer upgrade', 'settings.billing.subscription.waiting': 'Aguardando', 'settings.billing.subscription.waitingPayment': 'Aguardando pagamento', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': + 'Uma chave de API do Composio está atualmente armazenada neste dispositivo.', + 'settings.composio.apiKeyLabel': 'Chave de API do Composio', + 'settings.composio.apiKeyStored': 'Chave de API armazenada', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Alternado para modo Backend', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'Uma conta em app.composio.dev com uma chave de API', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'Religar cada integração através da sua conta pessoal do Composio', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'Observação: gatilhos do Composio (webhooks em tempo real) ainda não funcionam no modo Direto — apenas chamadas síncronas de ferramentas', + 'settings.composio.confirmNeedItems': 'Você precisará de:', + 'settings.composio.confirmSwitch': 'Entendi, alternar para Direto', + 'settings.composio.confirmTitle': '⚠️ Alternando para o modo Direto', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'Suas integrações existentes (Gmail, Slack, GitHub, etc. conectadas via OpenHuman) não ficarão visíveis — elas vivem no tenant do Composio gerenciado pelo OpenHuman.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'O Composio integra mais de 250 apps externos como ferramentas que seu agente pode chamar. Escolha como essas chamadas são roteadas.', 'settings.composio.modeDirect': 'Direto (traga sua própria chave de API)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'As chamadas vão direto para backend.composio.dev. Soberano / amigável para offline. A execução de ferramentas funciona de forma síncrona; webhooks de gatilhos em tempo real ainda não são roteados no modo direto (issue de acompanhamento).', 'settings.composio.modeManaged': 'Gerenciado (OpenHuman cuida para você)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'O OpenHuman faz proxy das chamadas de ferramentas pelo nosso backend (recomendado). A autenticação é intermediada; você nunca cola uma chave de API do Composio. Webhooks são totalmente roteados.', 'settings.composio.routingMode': 'Modo de roteamento', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + 'Falha ao salvar. O modo Direto requer uma chave de API não vazia.', 'settings.composio.saving': 'Salvando…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': 'Alternando…', 'settings.cron.jobs.desc': 'Descrição', 'settings.cron.jobs.empty': 'Nenhuma tarefa cron do core encontrada.', 'settings.cron.jobs.lastStatus': 'Último status', 'settings.cron.jobs.loading': 'Carregando tarefas cron...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'Carregando execuções', 'settings.cron.jobs.nextRun': 'Próxima execução', 'settings.cron.jobs.pause': 'Pausar', 'settings.cron.jobs.paused': 'Ativado', 'settings.cron.jobs.recentRuns': 'Execuções recentes', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'Removendo', 'settings.cron.jobs.resume': 'Retomar', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'Executando agora', 'settings.cron.jobs.saving': 'Salvando…', 'settings.cron.jobs.schedule': 'Agendamento', 'settings.cron.jobs.title': 'Tarefas Cron do Core', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'Ver execuções', 'settings.localModel.deviceCapability.active': 'Ativo', 'settings.localModel.deviceCapability.appliedTier': 'Nível aplicado', 'settings.localModel.deviceCapability.applying': 'Aplicando', @@ -68,10 +70,11 @@ const pt5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Instalação do Ollama falhou', 'settings.localModel.deviceCapability.installFailedDesc': 'O instalador encerrou antes que o Ollama estivesse utilizável. Clique em tentar novamente ou instale manualmente em ollama.com.', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'Execute o Ollama primeiro.', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'Os níveis locais dependem de um endpoint Ollama gerenciado externamente. Inicie-o você mesmo, baixe os modelos desejados e continue usando "Desativado (fallback de nuvem)" até que o runtime esteja acessível.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'Execute o Ollama primeiro para usar este nível', 'settings.localModel.deviceCapability.installingOllama': 'Instalando ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'Carregando informações do dispositivo', 'settings.localModel.deviceCapability.localAiDisabled': @@ -93,8 +96,8 @@ const pt5: TranslationMap = { 'Digite qualquer prompt e execute-o no modelo local...', 'settings.localModel.download.quantizationPref': 'Preferência de quantização', 'settings.localModel.download.runEmbeddingTest': 'Executando...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'Executar Teste de Prompt', + 'settings.localModel.download.runSummaryTest': 'Executar Teste de Resumo', 'settings.localModel.download.runTranscriptionTest': 'Executando...', 'settings.localModel.download.runTtsTest': 'Executando...', 'settings.localModel.download.runVisionTest': 'Executando...', @@ -124,11 +127,11 @@ const pt5: TranslationMap = { 'settings.localModel.status.customLocation': 'Localização personalizada', 'settings.localModel.status.customLocationDesc': 'Descrição de localização personalizada', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Clique em "Executar Diagnóstico" para verificar se o Ollama está rodando e os modelos estão instalados.', 'settings.localModel.status.downloadingUnknown': 'Baixando (tamanho desconhecido)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'Modelos esperados', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'Forçar Re-bootstrap', 'settings.localModel.status.generationTps': 'TPS de geração', 'settings.localModel.status.hideErrorDetails': 'Ocultar detalhes do erro', 'settings.localModel.status.installManually': 'Instalar manualmente', @@ -138,16 +141,16 @@ const pt5: TranslationMap = { 'settings.localModel.status.installing': 'Instalando...', 'settings.localModel.status.installingOllama': 'Instalando runtime Ollama...', 'settings.localModel.status.issues': 'Problemas', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '{count} problema(s) encontrado(s)', 'settings.localModel.status.lastLatency': 'Última Latência', 'settings.localModel.status.model': 'Modelo', 'settings.localModel.status.notFound': 'Não encontrado', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'Não está em execução', 'settings.localModel.status.ollamaBinaryPath': 'Caminho do binário Ollama', 'settings.localModel.status.ollamaDiagnostics': 'Diagnósticos do Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Runtime do Ollama indisponível', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'O OpenHuman agora trata o Ollama como um runtime de inferência externo. Inicie seu próprio servidor Ollama, baixe os modelos desejados e aponte o roteamento de carga para ele.', 'settings.localModel.status.progress': 'Progresso', 'settings.localModel.status.provider': 'Provedor', 'settings.localModel.status.retryBootstrap': 'Tentar Bootstrap Novamente', @@ -172,26 +175,26 @@ const pt5: TranslationMap = { 'settings.mascot.colorHeading': 'Título de cor', 'settings.mascot.loadingLibrary': 'Carregando biblioteca do OpenHuman…', 'settings.mascot.localDefault': 'OpenHuman local (padrão)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'Nenhum personagem do OpenHuman disponível ainda', 'settings.mascot.noColorVariants': 'Sem variantes de cor', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'Recomendado', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'Padrão sensato — boa continuidade sem queimar tokens extras em cada execução.', + 'settings.memoryWindow.balanced.label': 'Balanceado', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'Quanto contexto lembrado o OpenHuman injeta em cada nova execução do agente. Janelas maiores parecem mais cientes de conversas passadas, mas usam mais tokens — e custam mais — a cada execução.', + 'settings.memoryWindow.extended.badge': 'Mais contexto', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'Mais memória de longo prazo injetada em cada execução. Custo maior por turno.', + 'settings.memoryWindow.extended.label': 'Estendido', + 'settings.memoryWindow.maximum.badge': 'Maior custo', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'A maior janela segura. Melhor continuidade, conta de tokens significativamente maior a cada execução.', + 'settings.memoryWindow.maximum.label': 'Máximo', + 'settings.memoryWindow.minimal.badge': 'Mais barato', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'Menor janela de memória. Mais barato, mais rápido, menor continuidade entre execuções.', + 'settings.memoryWindow.minimal.label': 'Mínimo', 'settings.memoryWindow.title': 'Janela de memória de longo prazo', 'settings.screenIntel.permissions.accessibility': 'Acessibilidade', 'settings.screenIntel.permissions.grantHint': 'Dica de concessão', @@ -208,17 +211,17 @@ const pt5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'Gravação de Tela', 'settings.screenIntel.permissions.title': 'Permissões', 'skills.card.moreActions': 'Mais ações', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'Ferramentas permitidas', + 'skills.create.author': 'Autor', 'skills.create.authorPlaceholder': 'Seu nome', 'skills.create.commaSeparated': '(separado por vírgulas)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'Criar skill', 'skills.create.createError': 'Não foi possível criar habilidade', 'skills.create.creating': 'Criando…', - 'skills.create.description': 'Description', + 'skills.create.description': 'Descrição', 'skills.create.descriptionPlaceholder': 'O que essa habilidade faz?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'Licença', + 'skills.create.name': 'Nome', 'skills.create.namePlaceholder': 'ex.: Trade Journal', 'skills.create.scope': 'Escopo', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -227,7 +230,7 @@ const pt5: TranslationMap = { 'skills.create.slugLabel': 'Rótulo do slug', 'skills.create.subtitle': 'SKILL.md', 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.title': 'Nova skill', 'skills.detail.allowedTools': 'Ferramentas permitidas', 'skills.detail.author': 'Autor', 'skills.detail.bundledResources': 'Recursos incluídos', @@ -244,13 +247,13 @@ const pt5: TranslationMap = { 'skills.install.rawError': 'Erro bruto', 'skills.install.timeoutHint': '(segundos, opcional)', 'skills.install.timeoutLabel': 'Rótulo de timeout', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': 'Instalar skill a partir de URL', + 'skills.install.urlLabel': 'URL da skill', 'skills.meetingBots.bannerDesc': 'Descrição do banner', 'skills.meetingBots.bannerTitle': 'Título do banner', 'skills.meetingBots.busyTitle': 'OpenHuman está ocupado', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'Em breve', + 'skills.meetingBots.couldNotStartTitle': 'Não foi possível iniciar o OpenHuman', 'skills.meetingBots.displayName': 'Nome de exibição', 'skills.meetingBots.failedToStart': 'Falha ao iniciar o OpenHuman.', 'skills.meetingBots.joiningMessage': 'Ele deve aparecer como participante em alguns segundos.', @@ -260,10 +263,10 @@ const pt5: TranslationMap = { 'skills.meetingBots.modalDesc': 'Descrição do modal', 'skills.meetingBots.modalTitle': 'Enviar OpenHuman para uma reunião', 'skills.meetingBots.newBadge': 'Badge novo', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'Enviar para', 'skills.meetingBots.starting': 'Iniciando…', 'skills.resource.preview.closeAriaLabel': 'Fechar visualização', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'Falha na pré-visualização', 'skills.resource.preview.loading': 'Carregando visualização…', 'skills.resource.tree.empty': 'Sem recursos incluídos.', 'skills.search.placeholder': 'Placeholder', @@ -331,32 +334,32 @@ const pt5: TranslationMap = { 'skills.setup.voice.sttReady': 'Modelo de fala para texto pronto', 'skills.setup.voice.sttReturnHint': 'Dica de retorno STT', 'skills.setup.voice.title': 'Inteligência de Voz', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'Não foi possível desinstalar', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'Isso exclui permanentemente o diretório da skill e todos os recursos empacotados. O agente deixará de vê-la no próximo turno.', + 'skills.uninstall.title': 'Desinstalar', + 'skills.uninstall.uninstallBtn': 'Desinstalar', + 'skills.uninstall.uninstalling': 'Desinstalando…', 'upsell.global.limitMessage': 'Faça upgrade do seu plano ou adicione créditos para continuar', 'upsell.global.limitTitle': 'Você', 'upsell.global.nearLimitMessage': 'Você usou {pct}% do seu limite de uso. Faça upgrade para limites mais altos.', 'upsell.global.nearLimitTitle': 'Aproximando-se do limite de uso', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'Você atingiu seu limite semanal.{reset} Atualize seu plano ou recarregue créditos para evitar limites.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'Você atingiu seu limite de taxa de inferência de 10 horas.{reset} Atualize para limites maiores.', 'upsell.usageLimit.heading': 'Limite de Uso Atingido', 'upsell.usageLimit.notNow': 'Agora não', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'Será redefinido {time}.', 'upsell.usageLimit.upgradePlan': 'Fazer upgrade do plano', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'Vamos lá!', + 'walkthrough.tooltip.next': 'Próximo →', + 'walkthrough.tooltip.skip': 'Pular tour', + 'walkthrough.tooltip.stepCounter': '{n} de {total}', 'webhooks.activity.empty': 'Vazio', 'webhooks.activity.title': 'Atividade Recente', 'webhooks.composioHistory.empty': 'Vazio', @@ -378,26 +381,27 @@ const pt5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'Remover Echo', 'webhooks.tunnels.title': 'Tunnels de Webhook', 'webhooks.tunnels.toggleFailed': 'Falha ao alternar echo', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'Autenticação expirada', + 'composio.reconnect': 'Reconectar', + 'composio.directModeRequiresKey': + 'Falha ao salvar. O modo Direto requer uma chave de API não vazia.', + 'composio.notYetRouted': 'ainda não roteado', + 'composio.triggers.loading': 'Carregando…', + 'conversations.taskKanban.todo': 'A fazer', + 'settings.composio.loading': 'Carregando…', + 'settings.mascot.noCharactersAvailable': 'Nenhum personagem do OpenHuman disponível ainda', + 'skills.uninstall.confirmTitle': 'Desinstalar {name}?', + 'conversations.taskKanban.blocked': 'Bloqueado', + 'conversations.taskKanban.done': 'Concluído', + 'conversations.taskKanban.inProgress': 'Em andamento', + 'intelligence.memoryChunk.detail.copiedHint': 'copiado', + 'settings.composio.notYetRouted': 'ainda não roteado', + 'settings.localModel.download.manageExternal': 'Gerencie este modelo no seu runtime externo.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'Gerencie o processo do Ollama e o download de modelos fora do OpenHuman e, em seguida, execute o diagnóstico novamente.', + 'settings.localModel.status.ollamaDocs': 'Documentação do Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'para instruções de configuração, em seguida tente novamente depois que seu runtime estiver acessível.', }; export default pt5; diff --git a/app/src/lib/i18n/chunks/ru-1.ts b/app/src/lib/i18n/chunks/ru-1.ts index 66f4debc0..d1f8005c6 100644 --- a/app/src/lib/i18n/chunks/ru-1.ts +++ b/app/src/lib/i18n/chunks/ru-1.ts @@ -17,7 +17,7 @@ const ru1: TranslationMap = { 'common.edit': 'Редактировать', 'common.create': 'Создать', 'common.search': 'Поиск', - 'common.loading': 'loading…', + 'common.loading': 'загрузка…', 'common.error': 'Ошибка', 'common.success': 'Готово', 'common.back': 'Назад', @@ -31,9 +31,9 @@ const ru1: TranslationMap = { 'common.yes': 'Да', 'common.no': 'Нет', 'common.ok': 'Понятно', - 'common.retry': 'Try again', + 'common.retry': 'Повторить', 'common.copy': 'Копировать', - 'common.copied': 'Copied', + 'common.copied': 'Скопировано', 'common.learnMore': 'Узнать больше', 'common.seeAll': 'Посмотреть', 'common.dismiss': 'Закрыть', diff --git a/app/src/lib/i18n/chunks/ru-2.ts b/app/src/lib/i18n/chunks/ru-2.ts index 637cf2751..a838403de 100644 --- a/app/src/lib/i18n/chunks/ru-2.ts +++ b/app/src/lib/i18n/chunks/ru-2.ts @@ -230,7 +230,7 @@ const ru2: TranslationMap = { 'composio.triggersStillRecorded': 'Триггеры по-прежнему записываются в историю — LLM-запросы не выполняются.', 'composio.disableSpecificIntegrations': 'Отключить AI-сортировку для конкретных интеграций', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': 'Настройки сохранены', 'composio.saveFailed': 'Не удалось сохранить. Попробуй ещё раз.', 'cron.title': 'Задания по расписанию', 'cron.scheduledJobs': 'Запланированные задания', @@ -367,9 +367,9 @@ const ru2: TranslationMap = { 'dreams.description': 'Сны — это AI-отражения, которые синтезируют закономерности из твоих воспоминаний.', 'dreams.comingSoon': 'Скоро', - 'assignment.memoryLlm': 'Memory LLM', + 'assignment.memoryLlm': 'LLM памяти', 'assignment.memoryLlmAria': 'Выбор Memory LLM', - 'assignment.embedder': 'Embedder', + 'assignment.embedder': 'Эмбеддер', 'assignment.loaded': 'Загружено', 'assignment.notDownloaded': 'Не загружено', 'assignment.usedForExtractSummarise': 'Используется для извлечения и суммаризации', diff --git a/app/src/lib/i18n/chunks/ru-3.ts b/app/src/lib/i18n/chunks/ru-3.ts index c627b8e9c..ed426b164 100644 --- a/app/src/lib/i18n/chunks/ru-3.ts +++ b/app/src/lib/i18n/chunks/ru-3.ts @@ -251,9 +251,11 @@ const ru3: TranslationMap = { 'accounts.addModal.allConnected': 'Все подключены', 'accounts.addModal.title': 'Добавить аккаунт', 'accounts.respondQueue.empty': 'Пусто', + 'accounts.respondQueue.hide': 'Скрыть очередь ответов', 'accounts.respondQueue.loadFailed': 'Не удалось загрузить очередь ответов', 'accounts.respondQueue.loading': 'Загрузка очереди…', 'accounts.respondQueue.pending': 'Ожидает', + 'accounts.respondQueue.show': 'Показать очередь ответов', 'accounts.respondQueue.title': 'Очередь ответов', 'accounts.webviewHost.almostReady': 'Почти готово...', 'accounts.webviewHost.loadTimeout': 'Таймаут загрузки', @@ -270,7 +272,7 @@ const ru3: TranslationMap = { 'app.connectionIndicator.coreOffline': 'Ядро офлайн', 'app.connectionIndicator.disconnected': 'Отключено', 'app.connectionIndicator.offline': 'Офлайн', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': 'Переподключение…', 'app.errorFallback.componentStack': 'Стек компонентов', 'app.errorFallback.downloadLatest': 'Скачать последнюю версию', 'app.errorFallback.heading': 'Заголовок', @@ -280,37 +282,37 @@ const ru3: TranslationMap = { 'app.errorFallback.tryRecover': 'Попробовать восстановить', 'app.localAiDownload.installing': 'Установка...', 'app.localAiDownload.preparing': 'Подготовка...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': 'Продолжить со входом через {label}', 'app.openhumanLink.accounts.done': 'Готово', - 'app.openhumanLink.accounts.intro': 'Intro', - 'app.openhumanLink.accounts.webviewNote': 'Webview note', + 'app.openhumanLink.accounts.intro': 'Введение', + 'app.openhumanLink.accounts.webviewNote': 'Примечание о Webview', 'app.openhumanLink.billing.openDashboard': 'Открыть панель', 'app.openhumanLink.billing.stayOnTrial': 'Остаться на пробном периоде', 'app.openhumanLink.billing.trialCredit': 'Пробный кредит', - 'app.openhumanLink.billing.trialDesc': 'Trial desc', + 'app.openhumanLink.billing.trialDesc': 'Описание пробного периода', 'app.openhumanLink.defaultBody': - 'Not ready in the popup yet. Open the full settings page when you need it.', - 'app.openhumanLink.discord.intro': 'Intro', + 'Ещё не готово во всплывающем окне. Откройте полную страницу настроек, когда понадобится.', + 'app.openhumanLink.discord.intro': 'Введение', 'app.openhumanLink.discord.openInvite': 'Открыть приглашение', - 'app.openhumanLink.discord.perk1': 'Perk1', - 'app.openhumanLink.discord.perk2': 'Perk2', - 'app.openhumanLink.discord.perk3': 'Perk3', - 'app.openhumanLink.discord.perk4': 'Perk4', + 'app.openhumanLink.discord.perk1': 'Преимущество 1', + 'app.openhumanLink.discord.perk2': 'Преимущество 2', + 'app.openhumanLink.discord.perk3': 'Преимущество 3', + 'app.openhumanLink.discord.perk4': 'Преимущество 4', 'app.openhumanLink.done': 'Готово', 'app.openhumanLink.loadingChannelSetup': 'Загрузка настроек канала', 'app.openhumanLink.maybeLater': 'Может, потом', 'app.openhumanLink.notifications.asking': 'Запрос у ОС…', 'app.openhumanLink.notifications.blocked': 'Заблокировано', - 'app.openhumanLink.notifications.blockedStep1': 'Blocked step1', - 'app.openhumanLink.notifications.blockedStep2': 'Blocked step2', - 'app.openhumanLink.notifications.blockedStep3': 'Blocked step3', - 'app.openhumanLink.notifications.intro': 'Intro', - 'app.openhumanLink.notifications.promptHint': 'Prompt hint', + 'app.openhumanLink.notifications.blockedStep1': 'Заблокировано, шаг 1', + 'app.openhumanLink.notifications.blockedStep2': 'Заблокировано, шаг 2', + 'app.openhumanLink.notifications.blockedStep3': 'Заблокировано, шаг 3', + 'app.openhumanLink.notifications.intro': 'Введение', + 'app.openhumanLink.notifications.promptHint': 'Подсказка', 'app.openhumanLink.notifications.retry': 'Повторить тестовое уведомление', 'app.openhumanLink.notifications.send': 'Отправить тестовое уведомление', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': 'Не удалось отправить: {error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + 'Тестовое уведомление отправлено. Если вы его не получили, откройте «Системные настройки» → «Уведомления» → OpenHuman, включите «Разрешить уведомления» и установите стиль баннера «Постоянный».', 'app.openhumanLink.skipForNow': 'Пропустить', 'app.openhumanLink.telegramUnavailable': 'Telegram недоступен', 'app.openhumanLink.title.accounts': 'Подключи свои приложения', @@ -318,11 +320,11 @@ const ru3: TranslationMap = { 'app.openhumanLink.title.discord': 'Вступи в сообщество', 'app.openhumanLink.title.messaging': 'Подключи канал связи', 'app.openhumanLink.title.notifications': 'Разрешить уведомления', - 'app.persistRehydration.body': 'Body', + 'app.persistRehydration.body': 'Текст', 'app.persistRehydration.heading': 'Заголовок', 'app.persistRehydration.resetCta': 'Сброс…', 'app.persistRehydration.resetting': 'Сброс…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': 'Инициализация OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': 'Что-то пошло не так при обновлении.', 'app.update.header.default': 'Обновление', @@ -332,11 +334,11 @@ const ru3: TranslationMap = { 'app.update.header.restarting': 'Перезапуск…', 'app.update.later': 'Позже', 'app.update.newVersionReady': 'Новая версия готова к установке.', - 'app.update.progress.downloaded': '{amount} downloaded', + 'app.update.progress.downloaded': 'Загружено: {amount}', 'app.update.progress.installing': 'Установка новой версии…', 'app.update.progress.restarting': 'Перезапуск приложения…', 'app.update.progress.working': '{percent}%', - 'app.update.restartNote': 'Restart note', + 'app.update.restartNote': 'Примечание о перезапуске', 'app.update.restartNow': 'Перезапустить сейчас', 'app.update.versionReady': 'Версия {newVersion} готова к установке.', 'channels.discord.accountLinked': 'Аккаунт привязан', @@ -347,7 +349,7 @@ const ru3: TranslationMap = { 'channels.discord.linkTokenOnce': 'Токен привязки (однократно)', 'channels.discord.picker.allPermissionsOk': 'Бот имеет все необходимые права в этом канале.', 'channels.discord.picker.botNotInServers': 'Бот не на серверах', - 'channels.discord.picker.category': 'Category', + 'channels.discord.picker.category': 'Категория', 'channels.discord.picker.channel': 'Канал', 'channels.discord.picker.checkingPermissions': 'Проверка прав', 'channels.discord.picker.loadingChannels': 'Загрузка каналов...', @@ -358,7 +360,7 @@ const ru3: TranslationMap = { 'channels.discord.picker.selectChannel': 'Выбери канал', 'channels.discord.picker.selectServer': 'Выбери сервер', 'channels.discord.picker.server': 'Сервер', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': 'Выбор сервера и канала', 'channels.discord.savedRestartRequired': 'Канал сохранён. Перезапусти приложение для активации.', 'channels.telegram.connect': 'Подключить', 'channels.telegram.managedDmConnecting': 'Подключение управляемого DM', diff --git a/app/src/lib/i18n/chunks/ru-4.ts b/app/src/lib/i18n/chunks/ru-4.ts index 0037623ba..19b1cbb5a 100644 --- a/app/src/lib/i18n/chunks/ru-4.ts +++ b/app/src/lib/i18n/chunks/ru-4.ts @@ -2,105 +2,105 @@ import type { TranslationMap } from '../types'; // Russian (Русский) chunk 4/5. Translated from chunks/en-4.ts. const ru4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': 'Подтвердить и отписаться', + 'chat.unsubscribeApproval.approved': '✓ Подписка успешно отменена.', 'chat.unsubscribeApproval.denied': '✕ Запрос отклонён.', 'chat.unsubscribeApproval.deny': 'Отклонить', 'chat.unsubscribeApproval.processing': 'Обработка...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': 'Запрос на отписку', 'commandPalette.ariaLabel': 'Палитра команд', 'commandPalette.description': 'Описание', 'commandPalette.label': 'Команды', 'commandPalette.noResults': 'Ничего не найдено', 'commandPalette.placeholder': 'Введи команду или поиск…', 'commandPalette.searchAria': 'Поиск команд', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': 'Нажмите ?, чтобы увидеть все сочетания', 'commandPalette.title': 'Палитра команд', 'composio.connect.additionalConfigRequired': 'Требуется дополнительная настройка', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Поддомен Atlassian', - 'composio.connect.connect': 'Connect', - 'composio.connect.connectionFailed': 'Connection failed (status: {status}).', + 'composio.connect.connect': 'Подключить', + 'composio.connect.connectionFailed': 'Не удалось подключиться (статус: {status}).', 'composio.connect.disconnectFailed': 'Ошибка отключения: {msg}', 'composio.connect.disconnecting': 'Отключение…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': 'Подключите свой', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + 'аккаунт. Мы откроем окно браузера, вы предоставите доступ там, и приложение автоматически обнаружит подключение.', + 'composio.connect.isConnected': 'подключён.', + 'composio.connect.manage': 'Управлять', + 'composio.connect.needsSubdomain': 'Чтобы подключить', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + 'введите ваш поддомен Atlassian (например, acme для acme.atlassian.net) и попробуйте снова.', + 'composio.connect.oauthComplete': 'Ожидание завершения OAuth…', 'composio.connect.oauthTimeout': 'Таймаут OAuth', 'composio.connect.permissions': 'Разрешения', 'composio.connect.permissionsDefault': 'Чтение + запись включены по умолчанию', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': 'может раскрыть', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'Собственные права агента OpenHuman настраиваются ниже переключателями чтения, записи и администратора.', 'composio.connect.reopenBrowser': 'Открыть браузер снова', 'composio.connect.requestingUrl': 'Запрос URL подключения…', 'composio.connect.retryConnection': 'Повторить подключение', 'composio.connect.scopeLoadError': 'Не удалось загрузить настройки области: {msg}', 'composio.connect.scopeSaveError': 'Не удалось сохранить область {key}: {msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + 'Введите только короткий поддомен (например, "acme"), а не полный URL. Допустимы только буквы, цифры и дефисы.', 'composio.connect.subdomainRequired': 'Введи свой поддомен Atlassian для продолжения.', 'composio.connect.wabaIdLabel': 'ID аккаунта WhatsApp Business', 'composio.connect.wabaIdRequired': 'Введи ID аккаунта WhatsApp Business (WABA ID) для продолжения.', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': 'Ожидание', 'composio.connect.waitingHint': 'Подсказка ожидания', 'composio.triggers.heading': 'Триггеры', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': 'Слушать события от', + 'composio.triggers.loadError': 'Не удалось загрузить триггеры', 'composio.triggers.needsConfiguration': 'Требуется настройка', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': 'Сейчас нет доступных триггеров для', 'conversations.taskKanban.moveLeft': 'Переместить влево', 'conversations.taskKanban.moveRight': 'Переместить вправо', 'conversations.taskKanban.title': 'Задачи', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': 'ход', 'conversations.toolTimeline.workerThread': 'чат воркера', - 'daemon.serviceBlockingGate.body': 'Body', + 'daemon.serviceBlockingGate.body': 'Текст', 'daemon.serviceBlockingGate.downloadHint': 'Подсказка по загрузке', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': 'Скачать последнюю версию', + 'daemon.serviceBlockingGate.retryCore': 'Повторить запуск Core', 'daemon.serviceBlockingGate.retryFailed': 'Повтор не удался. Скачай последнюю версию и попробуй снова.', 'daemon.serviceBlockingGate.retrying': 'Повтор...', 'daemon.serviceBlockingGate.title': 'Ядро OpenHuman недоступно', - 'home.banners.discordSubtitle': 'Discord subtitle', + 'home.banners.discordSubtitle': 'Подзаголовок Discord', 'home.banners.discordTitle': 'Вступи в наш Discord', 'home.banners.earlyBirdDismiss': 'Закрыть баннер', - 'home.banners.earlyBirdFirstSub': 'first subscription.', - 'home.banners.earlyBirdOn': 'Early bird on', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', - 'home.banners.earlyBirdUseCode': 'Early bird use code', - 'home.banners.getSubscription': 'get a subscription', - 'home.banners.promoCreditsBody': 'Promo credits body', + 'home.banners.earlyBirdFirstSub': 'первую подписку.', + 'home.banners.earlyBirdOn': 'Скидка раннего доступа на', + 'home.banners.earlyBirdTitle': 'Первые 1 000 пользователей получают скидку 60%.', + 'home.banners.earlyBirdUseCode': 'Используйте промокод для раннего доступа', + 'home.banners.getSubscription': 'оформить подписку', + 'home.banners.promoCreditsBody': 'Описание промо-кредитов', 'home.banners.promoCreditsTitle': '{amount}', - 'home.banners.promoCreditsUsage': 'Promo credits usage', + 'home.banners.promoCreditsUsage': 'Использование промо-кредитов', 'intelligence.memoryChunk.detail.chunk': 'Блок', 'intelligence.memoryChunk.detail.copyChunkId': 'Скопировать ID блока', 'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024dim', 'intelligence.memoryChunk.detail.noEmbedding': 'Векторного вложения нет', 'intelligence.memoryChunk.letterhead.from': 'от', 'intelligence.memoryChunk.letterhead.to': 'кому', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 фрагмент', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} фрагментов', 'intelligence.memoryChunk.mentioned.heading': 'у п о м я н у т о', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} оценка {pct} процентов', + 'intelligence.memoryChunk.scoreBars.atThreshold': 'при {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': 'отброшено', 'intelligence.memoryChunk.scoreBars.heading': 'п о ч е м у с о х р а н е н о', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': 'сохранено', + 'intelligence.memoryText.entityTypePrefix': 'Тип сущности', 'intelligence.screenDebug.active': 'Активно', 'intelligence.screenDebug.app': 'Приложение', 'intelligence.screenDebug.bounds': 'Границы', 'intelligence.screenDebug.captureAlt': 'Результат тестового захвата', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': 'Ошибка', + 'intelligence.screenDebug.captureSuccess': 'Успех', 'intelligence.screenDebug.captureTest': 'Тест захвата', 'intelligence.screenDebug.capturing': 'Захват', 'intelligence.screenDebug.frames': 'Кадры', @@ -122,28 +122,28 @@ const ru4: TranslationMap = { 'intelligence.screenDebug.unknown': 'Неизвестно', 'intelligence.screenDebug.visionQueue': 'Очередь обработки изображений', 'intelligence.screenDebug.visionState': 'Состояние обработки изображений', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 активная доска в разговорах', + 'intelligence.tasks.activeBoardOther': '{count} активных досок в разговорах', 'intelligence.tasks.empty': 'Досок задач агента пока нет', - 'intelligence.tasks.emptyHint': 'Empty hint', + 'intelligence.tasks.emptyHint': 'Пусто', 'intelligence.tasks.failedToLoad': 'Не удалось загрузить', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': 'в реальном времени', 'intelligence.tasks.loadingBoards': 'Загрузка досок задач…', - 'intelligence.tasks.threadPrefix': 'Thread {thread}', + 'intelligence.tasks.threadPrefix': 'Тред {thread}', 'notifications.card.dismiss': 'Закрыть уведомление', - 'notifications.card.importanceTitle': 'Importance: {pct}%', + 'notifications.card.importanceTitle': 'Важность: {pct}%', 'notifications.center.empty': 'Уведомлений пока нет', - 'notifications.center.emptyHint': 'Empty hint', + 'notifications.center.emptyHint': 'Пусто', 'notifications.center.filterAll': 'Все', 'notifications.center.markAllRead': 'Отметить всё прочитанным', 'notifications.center.title': 'Уведомления', 'oauth.button.connecting': 'Подключение...', 'oauth.login.continueWith': 'Продолжить через', - 'onboarding.contextGathering.buildingDesc': 'Building desc', + 'onboarding.contextGathering.buildingDesc': 'Сборка профиля', 'onboarding.contextGathering.buildingProfile': 'Составление профиля...', 'onboarding.contextGathering.continueToChat': 'Перейти в чат', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + 'Мы не смогли построить ваш полный профиль прямо сейчас, но это нормально — вы можете продолжить, и профиль будет дополняться со временем.', 'onboarding.contextGathering.title': 'Сбор контекста', 'openhuman.team_list_teams': 'Список команд', 'overlay.ariaAttention': 'Сообщение', @@ -151,30 +151,30 @@ const ru4: TranslationMap = { 'overlay.ariaVoiceActive': 'Голосовой ввод активен', 'overlay.orbTitle': 'Перетащи для перемещения · Двойной клик для сброса позиции', 'pages.settings.account.connections': 'Подключения', - 'pages.settings.account.connectionsDesc': 'Connections desc', + 'pages.settings.account.connectionsDesc': 'Описание подключений', 'pages.settings.account.privacy': 'Конфиденциальность', - 'pages.settings.account.privacyDesc': 'Privacy desc', + 'pages.settings.account.privacyDesc': 'Описание конфиденциальности', 'pages.settings.account.recoveryPhrase': 'Фраза восстановления', - 'pages.settings.account.recoveryPhraseDesc': 'Recovery phrase desc', + 'pages.settings.account.recoveryPhraseDesc': 'Описание фразы восстановления', 'pages.settings.account.team': 'Команда', - 'pages.settings.account.teamDesc': 'Team desc', + 'pages.settings.account.teamDesc': 'Описание команды', 'pages.settings.accountSection.description': 'Фраза восстановления, команда, подключения и настройки конфиденциальности.', 'pages.settings.accountSection.title': 'Аккаунт', 'pages.settings.ai.llm': 'LLM', - 'pages.settings.ai.llmDesc': 'Llm desc', + 'pages.settings.ai.llmDesc': 'Описание LLM', 'pages.settings.ai.voice': 'Голос', - 'pages.settings.ai.voiceDesc': 'Voice desc', + 'pages.settings.ai.voiceDesc': 'Описание голоса', 'pages.settings.aiSection.description': 'Языковые модели, локальный Ollama и голос (STT / TTS).', - 'pages.settings.aiSection.title': 'AI', + 'pages.settings.aiSection.title': 'ИИ', 'pages.settings.features.messagingChannels': 'Каналы мессенджеров', - 'pages.settings.features.messagingChannelsDesc': 'Messaging channels desc', + 'pages.settings.features.messagingChannelsDesc': 'Описание каналов сообщений', 'pages.settings.features.notifications': 'Уведомления', - 'pages.settings.features.notificationsDesc': 'Notifications desc', + 'pages.settings.features.notificationsDesc': 'Описание уведомлений', 'pages.settings.features.screenAwareness': 'Слежение за экраном', - 'pages.settings.features.screenAwarenessDesc': 'Screen awareness desc', + 'pages.settings.features.screenAwarenessDesc': 'Описание распознавания экрана', 'pages.settings.features.tools': 'Инструменты', - 'pages.settings.features.toolsDesc': 'Tools desc', + 'pages.settings.features.toolsDesc': 'Описание инструментов', 'pages.settings.featuresSection.description': 'Слежение за экраном, мессенджеры и инструменты.', 'pages.settings.featuresSection.title': 'Функции', 'privacy.dataKind.credentials': 'Учётные данные', @@ -182,27 +182,27 @@ const ru4: TranslationMap = { 'privacy.dataKind.diagnostics': 'Диагностика', 'privacy.dataKind.metadata': 'Метаданные', 'privacy.dataKind.raw': 'Необработанные данные', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': 'Что покидает мой компьютер?', + 'rewards.community.achievementsUnlocked': 'Открыто достижений: {unlocked} из {total}', 'rewards.community.connectDiscord': 'Подключить Discord', 'rewards.community.cumulativeTokens': 'Токенов всего', 'rewards.community.currentStreak': 'Текущая серия', 'rewards.community.discordLinkedNotInGuild': 'Discord привязан, но не в сервере', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': 'Присоединился к серверу', 'rewards.community.discordNotLinked': 'Discord не привязан', 'rewards.community.discordServer': 'Сервер Discord', 'rewards.community.discordStatusUnavailable': 'Статус Discord недоступен', 'rewards.community.discordWaiting': 'Ожидание Discord', - 'rewards.community.heroSubtitle': 'Hero subtitle', - 'rewards.community.heroTitle': 'Hero title', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.heroSubtitle': 'Подзаголовок', + 'rewards.community.heroTitle': 'Заголовок', + 'rewards.community.joinDiscord': 'Присоединиться к Discord', 'rewards.community.loadingRewards': 'Загрузка наград…', 'rewards.community.locked': 'Разблокировано', 'rewards.community.retrying': 'Повтор…', 'rewards.community.rolesAndRewards': 'Роли и награды', 'rewards.community.streakDays': '{n}', 'rewards.community.syncPending': 'Синхронизация наград ожидает', - 'rewards.community.syncPendingDesc': 'Sync pending desc', + 'rewards.community.syncPendingDesc': 'Ожидание синхронизации', 'rewards.community.syncUnavailable': 'Синхронизация недоступна', 'rewards.community.tryAgain': 'Повтор…', 'rewards.community.unknown': 'Неизвестно', @@ -213,21 +213,21 @@ const ru4: TranslationMap = { 'rewards.coupon.colReward': 'Награда', 'rewards.coupon.colStatus': 'Статус', 'rewards.coupon.loadingHistory': 'Загрузка истории наград…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': 'Промокоды ещё не использованы.', 'rewards.coupon.pending': 'Ожидает', 'rewards.coupon.placeholder': 'Промокод', 'rewards.coupon.promoCredits': 'Промокредиты', 'rewards.coupon.recentRedemptions': 'Недавние активации', 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + '{code} принят. {amount} разблокируется после выполнения требуемого действия.', + 'rewards.coupon.redeemButton': 'Использовать код', + 'rewards.coupon.redeemSuccess': '{code} применён. {amount} добавлено к вашим кредитам.', 'rewards.coupon.redeemedCodes': 'Активированные коды', 'rewards.coupon.redeeming': 'Активация...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', - 'rewards.coupon.subtitle': 'Subtitle', + 'rewards.coupon.statusApplied': 'Применён', + 'rewards.coupon.statusPendingAction': 'Ожидает действия', + 'rewards.coupon.statusRedeemed': 'Использован', + 'rewards.coupon.subtitle': 'Подзаголовок', 'rewards.coupon.title': 'Активировать промокод', 'rewards.referralSection.activity': 'Реферальная активность', 'rewards.referralSection.apply': 'Применение…', @@ -240,9 +240,9 @@ const ru4: TranslationMap = { 'rewards.referralSection.copyCode': 'Скопировать код', 'rewards.referralSection.copyFailed': 'Не удалось скопировать', 'rewards.referralSection.haveCode': 'Есть реферальный код?', - 'rewards.referralSection.haveCodeDesc': 'Have code desc', + 'rewards.referralSection.haveCodeDesc': 'Есть код', 'rewards.referralSection.linked': 'Привязан', - 'rewards.referralSection.linkedCode': '(code {code})', + 'rewards.referralSection.linkedCode': '(код {code})', 'rewards.referralSection.loading': 'Загрузка реферальной программы…', 'rewards.referralSection.noReferrals': 'Рефералов нет', 'rewards.referralSection.pendingReferrals': 'Ожидающие рефералы', @@ -251,36 +251,36 @@ const ru4: TranslationMap = { 'rewards.referralSection.statusCompleted': 'Завершено', 'rewards.referralSection.statusExpired': 'Истёк срок', 'rewards.referralSection.statusJoined': 'Вступил', - 'rewards.referralSection.subtitle': 'Subtitle', + 'rewards.referralSection.subtitle': 'Подзаголовок', 'rewards.referralSection.title': 'Приглашай друзей, зарабатывай кредиты', 'rewards.referralSection.totalEarned': 'Заработано всего', 'rewards.referralSection.yourCode': 'Твой код', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': 'Добавить облачного провайдера', 'settings.ai.addProvider': 'Сохранение…', 'settings.ai.apiKeyFieldLabel': 'Поле API-ключа', 'settings.ai.apiKeyRequired': 'Вставь свой API-ключ для продолжения.', 'settings.ai.apiKeyStoredEncrypted': 'API-ключ хранится в зашифрованном виде', 'settings.ai.apiKeysEncrypted': 'auth-profiles.json', 'settings.ai.clearStoredKey': 'Очистить сохранённый ключ', - 'settings.ai.connectProvider': 'Connect provider', + 'settings.ai.connectProvider': 'Подключить провайдера', 'settings.ai.customRouting': 'Пользовательская маршрутизация', 'settings.ai.defaultResolvesTo': 'OpenHuman', 'settings.ai.discard': 'Отменить', - 'settings.ai.editProvider': 'Edit provider', + 'settings.ai.editProvider': 'Изменить провайдера', 'settings.ai.llmProviders': 'LLM-провайдеры', - 'settings.ai.llmProvidersDesc': 'Llm providers desc', + 'settings.ai.llmProvidersDesc': 'Описание провайдеров LLM', 'settings.ai.localOllama': 'Локально (Ollama)', 'settings.ai.modelLabel': 'Модель', 'settings.ai.noCustomProviders': 'Нет пользовательских провайдеров', 'settings.ai.providerLabel': 'Провайдер', 'settings.ai.routing': 'Маршрутизация', 'settings.ai.routingCustom': 'Пользовательская маршрутизация', - 'settings.ai.routingDefault': 'Default', - 'settings.ai.routingDesc': 'Routing desc', + 'settings.ai.routingDefault': 'По умолчанию', + 'settings.ai.routingDesc': 'Описание маршрутизации', 'settings.ai.saveChanges': 'Сохранение…', 'settings.ai.saving': 'Сохранение…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': 'несохранённое изменение', + 'settings.ai.unsavedChanges': 'несохранённые изменения', 'settings.ai.workloadGroupBackground': 'Фоновые задачи', 'settings.ai.workloadGroupChat': 'Чат', 'settings.autocomplete.appFilter.acceptSuggestion': 'Принять предложение', @@ -294,9 +294,9 @@ const ru4: TranslationMap = { 'settings.autocomplete.appFilter.runtime': 'Среда выполнения', 'settings.autocomplete.appFilter.test': 'Тест', 'settings.autocomplete.completionStyle.acceptedCompletion': - '{count} accepted completion stored — used to personalise future suggestions.', + 'Сохранено {count} принятое автозаполнение — используется для персонализации будущих подсказок.', 'settings.autocomplete.completionStyle.acceptedCompletions': - '{count} accepted completions stored — used to personalise future suggestions.', + 'Сохранено {count} принятых автозаполнений — используется для персонализации будущих подсказок.', 'settings.autocomplete.completionStyle.clearHistory': 'Очистка…', 'settings.autocomplete.completionStyle.clearing': 'Очистка…', 'settings.autocomplete.completionStyle.debounce': 'Задержка (ms)', @@ -321,42 +321,42 @@ const ru4: TranslationMap = { 'settings.billing.autoRecharge.saveSettings': 'Сохранение…', 'settings.billing.autoRecharge.saving': 'Сохранение…', 'settings.billing.autoRecharge.setDefault': ':', - 'settings.billing.autoRecharge.subtitle': 'Subtitle', + 'settings.billing.autoRecharge.subtitle': 'Подзаголовок', 'settings.billing.autoRecharge.title': 'Включить автопополнение', 'settings.billing.autoRecharge.toggleAriaLabel': 'Переключить автопополнение', 'settings.billing.autoRecharge.weeklyLimit': 'Еженедельный лимит расходов', - 'settings.billing.history.desc': 'Desc', + 'settings.billing.history.desc': 'Описание', 'settings.billing.history.empty': 'Пусто', 'settings.billing.history.openPortal': 'Открыть портал', 'settings.billing.history.posted': 'Проведено', - 'settings.billing.history.title': 'Title', + 'settings.billing.history.title': 'Заголовок', 'settings.billing.inferenceBudget.cycleEnds': 'Цикл заканчивается', 'settings.billing.inferenceBudget.exhausted': 'Исчерпан', 'settings.billing.inferenceBudget.loadError': 'Ошибка загрузки', - 'settings.billing.inferenceBudget.noBudgetDesc': 'No budget desc', + 'settings.billing.inferenceBudget.noBudgetDesc': 'Бюджет не задан', 'settings.billing.inferenceBudget.noRecurringBudget': 'Нет регулярного бюджета', 'settings.billing.inferenceBudget.remaining': 'Осталось', 'settings.billing.inferenceBudget.tenHourCap': 'Ограничение 10 часов', - 'settings.billing.inferenceBudget.title': 'Title', + 'settings.billing.inferenceBudget.title': 'Заголовок', 'settings.billing.payAsYouGo.available': 'Доступно', 'settings.billing.payAsYouGo.chargeCustomAmount': 'Открытие…', - 'settings.billing.payAsYouGo.chooseTopUpDesc': 'Choose top up desc', - 'settings.billing.payAsYouGo.chooseTopUpTitle': 'Choose top up title', - 'settings.billing.payAsYouGo.creditBalanceDesc': 'Credit balance desc', - 'settings.billing.payAsYouGo.creditBalanceTitle': 'Credit balance title', + 'settings.billing.payAsYouGo.chooseTopUpDesc': 'Описание выбора пополнения', + 'settings.billing.payAsYouGo.chooseTopUpTitle': 'Выберите сумму пополнения', + 'settings.billing.payAsYouGo.creditBalanceDesc': 'Описание баланса кредитов', + 'settings.billing.payAsYouGo.creditBalanceTitle': 'Баланс кредитов', 'settings.billing.payAsYouGo.customAmount': 'Произвольная сумма', 'settings.billing.payAsYouGo.enterAmount': 'Введи сумму', - 'settings.billing.payAsYouGo.opening': 'Opening', + 'settings.billing.payAsYouGo.opening': 'Открытие', 'settings.billing.payAsYouGo.promotionalCredits': 'Промокредиты', 'settings.billing.payAsYouGo.topUpBalance': 'Пополнение баланса', 'settings.billing.payAsYouGo.topUpCredits': 'Пополнить кредиты', 'settings.billing.payAsYouGo.unableToLoad': 'Не удалось загрузить баланс.', 'settings.billing.subscription.annual': 'Годовая', 'settings.billing.subscription.billedAnnually': 'Оплата раз в год', - 'settings.billing.subscription.chooseSubtitle': 'Choose subtitle', - 'settings.billing.subscription.chooseTitle': 'Choose title', - 'settings.billing.subscription.cryptoDesc': 'Crypto desc', - 'settings.billing.subscription.cryptoQuestion': 'Crypto question', + 'settings.billing.subscription.chooseSubtitle': 'Подзаголовок выбора', + 'settings.billing.subscription.chooseTitle': 'Заголовок выбора', + 'settings.billing.subscription.cryptoDesc': 'Описание крипто', + 'settings.billing.subscription.cryptoQuestion': 'Вопрос о крипто', 'settings.billing.subscription.current': 'Текущий', 'settings.billing.subscription.currentPlan': 'Текущий план', 'settings.billing.subscription.monthly': 'Ежемесячная', diff --git a/app/src/lib/i18n/chunks/ru-5.ts b/app/src/lib/i18n/chunks/ru-5.ts index e409d6872..25f88be3f 100644 --- a/app/src/lib/i18n/chunks/ru-5.ts +++ b/app/src/lib/i18n/chunks/ru-5.ts @@ -6,49 +6,50 @@ const ru5: TranslationMap = { 'settings.billing.subscription.upgrade': 'Улучшить', 'settings.billing.subscription.waiting': 'Ожидание', 'settings.billing.subscription.waitingPayment': 'Ожидание оплаты', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': 'API-ключ Composio сейчас сохранён на этом устройстве.', + 'settings.composio.apiKeyLabel': 'API-ключ Composio', + 'settings.composio.apiKeyStored': 'API-ключ сохранён', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': 'Переключено в режим Backend', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', + 'settings.composio.confirmItem1': 'Аккаунт на app.composio.dev с API-ключом', 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'Заново привязать каждую интеграцию через ваш личный аккаунт Composio', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + 'Примечание: триггеры Composio (вебхуки в реальном времени) пока не работают в прямом режиме — только синхронные вызовы инструментов', + 'settings.composio.confirmNeedItems': 'Вам понадобится:', + 'settings.composio.confirmSwitch': 'Понятно, переключить на «Прямой»', + 'settings.composio.confirmTitle': '⚠️ Переключение на прямой режим', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + 'Ваши существующие интеграции (Gmail, Slack, GitHub и т. д., привязанные через OpenHuman) не будут видны — они находятся в управляемом OpenHuman тенанте Composio.', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio интегрирует 250+ внешних приложений как инструменты, которые может вызывать ваш агент. Выберите способ маршрутизации этих вызовов.', 'settings.composio.modeDirect': 'Прямой (собственный API-ключ)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + 'Вызовы идут напрямую на backend.composio.dev. Суверенно и подходит для офлайн. Выполнение инструментов работает синхронно; вебхуки триггеров в реальном времени пока не маршрутизируются в прямом режиме (см. отдельную задачу).', 'settings.composio.modeManaged': 'Управляемый (OpenHuman управляет за тебя)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman проксирует вызовы инструментов через наш бэкенд (рекомендуется). Авторизация брокеруется; вам не нужно вставлять API-ключ Composio. Вебхуки полностью маршрутизируются.', 'settings.composio.routingMode': 'Режим маршрутизации', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': + 'Не удалось сохранить. Прямой режим требует непустой API-ключ.', 'settings.composio.saving': 'Сохранение…', - 'settings.composio.switching': 'Switching…', - 'settings.cron.jobs.desc': 'Desc', + 'settings.composio.switching': 'Переключение…', + 'settings.cron.jobs.desc': 'Описание', 'settings.cron.jobs.empty': 'Заданий по расписанию не найдено.', 'settings.cron.jobs.lastStatus': 'Последний статус', 'settings.cron.jobs.loading': 'Загрузка заданий...', - 'settings.cron.jobs.loadingRuns': 'Loading runs', + 'settings.cron.jobs.loadingRuns': 'Загрузка запусков', 'settings.cron.jobs.nextRun': 'Следующий запуск', 'settings.cron.jobs.pause': 'Приостановить', 'settings.cron.jobs.paused': 'Включено', 'settings.cron.jobs.recentRuns': 'Последние запуски', - 'settings.cron.jobs.removing': 'Removing', + 'settings.cron.jobs.removing': 'Удаление', 'settings.cron.jobs.resume': 'Возобновить', - 'settings.cron.jobs.runningNow': 'Running now', + 'settings.cron.jobs.runningNow': 'Выполняется сейчас', 'settings.cron.jobs.saving': 'Сохранение…', 'settings.cron.jobs.schedule': 'Расписание', 'settings.cron.jobs.title': 'Задания ядра по расписанию', - 'settings.cron.jobs.viewRuns': 'View runs', + 'settings.cron.jobs.viewRuns': 'Посмотреть запуски', 'settings.localModel.deviceCapability.active': 'Активно', 'settings.localModel.deviceCapability.appliedTier': 'Применённый уровень', 'settings.localModel.deviceCapability.applying': 'Применение', @@ -58,7 +59,7 @@ const ru5: TranslationMap = { 'settings.localModel.deviceCapability.customModelIds': 'Пользовательские ID моделей', 'settings.localModel.deviceCapability.detected': 'Обнаружено', 'settings.localModel.deviceCapability.disabled': 'Отключено', - 'settings.localModel.deviceCapability.disabledDesc': 'Disabled desc', + 'settings.localModel.deviceCapability.disabledDesc': 'Отключено', 'settings.localModel.deviceCapability.downloadingModels': '(загрузка моделей)', 'settings.localModel.deviceCapability.downloadingSetupDesc': 'Загрузка установщика OllamaSetup (~2 ГБ) и распаковка. При первой установке это может занять минуту.', @@ -67,10 +68,11 @@ const ru5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Установка Ollama не удалась', 'settings.localModel.deviceCapability.installFailedDesc': 'Установщик завершил работу до того, как Ollama стала готова к использованию. Нажми «Повторить» или установи вручную с ollama.com.', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': 'Сначала запустите Ollama.', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + 'Локальные уровни зависят от внешне управляемого эндпоинта Ollama. Запустите его самостоятельно, загрузите нужные модели и используйте «Отключено (облачный fallback)», пока среда выполнения недоступна.', + 'settings.localModel.deviceCapability.installOllamaFirst': + 'Сначала запустите Ollama, чтобы использовать этот уровень', 'settings.localModel.deviceCapability.installingOllama': 'Установка Ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': 'Загрузка информации об устройстве', 'settings.localModel.deviceCapability.localAiDisabled': @@ -92,8 +94,8 @@ const ru5: TranslationMap = { 'Введи любой запрос для тестирования локальной модели...', 'settings.localModel.download.quantizationPref': 'Предпочтения квантизации', 'settings.localModel.download.runEmbeddingTest': 'Выполнение...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': 'Запустить тест промпта', + 'settings.localModel.download.runSummaryTest': 'Запустить тест сводки', 'settings.localModel.download.runTranscriptionTest': 'Выполнение...', 'settings.localModel.download.runTtsTest': 'Выполнение...', 'settings.localModel.download.runVisionTest': 'Выполнение...', @@ -116,17 +118,17 @@ const ru5: TranslationMap = { 'settings.localModel.status.artifact': 'Артефакт', 'settings.localModel.status.backend': 'Бэкенд', 'settings.localModel.status.binary': 'Бинарный файл', - 'settings.localModel.status.bootstrapResume': 'Bootstrap / Resume', + 'settings.localModel.status.bootstrapResume': 'Инициализация / возобновление', 'settings.localModel.status.checking': 'Проверка...', 'settings.localModel.status.checkingOllama': 'Проверка Ollama', 'settings.localModel.status.customLocation': 'Пользовательский путь', - 'settings.localModel.status.customLocationDesc': 'Custom location desc', + 'settings.localModel.status.customLocationDesc': 'Описание пользовательского расположения', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + 'Нажмите «Запустить диагностику», чтобы убедиться, что Ollama запущен и модели установлены.', 'settings.localModel.status.downloadingUnknown': 'Загрузка (размер неизвестен)', 'settings.localModel.status.eta': 'ETA', 'settings.localModel.status.expectedModels': 'Ожидаемые модели', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': 'Принудительная переинициализация', 'settings.localModel.status.generationTps': 'Скорость генерации (TPS)', 'settings.localModel.status.hideErrorDetails': 'Скрыть детали ошибки', 'settings.localModel.status.installManually': 'Установить вручную', @@ -136,16 +138,16 @@ const ru5: TranslationMap = { 'settings.localModel.status.installing': 'Установка...', 'settings.localModel.status.installingOllama': 'Установка среды Ollama...', 'settings.localModel.status.issues': 'Проблемы', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': 'Найдено проблем: {count}', 'settings.localModel.status.lastLatency': 'Последняя задержка', 'settings.localModel.status.model': 'Модель', 'settings.localModel.status.notFound': 'Не найдено', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': 'Не запущено', 'settings.localModel.status.ollamaBinaryPath': 'Путь к бинарному файлу Ollama', 'settings.localModel.status.ollamaDiagnostics': 'Диагностика Ollama', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Среда выполнения Ollama недоступна', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman теперь рассматривает Ollama как внешнюю среду инференса. Запустите собственный сервер Ollama, загрузите нужные модели и направьте маршрутизацию нагрузки на него.', 'settings.localModel.status.progress': 'Прогресс', 'settings.localModel.status.provider': 'Провайдер', 'settings.localModel.status.retryBootstrap': 'Повторить Bootstrap', @@ -164,32 +166,32 @@ const ru5: TranslationMap = { 'settings.localModel.status.unavailable': 'Недоступно', 'settings.localModel.status.working': 'Работаю...', 'settings.mascot.active': 'Активно', - 'settings.mascot.characterDesc': 'Character desc', - 'settings.mascot.characterHeading': 'Character heading', - 'settings.mascot.colorDesc': 'Color desc', - 'settings.mascot.colorHeading': 'Color heading', + 'settings.mascot.characterDesc': 'Описание персонажа', + 'settings.mascot.characterHeading': 'Персонаж', + 'settings.mascot.colorDesc': 'Описание цвета', + 'settings.mascot.colorHeading': 'Цвет', 'settings.mascot.loadingLibrary': 'Загрузка библиотеки OpenHuman…', 'settings.mascot.localDefault': 'Локальный OpenHuman (по умолчанию)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': 'Персонажи OpenHuman пока недоступны', 'settings.mascot.noColorVariants': 'Нет цветовых вариантов', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': 'Рекомендуется', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + 'Разумное значение по умолчанию — хорошая непрерывность без лишних трат токенов на каждом запуске.', + 'settings.memoryWindow.balanced.label': 'Сбалансированный', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', + 'Сколько запомненного контекста OpenHuman добавляет в каждый новый запуск агента. Более широкие окна дают ощущение лучшей памяти о прошлых разговорах, но используют больше токенов — и стоят дороже — на каждом запуске.', + 'settings.memoryWindow.extended.badge': 'Больше контекста', 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', + 'Больше долгосрочной памяти на каждый запуск. Выше расход токенов за ход.', + 'settings.memoryWindow.extended.label': 'Расширенный', + 'settings.memoryWindow.maximum.badge': 'Самый дорогой', 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', + 'Самое большое безопасное окно. Лучшая непрерывность, заметно выше расход токенов на каждом запуске.', + 'settings.memoryWindow.maximum.label': 'Максимум', + 'settings.memoryWindow.minimal.badge': 'Самый дешёвый', 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'Самое маленькое окно памяти. Дешевле, быстрее, минимальная непрерывность между запусками.', + 'settings.memoryWindow.minimal.label': 'Минимальный', 'settings.memoryWindow.title': 'Окно долгосрочной памяти', 'settings.screenIntel.permissions.accessibility': 'Доступность', 'settings.screenIntel.permissions.grantHint': 'Подсказка по предоставлению', @@ -206,17 +208,17 @@ const ru5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': 'Запись экрана', 'settings.screenIntel.permissions.title': 'Разрешения', 'skills.card.moreActions': 'Ещё действия', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': 'Разрешённые инструменты', + 'skills.create.author': 'Автор', 'skills.create.authorPlaceholder': 'Твоё имя', 'skills.create.commaSeparated': '(через запятую)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': 'Создать навык', 'skills.create.createError': 'Не удалось создать навык', 'skills.create.creating': 'Создание…', - 'skills.create.description': 'Description', + 'skills.create.description': 'Описание', 'skills.create.descriptionPlaceholder': 'Что делает этот навык?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': 'Лицензия', + 'skills.create.name': 'Название', 'skills.create.namePlaceholder': 'напр. Trade Journal', 'skills.create.scope': 'Область', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -224,8 +226,8 @@ const ru5: TranslationMap = { 'Записывается в ~/.openhuman/skills//SKILL.md — доступно во всех рабочих пространствах.', 'skills.create.slugLabel': 'Slug', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': 'Теги', + 'skills.create.title': 'Новый навык', 'skills.detail.allowedTools': 'Разрешённые инструменты', 'skills.detail.author': 'Автор', 'skills.detail.bundledResources': 'Встроенные ресурсы', @@ -242,31 +244,31 @@ const ru5: TranslationMap = { 'skills.install.rawError': 'Необработанная ошибка', 'skills.install.timeoutHint': '(секунды, необязательно)', 'skills.install.timeoutLabel': 'Таймаут', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', - 'skills.meetingBots.bannerDesc': 'Banner desc', - 'skills.meetingBots.bannerTitle': 'Banner title', + 'skills.install.title': 'Установить навык по URL', + 'skills.install.urlLabel': 'URL навыка', + 'skills.meetingBots.bannerDesc': 'Описание баннера', + 'skills.meetingBots.bannerTitle': 'Заголовок баннера', 'skills.meetingBots.busyTitle': 'OpenHuman занят', - 'skills.meetingBots.comingSoon': 'Coming soon', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.comingSoon': 'Скоро', + 'skills.meetingBots.couldNotStartTitle': 'Не удалось запустить OpenHuman', 'skills.meetingBots.displayName': 'Отображаемое имя', 'skills.meetingBots.failedToStart': 'Не удалось запустить OpenHuman.', 'skills.meetingBots.joiningMessage': 'Он должен появиться как участник через несколько секунд.', 'skills.meetingBots.joiningTitle': 'OpenHuman подключается к встрече', 'skills.meetingBots.meetingLink': 'Ссылка на встречу', 'skills.meetingBots.modalAriaLabel': 'Отправить OpenHuman на встречу', - 'skills.meetingBots.modalDesc': 'Modal desc', + 'skills.meetingBots.modalDesc': 'Описание окна', 'skills.meetingBots.modalTitle': 'Отправить OpenHuman на встречу', 'skills.meetingBots.newBadge': 'Новое', - 'skills.meetingBots.sendTo': 'Send to', + 'skills.meetingBots.sendTo': 'Отправить', 'skills.meetingBots.starting': 'Запуск…', 'skills.resource.preview.closeAriaLabel': 'Закрыть предпросмотр', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': 'Не удалось показать превью', 'skills.resource.preview.loading': 'Загрузка предпросмотра…', 'skills.resource.tree.empty': 'Встроенных ресурсов нет.', 'skills.search.placeholder': 'Поиск', 'skills.setup.autocomplete.acceptKey': 'Клавиша принятия', - 'skills.setup.autocomplete.activeDesc': 'Active desc', + 'skills.setup.autocomplete.activeDesc': 'Активно', 'skills.setup.autocomplete.activeTitle': 'Автодополнение активно', 'skills.setup.autocomplete.customizeSettings': 'Настроить параметры', 'skills.setup.autocomplete.debounce': 'Задержка', @@ -280,7 +282,7 @@ const ru5: TranslationMap = { 'skills.setup.autocomplete.stylePreset': 'Пресет стиля', 'skills.setup.autocomplete.stylePresetValue': 'Сбалансированный (можно изменить позже)', 'skills.setup.autocomplete.title': 'Автодополнение текста', - 'skills.setup.screenIntel.activeDesc': 'Active desc', + 'skills.setup.screenIntel.activeDesc': 'Активно', 'skills.setup.screenIntel.activeTitle': 'Интеллект экрана включён', 'skills.setup.screenIntel.advancedSettings': 'Дополнительные настройки', 'skills.setup.screenIntel.allGranted': 'Все разрешения предоставлены', @@ -289,7 +291,8 @@ const ru5: TranslationMap = { 'skills.setup.screenIntel.deniedHint': 'После предоставления разрешений в Системных настройках нажми ниже для перезапуска и применения изменений.', 'skills.setup.screenIntel.enableBtn': 'Включение...', - 'skills.setup.screenIntel.enableDesc': 's on your screen and feed useful context into your agent', + 'skills.setup.screenIntel.enableDesc': + 'Видеть, что происходит на вашем экране, и передавать полезный контекст вашему агенту', 'skills.setup.screenIntel.enableError': 'Не удалось включить интеллект экрана', 'skills.setup.screenIntel.enabling': 'Включение...', 'skills.setup.screenIntel.grant': 'Открытие...', @@ -300,7 +303,7 @@ const ru5: TranslationMap = { 'skills.setup.screenIntel.permAccessibility': 'Доступность', 'skills.setup.screenIntel.permInputMonitoring': 'Мониторинг ввода', 'skills.setup.screenIntel.permScreenRecording': 'Запись экрана', - 'skills.setup.screenIntel.permissionsDesc': 'Permissions desc', + 'skills.setup.screenIntel.permissionsDesc': 'Описание разрешений', 'skills.setup.screenIntel.refreshStatus': 'Обновить статус', 'skills.setup.screenIntel.restartRefresh': 'Перезапуск...', 'skills.setup.screenIntel.restarting': 'Перезапуск...', @@ -315,7 +318,7 @@ const ru5: TranslationMap = { 'skills.setup.voice.activeTitle': 'Голосовой интеллект активен', 'skills.setup.voice.customizeSettings': 'Настроить параметры', 'skills.setup.voice.downloadSttBtn': 'Скачать STT-модель', - 'skills.setup.voice.enableDesc': 'Enable desc', + 'skills.setup.voice.enableDesc': 'Включить', 'skills.setup.voice.hotkey': 'Горячая клавиша', 'skills.setup.voice.startBtn': 'Запуск...', 'skills.setup.voice.startError': 'Не удалось запустить голосовой сервер', @@ -327,34 +330,34 @@ const ru5: TranslationMap = { 'skills.setup.voice.sttNotReadyDesc': 'Голосовой интеллект требует локальной модели Whisper для транскрипции. Скачай её в настройках локальной модели.', 'skills.setup.voice.sttReady': 'Модель распознавания речи готова', - 'skills.setup.voice.sttReturnHint': 'Stt return hint', + 'skills.setup.voice.sttReturnHint': 'Подсказка возврата STT', 'skills.setup.voice.title': 'Голосовой интеллект', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': 'Не удалось удалить', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + 'Это навсегда удалит каталог навыка и все его ресурсы. Агент перестанет видеть его на следующем ходу.', + 'skills.uninstall.title': 'Удалить', + 'skills.uninstall.uninstallBtn': 'Удалить', + 'skills.uninstall.uninstalling': 'Удаление…', 'upsell.global.limitMessage': 'Улучши план или пополни кредиты для продолжения', 'upsell.global.limitTitle': 'Ты', 'upsell.global.nearLimitMessage': 'Ты использовал {pct}% лимита. Улучши план для увеличения лимитов.', 'upsell.global.nearLimitTitle': 'Лимит использования близко', 'upsell.usageLimit.bodyBudget': - "You've hit your weekly limit.{reset} Upgrade your plan or top up credits to avoid limits.", + 'Вы достигли недельного лимита.{reset} Обновите план или пополните кредиты, чтобы избежать ограничений.', 'upsell.usageLimit.bodyRate': - "You've hit your 10-hour inference rate limit.{reset} Upgrade for higher limits.", + 'Вы достигли 10-часового лимита частоты инференса.{reset} Обновите план для более высоких лимитов.', 'upsell.usageLimit.heading': 'Лимит использования достигнут', 'upsell.usageLimit.notNow': 'Не сейчас', 'upsell.usageLimit.perWindow': '{amount}', 'upsell.usageLimit.planIncludes': '{plan}', - 'upsell.usageLimit.resetsIn': 'It resets {time}.', + 'upsell.usageLimit.resetsIn': 'Сбросится {time}.', 'upsell.usageLimit.upgradePlan': 'Улучшить план', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': 'Поехали!', + 'walkthrough.tooltip.next': 'Далее →', + 'walkthrough.tooltip.skip': 'Пропустить тур', + 'walkthrough.tooltip.stepCounter': '{n} из {total}', 'webhooks.activity.empty': 'Пусто', 'webhooks.activity.title': 'Последняя активность', 'webhooks.composioHistory.empty': 'Пусто', @@ -376,26 +379,27 @@ const ru5: TranslationMap = { 'webhooks.tunnels.removeEcho': 'Убрать эхо', 'webhooks.tunnels.title': 'Вебхук-туннели', 'webhooks.tunnels.toggleFailed': 'Не удалось переключить эхо', - 'composio.authExpired': 'Auth expired', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.authExpired': 'Срок авторизации истёк', + 'composio.reconnect': 'Переподключить', + 'composio.directModeRequiresKey': 'Не удалось сохранить. Прямой режим требует непустой API-ключ.', + 'composio.notYetRouted': 'пока не маршрутизируется', + 'composio.triggers.loading': 'Загрузка…', + 'conversations.taskKanban.todo': 'К выполнению', + 'settings.composio.loading': 'Загрузка…', + 'settings.mascot.noCharactersAvailable': 'Персонажи OpenHuman пока недоступны', + 'skills.uninstall.confirmTitle': 'Удалить {name}?', + 'conversations.taskKanban.blocked': 'Заблокировано', + 'conversations.taskKanban.done': 'Готово', + 'conversations.taskKanban.inProgress': 'В работе', + 'intelligence.memoryChunk.detail.copiedHint': 'скопировано', + 'settings.composio.notYetRouted': 'пока не маршрутизируется', + 'settings.localModel.download.manageExternal': + 'Управляйте этой моделью во внешней среде выполнения.', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', + 'Управляйте процессом Ollama и загрузкой моделей вне OpenHuman, затем повторите диагностику.', + 'settings.localModel.status.ollamaDocs': 'Документация Ollama', 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + 'для инструкций по настройке, затем повторите, когда среда выполнения станет доступна.', }; export default ru5; diff --git a/app/src/lib/i18n/chunks/zh-CN-1.ts b/app/src/lib/i18n/chunks/zh-CN-1.ts index 4eb2fe724..07148c23a 100644 --- a/app/src/lib/i18n/chunks/zh-CN-1.ts +++ b/app/src/lib/i18n/chunks/zh-CN-1.ts @@ -17,7 +17,7 @@ const zhCN1: TranslationMap = { 'common.edit': '编辑', 'common.create': '创建', 'common.search': '搜索', - 'common.loading': 'loading…', + 'common.loading': '加载中…', 'common.error': '错误', 'common.success': '成功', 'common.back': '返回', @@ -31,9 +31,9 @@ const zhCN1: TranslationMap = { 'common.yes': '是', 'common.no': '否', 'common.ok': '确定', - 'common.retry': 'Try again', + 'common.retry': '重试', 'common.copy': '复制', - 'common.copied': 'Copied', + 'common.copied': '已复制', 'common.learnMore': '了解更多', 'common.seeAll': '查看全部', 'common.dismiss': '忽略', diff --git a/app/src/lib/i18n/chunks/zh-CN-2.ts b/app/src/lib/i18n/chunks/zh-CN-2.ts index 458778550..5456142af 100644 --- a/app/src/lib/i18n/chunks/zh-CN-2.ts +++ b/app/src/lib/i18n/chunks/zh-CN-2.ts @@ -215,7 +215,7 @@ const zhCN2: TranslationMap = { 'composio.disableAllTriage': '禁用所有触发器的 AI 分类', 'composio.triggersStillRecorded': '触发器仍记录到历史记录中——不运行 LLM 轮次。', 'composio.disableSpecificIntegrations': '禁用特定集成的 AI 分类', - 'composio.settingsSaved': 'Settings saved', + 'composio.settingsSaved': '设置已保存', 'composio.saveFailed': '保存失败。请重试。', 'cron.title': '定时任务', 'cron.scheduledJobs': '计划任务', diff --git a/app/src/lib/i18n/chunks/zh-CN-3.ts b/app/src/lib/i18n/chunks/zh-CN-3.ts index 0ce17d201..d04ee4add 100644 --- a/app/src/lib/i18n/chunks/zh-CN-3.ts +++ b/app/src/lib/i18n/chunks/zh-CN-3.ts @@ -263,7 +263,7 @@ const zhCN3: TranslationMap = { 'app.connectionIndicator.coreOffline': '核心离线', 'app.connectionIndicator.disconnected': '已断开', 'app.connectionIndicator.offline': '离线', - 'app.connectionIndicator.reconnecting': 'Reconnecting…', + 'app.connectionIndicator.reconnecting': '重新连接中…', 'app.errorFallback.componentStack': '组件堆栈', 'app.errorFallback.downloadLatest': '下载最新版本', 'app.errorFallback.heading': '出现错误', @@ -273,7 +273,7 @@ const zhCN3: TranslationMap = { 'app.errorFallback.tryRecover': '尝试恢复', 'app.localAiDownload.installing': '安装中...', 'app.localAiDownload.preparing': '准备中...', - 'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in', + 'app.openhumanLink.accounts.continueWith': '使用 {label} 登录继续', 'app.openhumanLink.accounts.done': '完成', 'app.openhumanLink.accounts.intro': '简介', 'app.openhumanLink.accounts.webviewNote': '网页视图说明', @@ -300,9 +300,9 @@ const zhCN3: TranslationMap = { 'app.openhumanLink.notifications.promptHint': '提示', 'app.openhumanLink.notifications.retry': '重试测试通知', 'app.openhumanLink.notifications.send': '发送测试通知', - 'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}", + 'app.openhumanLink.notifications.sendFailed': '无法发送:{error}', 'app.openhumanLink.notifications.sent': - 'Test notification sent. If you didn’t receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.', + '测试通知已发送。如果未收到,请前往「系统设置 → 通知 → OpenHuman」,开启「允许通知」并将横幅样式设置为「持续」。', 'app.openhumanLink.skipForNow': '暂时跳过', 'app.openhumanLink.telegramUnavailable': 'Telegram 不可用', 'app.openhumanLink.title.accounts': '连接你的应用', @@ -314,7 +314,7 @@ const zhCN3: TranslationMap = { 'app.persistRehydration.heading': '加载中', 'app.persistRehydration.resetCta': '重置中…', 'app.persistRehydration.resetting': '重置中…', - 'app.routeLoading.initializing': 'Initializing OpenHuman...', + 'app.routeLoading.initializing': '正在初始化 OpenHuman...', 'app.update.currentlyOn': '{version}', 'app.update.errorFallback': '更新时出现问题。', 'app.update.header.default': '更新', @@ -350,7 +350,7 @@ const zhCN3: TranslationMap = { 'channels.discord.picker.selectChannel': '选择频道', 'channels.discord.picker.selectServer': '选择服务器', 'channels.discord.picker.server': '服务器', - 'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection', + 'channels.discord.picker.serverChannelSelection': '服务器与频道选择', 'channels.discord.savedRestartRequired': '频道已保存。重启应用以激活。', 'channels.telegram.connect': '连接', 'channels.telegram.managedDmConnecting': '正在连接私信', diff --git a/app/src/lib/i18n/chunks/zh-CN-4.ts b/app/src/lib/i18n/chunks/zh-CN-4.ts index 7b50e50a3..16ae7501b 100644 --- a/app/src/lib/i18n/chunks/zh-CN-4.ts +++ b/app/src/lib/i18n/chunks/zh-CN-4.ts @@ -2,103 +2,103 @@ import type { TranslationMap } from '../types'; // Simplified Chinese (简体中文) chunk 4/5. Translated from chunks/en-4.ts. const zhCN4: TranslationMap = { - 'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe', - 'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.', + 'chat.unsubscribeApproval.approve': '批准并退订', + 'chat.unsubscribeApproval.approved': '✓ 已成功退订。', 'chat.unsubscribeApproval.denied': '✕ 请求已拒绝。', 'chat.unsubscribeApproval.deny': '拒绝', 'chat.unsubscribeApproval.processing': '处理中...', - 'chat.unsubscribeApproval.title': 'Unsubscribe Request', + 'chat.unsubscribeApproval.title': '退订请求', 'commandPalette.ariaLabel': '命令面板', 'commandPalette.description': '描述', 'commandPalette.label': '命令', 'commandPalette.noResults': '无结果', 'commandPalette.placeholder': '输入命令或搜索…', 'commandPalette.searchAria': '搜索命令', - 'commandPalette.shortcutHint': 'Press ? for all shortcuts', + 'commandPalette.shortcutHint': '按 ? 查看所有快捷键', 'commandPalette.title': '命令面板', 'composio.connect.additionalConfigRequired': '需要额外配置', 'composio.connect.atlassianSubdomainHint': 'acme', 'composio.connect.atlassianSubdomainLabel': 'Atlassian 子域名', - 'composio.connect.connect': 'Connect', + 'composio.connect.connect': '连接', 'composio.connect.connectionFailed': '连接失败。', 'composio.connect.disconnectFailed': '断开连接失败:{msg}', 'composio.connect.disconnecting': '断开中…', - 'composio.connect.idleDescription': 'Connect your', + 'composio.connect.idleDescription': '连接你的', 'composio.connect.idleDescriptionSuffix': - "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.", - 'composio.connect.isConnected': 'is connected.', - 'composio.connect.manage': 'Manage', - 'composio.connect.needsSubdomain': 'To connect', + '账户。我们会打开浏览器窗口,你在其中授权后,应用会自动检测到该连接。', + 'composio.connect.isConnected': '已连接。', + 'composio.connect.manage': '管理', + 'composio.connect.needsSubdomain': '要连接', 'composio.connect.needsSubdomainSuffix': - 'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.', - 'composio.connect.oauthComplete': 'OAuth to complete…', + '请输入你的 Atlassian 子域名(例如 acme.atlassian.net 中的 acme),然后重试。', + 'composio.connect.oauthComplete': '等待完成 OAuth…', 'composio.connect.oauthTimeout': 'OAuth 超时', 'composio.connect.permissions': '权限', 'composio.connect.permissionsDefault': '默认启用读写权限', - 'composio.connect.permissionsNote': 'can expose', + 'composio.connect.permissionsNote': '可暴露', 'composio.connect.permissionsNoteSuffix': - "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.", + 'OpenHuman 自身的智能体权限通过下方的读取、写入和管理员开关控制。', 'composio.connect.reopenBrowser': '重新打开浏览器', 'composio.connect.requestingUrl': '正在请求连接 URL…', 'composio.connect.retryConnection': '重试连接', 'composio.connect.scopeLoadError': '无法加载权限范围偏好:{msg}', 'composio.connect.scopeSaveError': '无法保存 {key} 权限范围:{msg}', 'composio.connect.subdomainInvalid': - 'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.', + '仅输入短子域名(例如 "acme"),而非完整 URL。只能包含字母、数字和连字符。', 'composio.connect.subdomainRequired': '请输入你的 Atlassian 子域名以继续。', 'composio.connect.wabaIdLabel': 'WhatsApp 企业账户 ID', 'composio.connect.wabaIdRequired': '请输入你的 WhatsApp 企业账户 ID(WABA ID)以继续。', - 'composio.connect.waitingFor': 'Waiting for', + 'composio.connect.waitingFor': '等待中', 'composio.connect.waitingHint': '请在浏览器中完成授权', 'composio.triggers.heading': '触发器', - 'composio.triggers.listenFrom': 'Listen for events from', - 'composio.triggers.loadError': "Couldn't load triggers", + 'composio.triggers.listenFrom': '监听来自以下的事件', + 'composio.triggers.loadError': '无法加载触发器', 'composio.triggers.needsConfiguration': '需要配置', - 'composio.triggers.noneAvailable': 'No triggers are currently available for', + 'composio.triggers.noneAvailable': '当前没有可用的触发器:', 'conversations.taskKanban.moveLeft': '向左移动', 'conversations.taskKanban.moveRight': '向右移动', 'conversations.taskKanban.title': '任务', - 'conversations.toolTimeline.turn': 'turn', + 'conversations.toolTimeline.turn': '轮次', 'conversations.toolTimeline.workerThread': '工作线程', 'daemon.serviceBlockingGate.body': '核心服务不可用,请等待或下载最新版本。', 'daemon.serviceBlockingGate.downloadHint': '下载最新版本', - 'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version', - 'daemon.serviceBlockingGate.retryCore': 'Retry Core', + 'daemon.serviceBlockingGate.downloadLatest': '下载最新版本', + 'daemon.serviceBlockingGate.retryCore': '重试 Core', 'daemon.serviceBlockingGate.retryFailed': '重试失败。请下载最新应用版本后重试。', 'daemon.serviceBlockingGate.retrying': '重试中...', 'daemon.serviceBlockingGate.title': 'OpenHuman 核心不可用', 'home.banners.discordSubtitle': '加入我们,获取最新资讯', 'home.banners.discordTitle': '加入我们的 Discord', 'home.banners.earlyBirdDismiss': '忽略早鸟横幅', - 'home.banners.earlyBirdFirstSub': 'first subscription.', + 'home.banners.earlyBirdFirstSub': '首次订阅。', 'home.banners.earlyBirdOn': '早鸟优惠进行中', - 'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.', + 'home.banners.earlyBirdTitle': '前 1,000 名用户享 6 折优惠。', 'home.banners.earlyBirdUseCode': '使用早鸟码', - 'home.banners.getSubscription': 'get a subscription', + 'home.banners.getSubscription': '获取订阅', 'home.banners.promoCreditsBody': '你的促销配额已到账', 'home.banners.promoCreditsTitle': '{amount}', 'home.banners.promoCreditsUsage': '查看用量详情', 'intelligence.memoryChunk.detail.chunk': '片段', 'intelligence.memoryChunk.detail.copyChunkId': '复制片段 ID', - 'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024dim', + 'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024 维', 'intelligence.memoryChunk.detail.noEmbedding': '无嵌入', 'intelligence.memoryChunk.letterhead.from': '来自', 'intelligence.memoryChunk.letterhead.to': '至', - 'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk', - 'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks', + 'intelligence.memoryChunk.mentioned.chunkOne': '1 个片段', + 'intelligence.memoryChunk.mentioned.chunkOther': '{count} 个片段', 'intelligence.memoryChunk.mentioned.heading': '提及', - 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent', - 'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}', - 'intelligence.memoryChunk.scoreBars.dropped': 'dropped', + 'intelligence.memoryChunk.scoreBars.ariaScore': '{name} 得分 {pct}%', + 'intelligence.memoryChunk.scoreBars.atThreshold': '阈值 {threshold}', + 'intelligence.memoryChunk.scoreBars.dropped': '已丢弃', 'intelligence.memoryChunk.scoreBars.heading': '保留原因', - 'intelligence.memoryChunk.scoreBars.kept': 'kept', - 'intelligence.memoryText.entityTypePrefix': 'Entity type', + 'intelligence.memoryChunk.scoreBars.kept': '已保留', + 'intelligence.memoryText.entityTypePrefix': '实体类型', 'intelligence.screenDebug.active': '活跃', 'intelligence.screenDebug.app': '应用', 'intelligence.screenDebug.bounds': '边界', 'intelligence.screenDebug.captureAlt': '捕获测试结果', - 'intelligence.screenDebug.captureFailed': 'Failed', - 'intelligence.screenDebug.captureSuccess': 'Success', + 'intelligence.screenDebug.captureFailed': '失败', + 'intelligence.screenDebug.captureSuccess': '成功', 'intelligence.screenDebug.captureTest': '捕获测试', 'intelligence.screenDebug.capturing': '捕获中', 'intelligence.screenDebug.frames': '帧数', @@ -120,12 +120,12 @@ const zhCN4: TranslationMap = { 'intelligence.screenDebug.unknown': '未知', 'intelligence.screenDebug.visionQueue': '视觉队列', 'intelligence.screenDebug.visionState': '视觉状态', - 'intelligence.tasks.activeBoardOne': '1 active board across conversations', - 'intelligence.tasks.activeBoardOther': '{count} active boards across conversations', + 'intelligence.tasks.activeBoardOne': '1 个跨对话的活跃看板', + 'intelligence.tasks.activeBoardOther': '{count} 个跨对话的活跃看板', 'intelligence.tasks.empty': '暂无智能体任务看板', 'intelligence.tasks.emptyHint': '完成一项对话后,任务看板将出现在这里。', 'intelligence.tasks.failedToLoad': '加载失败', - 'intelligence.tasks.live': 'live', + 'intelligence.tasks.live': '实时', 'intelligence.tasks.loadingBoards': '正在加载任务看板…', 'intelligence.tasks.threadPrefix': '对话', 'notifications.card.dismiss': '忽略通知', @@ -141,7 +141,7 @@ const zhCN4: TranslationMap = { 'onboarding.contextGathering.buildingProfile': '正在构建你的档案...', 'onboarding.contextGathering.continueToChat': '前往对话', 'onboarding.contextGathering.errorDesc': - "We couldn't build your full profile right now, but that's okay — you can continue and your profile will build over time.", + '我们暂时无法构建你的完整资料,但没关系——你可以继续,资料会随时间逐步完善。', 'onboarding.contextGathering.title': '上下文收集', 'openhuman.team_list_teams': '团队列表', 'overlay.ariaAttention': '注意消息', @@ -179,20 +179,20 @@ const zhCN4: TranslationMap = { 'privacy.dataKind.diagnostics': '诊断信息', 'privacy.dataKind.metadata': '元数据', 'privacy.dataKind.raw': '原始数据', - 'privacy.whatLeaves.link.label': 'What leaves my computer?', - 'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked', + 'privacy.whatLeaves.link.label': '哪些数据会离开我的电脑?', + 'rewards.community.achievementsUnlocked': '已解锁 {unlocked}/{total} 项成就', 'rewards.community.connectDiscord': '连接 Discord', 'rewards.community.cumulativeTokens': '累计令牌', 'rewards.community.currentStreak': '当前连续天数', 'rewards.community.discordLinkedNotInGuild': '已关联 Discord 但未加入服务器', - 'rewards.community.discordMember': 'Joined the server', + 'rewards.community.discordMember': '已加入服务器', 'rewards.community.discordNotLinked': '未关联 Discord', 'rewards.community.discordServer': 'Discord 服务器', 'rewards.community.discordStatusUnavailable': 'Discord 状态不可用', 'rewards.community.discordWaiting': '等待 Discord 验证', 'rewards.community.heroSubtitle': '完成任务,赚取奖励', 'rewards.community.heroTitle': '社区奖励', - 'rewards.community.joinDiscord': 'Join Discord', + 'rewards.community.joinDiscord': '加入 Discord', 'rewards.community.loadingRewards': '正在加载奖励…', 'rewards.community.locked': '已解锁', 'rewards.community.retrying': '重试中…', @@ -210,20 +210,19 @@ const zhCN4: TranslationMap = { 'rewards.coupon.colReward': '奖励', 'rewards.coupon.colStatus': '状态', 'rewards.coupon.loadingHistory': '正在加载奖励历史…', - 'rewards.coupon.noCodes': 'No reward codes redeemed yet.', + 'rewards.coupon.noCodes': '尚未兑换任何奖励码。', 'rewards.coupon.pending': '处理中', 'rewards.coupon.placeholder': '优惠码', 'rewards.coupon.promoCredits': '促销配额', 'rewards.coupon.recentRedemptions': '最近兑换', - 'rewards.coupon.redeemAccepted': - '{code} accepted. {amount} will unlock after the required action is completed.', - 'rewards.coupon.redeemButton': 'Redeem Code', - 'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.', + 'rewards.coupon.redeemAccepted': '{code} 已接受。完成所需操作后将解锁 {amount}。', + 'rewards.coupon.redeemButton': '兑换码', + 'rewards.coupon.redeemSuccess': '{code} 已兑换。{amount} 已添加至你的额度。', 'rewards.coupon.redeemedCodes': '已兑换代码', 'rewards.coupon.redeeming': '兑换中...', - 'rewards.coupon.statusApplied': 'Applied', - 'rewards.coupon.statusPendingAction': 'Pending action', - 'rewards.coupon.statusRedeemed': 'Redeemed', + 'rewards.coupon.statusApplied': '已应用', + 'rewards.coupon.statusPendingAction': '待操作', + 'rewards.coupon.statusRedeemed': '已兑换', 'rewards.coupon.subtitle': '输入优惠码以兑换奖励', 'rewards.coupon.title': '兑换优惠码', 'rewards.referralSection.activity': '邀请活动', @@ -252,7 +251,7 @@ const zhCN4: TranslationMap = { 'rewards.referralSection.title': '邀请好友,赚取配额', 'rewards.referralSection.totalEarned': '总获得', 'rewards.referralSection.yourCode': '你的邀请码', - 'settings.ai.addCloudProvider': 'Add cloud provider', + 'settings.ai.addCloudProvider': '添加云端提供商', 'settings.ai.addProvider': '保存中…', 'settings.ai.apiKeyFieldLabel': 'API 密钥', 'settings.ai.apiKeyRequired': '请粘贴你的 API 密钥以继续。', @@ -272,12 +271,12 @@ const zhCN4: TranslationMap = { 'settings.ai.providerLabel': '提供商', 'settings.ai.routing': '路由', 'settings.ai.routingCustom': '自定义路由', - 'settings.ai.routingDefault': 'Default', + 'settings.ai.routingDefault': '默认', 'settings.ai.routingDesc': '为不同工作负载选择路由策略', 'settings.ai.saveChanges': '保存中…', 'settings.ai.saving': '保存中…', - 'settings.ai.unsavedChange': 'unsaved change', - 'settings.ai.unsavedChanges': 'unsaved changes', + 'settings.ai.unsavedChange': '未保存的更改', + 'settings.ai.unsavedChanges': '未保存的更改', 'settings.ai.workloadGroupBackground': '后台工作负载', 'settings.ai.workloadGroupChat': '对话工作负载', 'settings.autocomplete.appFilter.acceptSuggestion': '接受建议', diff --git a/app/src/lib/i18n/chunks/zh-CN-5.ts b/app/src/lib/i18n/chunks/zh-CN-5.ts index 00cabe2d3..a0ffb8560 100644 --- a/app/src/lib/i18n/chunks/zh-CN-5.ts +++ b/app/src/lib/i18n/chunks/zh-CN-5.ts @@ -6,33 +6,32 @@ const zhCN5: TranslationMap = { 'settings.billing.subscription.upgrade': '升级', 'settings.billing.subscription.waiting': '等待中', 'settings.billing.subscription.waitingPayment': '等待支付', - 'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.', - 'settings.composio.apiKeyLabel': 'Composio API key', - 'settings.composio.apiKeyStored': 'API key stored', + 'settings.composio.apiKeyDesc': '当前此设备上已存储一个 Composio API 密钥。', + 'settings.composio.apiKeyLabel': 'Composio API 密钥', + 'settings.composio.apiKeyStored': 'API 密钥已存储', 'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••', 'settings.composio.clearedToBackend': '已切换到后端模式', - 'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key', - 'settings.composio.confirmItem2': - 'To re-link each integration through your personal Composio account', + 'settings.composio.confirmItem1': '在 app.composio.dev 上拥有带 API 密钥的账户', + 'settings.composio.confirmItem2': '通过你的个人 Composio 账户重新关联每个集成', 'settings.composio.confirmItem3': - "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls", - 'settings.composio.confirmNeedItems': "You'll need:", - 'settings.composio.confirmSwitch': 'I understand, switch to Direct', - 'settings.composio.confirmTitle': '⚠️ Switching to Direct mode', + '注意:Composio 触发器(实时 Webhook)在直连模式下尚不可用——仅支持同步工具调用', + 'settings.composio.confirmNeedItems': '你需要:', + 'settings.composio.confirmSwitch': '我已了解,切换到直连', + 'settings.composio.confirmTitle': '⚠️ 切换到直连模式', 'settings.composio.confirmWarning': - "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.", + '你现有的集成(通过 OpenHuman 关联的 Gmail、Slack、GitHub 等)将不可见——它们存放在 OpenHuman 托管的 Composio 租户中。', 'settings.composio.intro': - 'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.', + 'Composio 集成了 250+ 外部应用作为智能体可调用的工具。请选择这些工具调用的路由方式。', 'settings.composio.modeDirect': '直连(自带 API 密钥)', 'settings.composio.modeDirectDesc': - 'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).', + '调用直接发送到 backend.composio.dev。自主可控 / 适合离线场景。工具同步执行;实时触发器 Webhook 目前在直连模式下尚未路由(后续问题)。', 'settings.composio.modeManaged': '托管(由 OpenHuman 管理)', 'settings.composio.modeManagedDesc': - 'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.', + 'OpenHuman 通过我们的后端代理工具调用(推荐)。认证由我们处理,你无需粘贴 Composio API 密钥。Webhook 完全路由。', 'settings.composio.routingMode': '路由模式', - 'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.', + 'settings.composio.saveErrorNoKey': '保存失败。直连模式需要非空的 API 密钥。', 'settings.composio.saving': '保存中…', - 'settings.composio.switching': 'Switching…', + 'settings.composio.switching': '切换中…', 'settings.cron.jobs.desc': '管理核心调度器中的定时任务', 'settings.cron.jobs.empty': '未找到核心定时任务。', 'settings.cron.jobs.lastStatus': '上次状态', @@ -67,10 +66,10 @@ const zhCN5: TranslationMap = { 'settings.localModel.deviceCapability.installFailed': 'Ollama 安装失败', 'settings.localModel.deviceCapability.installFailedDesc': '安装程序在 Ollama 可用之前退出。点击重试,或从 ollama.com 手动安装。', - 'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.', + 'settings.localModel.deviceCapability.installFirst': '请先运行 Ollama。', 'settings.localModel.deviceCapability.installFirstDesc': - 'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.', - 'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier', + '本地层级依赖外部托管的 Ollama 端点。请自行启动它,拉取所需模型,并在运行时可达前继续使用「已禁用(云端回退)」。', + 'settings.localModel.deviceCapability.installOllamaFirst': '请先运行 Ollama 以使用此层级', 'settings.localModel.deviceCapability.installingOllama': '正在安装 Ollama', 'settings.localModel.deviceCapability.loadingDeviceInfo': '正在加载设备信息', 'settings.localModel.deviceCapability.localAiDisabled': '本地 AI 已禁用 — 使用云端回退。', @@ -90,8 +89,8 @@ const zhCN5: TranslationMap = { 'settings.localModel.download.promptPlaceholder': '输入任意提示词并在本地模型上运行...', 'settings.localModel.download.quantizationPref': '量化偏好', 'settings.localModel.download.runEmbeddingTest': '运行中...', - 'settings.localModel.download.runPromptTest': 'Run Prompt Test', - 'settings.localModel.download.runSummaryTest': 'Run Summary Test', + 'settings.localModel.download.runPromptTest': '运行提示测试', + 'settings.localModel.download.runSummaryTest': '运行摘要测试', 'settings.localModel.download.runTranscriptionTest': '运行中...', 'settings.localModel.download.runTtsTest': '运行中...', 'settings.localModel.download.runVisionTest': '运行中...', @@ -119,11 +118,11 @@ const zhCN5: TranslationMap = { 'settings.localModel.status.customLocation': '自定义位置', 'settings.localModel.status.customLocationDesc': '自定义 Ollama 安装路径', 'settings.localModel.status.diagnosticsHint': - 'Click "Run Diagnostics" to verify Ollama is running and models are installed.', + '点击「运行诊断」以验证 Ollama 是否正在运行以及模型是否已安装。', 'settings.localModel.status.downloadingUnknown': '下载中(大小未知)', 'settings.localModel.status.eta': '预计完成时间', 'settings.localModel.status.expectedModels': '预期模型', - 'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap', + 'settings.localModel.status.forceRebootstrap': '强制重新引导', 'settings.localModel.status.generationTps': '生成 TPS', 'settings.localModel.status.hideErrorDetails': '隐藏错误详情', 'settings.localModel.status.installManually': '手动安装', @@ -133,16 +132,16 @@ const zhCN5: TranslationMap = { 'settings.localModel.status.installing': '安装中...', 'settings.localModel.status.installingOllama': '正在安装 Ollama 运行时...', 'settings.localModel.status.issues': '问题', - 'settings.localModel.status.issuesFound': '{count} issue(s) found', + 'settings.localModel.status.issuesFound': '发现 {count} 个问题', 'settings.localModel.status.lastLatency': '最近延迟', 'settings.localModel.status.model': '模型', 'settings.localModel.status.notFound': '未找到', - 'settings.localModel.status.notRunning': 'Not running', + 'settings.localModel.status.notRunning': '未运行', 'settings.localModel.status.ollamaBinaryPath': 'Ollama 二进制路径', 'settings.localModel.status.ollamaDiagnostics': 'Ollama 诊断', - 'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable', + 'settings.localModel.status.ollamaNotInstalled': 'Ollama 运行时不可用', 'settings.localModel.status.ollamaNotInstalledDesc': - 'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.', + 'OpenHuman 现在将 Ollama 视为外部推理运行时。请启动你自己的 Ollama 服务器,拉取所需模型,并将工作负载路由指向它。', 'settings.localModel.status.progress': '进度', 'settings.localModel.status.provider': '提供商', 'settings.localModel.status.retryBootstrap': '重试引导', @@ -167,26 +166,23 @@ const zhCN5: TranslationMap = { 'settings.mascot.colorHeading': '颜色', 'settings.mascot.loadingLibrary': '正在加载 OpenHuman 库…', 'settings.mascot.localDefault': '本地 OpenHuman(默认)', - 'settings.mascot.noCharacters': 'No OpenHuman characters are available yet', + 'settings.mascot.noCharacters': '暂无可用的 OpenHuman 角色', 'settings.mascot.noColorVariants': '无颜色变体', - 'settings.memoryWindow.balanced.badge': 'Recommended', + 'settings.memoryWindow.balanced.badge': '推荐', 'settings.memoryWindow.balanced.hint': - 'Sensible default — good continuity without burning extra tokens on every run.', - 'settings.memoryWindow.balanced.label': 'Balanced', + '合理的默认值——在不为每次运行消耗额外 token 的情况下保持良好的连贯性。', + 'settings.memoryWindow.balanced.label': '均衡', 'settings.memoryWindow.description': - 'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.', - 'settings.memoryWindow.extended.badge': 'More context', - 'settings.memoryWindow.extended.hint': - 'More long-term memory injected into each run. Higher token cost per turn.', - 'settings.memoryWindow.extended.label': 'Extended', - 'settings.memoryWindow.maximum.badge': 'Highest cost', - 'settings.memoryWindow.maximum.hint': - 'The largest safe window. Best continuity, meaningfully higher token bill on every run.', - 'settings.memoryWindow.maximum.label': 'Maximum', - 'settings.memoryWindow.minimal.badge': 'Cheapest', - 'settings.memoryWindow.minimal.hint': - 'Smallest memory window. Cheapest, fastest, least continuity between runs.', - 'settings.memoryWindow.minimal.label': 'Minimal', + 'OpenHuman 在每次新的智能体运行中注入多少记忆上下文。更大的窗口对过往对话更有感知,但每次运行会消耗更多 token,成本也更高。', + 'settings.memoryWindow.extended.badge': '更多上下文', + 'settings.memoryWindow.extended.hint': '向每次运行注入更多长期记忆。每轮 token 成本更高。', + 'settings.memoryWindow.extended.label': '扩展', + 'settings.memoryWindow.maximum.badge': '最高成本', + 'settings.memoryWindow.maximum.hint': '最大安全窗口。连贯性最佳,每次运行的 token 账单显著更高。', + 'settings.memoryWindow.maximum.label': '最大', + 'settings.memoryWindow.minimal.badge': '最便宜', + 'settings.memoryWindow.minimal.hint': '最小记忆窗口。最便宜、最快,但跨运行的连贯性最弱。', + 'settings.memoryWindow.minimal.label': '最小', 'settings.memoryWindow.title': '长期记忆窗口', 'settings.screenIntel.permissions.accessibility': '辅助功能', 'settings.screenIntel.permissions.grantHint': '在系统设置中授权后,点击下方刷新', @@ -203,17 +199,17 @@ const zhCN5: TranslationMap = { 'settings.screenIntel.permissions.screenRecording': '屏幕录制', 'settings.screenIntel.permissions.title': '权限', 'skills.card.moreActions': '更多操作', - 'skills.create.allowedTools': 'Allowed tools', - 'skills.create.author': 'Author', + 'skills.create.allowedTools': '允许的工具', + 'skills.create.author': '作者', 'skills.create.authorPlaceholder': '你的名字', 'skills.create.commaSeparated': '(逗号分隔)', - 'skills.create.createBtn': 'Create skill', + 'skills.create.createBtn': '创建技能', 'skills.create.createError': '无法创建技能', 'skills.create.creating': '创建中…', - 'skills.create.description': 'Description', + 'skills.create.description': '描述', 'skills.create.descriptionPlaceholder': '这个技能做什么?', - 'skills.create.license': 'License', - 'skills.create.name': 'Name', + 'skills.create.license': '许可证', + 'skills.create.name': '名称', 'skills.create.namePlaceholder': '例如:交易日志', 'skills.create.scope': '范围', 'skills.create.scopeProjectHint': '/.openhuman/skills/', @@ -221,8 +217,8 @@ const zhCN5: TranslationMap = { '写入 ~/.openhuman/skills//SKILL.md — 在所有工作空间中可用。', 'skills.create.slugLabel': '标识符', 'skills.create.subtitle': 'SKILL.md', - 'skills.create.tags': 'Tags', - 'skills.create.title': 'New skill', + 'skills.create.tags': '标签', + 'skills.create.title': '新建技能', 'skills.detail.allowedTools': '允许的工具', 'skills.detail.author': '作者', 'skills.detail.bundledResources': '捆绑资源', @@ -239,13 +235,13 @@ const zhCN5: TranslationMap = { 'skills.install.rawError': '原始错误', 'skills.install.timeoutHint': '(秒,可选)', 'skills.install.timeoutLabel': '超时', - 'skills.install.title': 'Install skill from URL', - 'skills.install.urlLabel': 'Skill URL', + 'skills.install.title': '从 URL 安装技能', + 'skills.install.urlLabel': '技能 URL', 'skills.meetingBots.bannerDesc': '让 OpenHuman 加入你的会议,自动记录摘要', 'skills.meetingBots.bannerTitle': '会议机器人', 'skills.meetingBots.busyTitle': 'OpenHuman 正忙', 'skills.meetingBots.comingSoon': '即将推出', - 'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman', + 'skills.meetingBots.couldNotStartTitle': '无法启动 OpenHuman', 'skills.meetingBots.displayName': '显示名称', 'skills.meetingBots.failedToStart': '启动 OpenHuman 失败。', 'skills.meetingBots.joiningMessage': '它应该在几秒钟内作为参会者出现。', @@ -258,7 +254,7 @@ const zhCN5: TranslationMap = { 'skills.meetingBots.sendTo': '发送到会议', 'skills.meetingBots.starting': '启动中…', 'skills.resource.preview.closeAriaLabel': '关闭预览', - 'skills.resource.preview.failed': 'Preview failed', + 'skills.resource.preview.failed': '预览失败', 'skills.resource.preview.loading': '加载预览中…', 'skills.resource.tree.empty': '无捆绑资源。', 'skills.search.placeholder': '搜索技能...', @@ -325,12 +321,12 @@ const zhCN5: TranslationMap = { 'skills.setup.voice.sttReady': '语音转文本模型已就绪', 'skills.setup.voice.sttReturnHint': '完成后将返回此页面', 'skills.setup.voice.title': '语音智能', - 'skills.uninstall.couldNotUninstall': 'Could not uninstall', + 'skills.uninstall.couldNotUninstall': '无法卸载', 'skills.uninstall.description': - 'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.', - 'skills.uninstall.title': 'Uninstall', - 'skills.uninstall.uninstallBtn': 'Uninstall', - 'skills.uninstall.uninstalling': 'Uninstalling…', + '这将永久删除技能目录及其所有捆绑资源。智能体将在下一轮停止看到它。', + 'skills.uninstall.title': '卸载', + 'skills.uninstall.uninstallBtn': '卸载', + 'skills.uninstall.uninstalling': '卸载中…', 'upsell.global.limitMessage': '升级方案或充值配额以继续使用', 'upsell.global.limitTitle': '已达使用限制', 'upsell.global.nearLimitMessage': '你已使用了 {pct}% 的使用限制。升级以获得更高限额。', @@ -344,10 +340,10 @@ const zhCN5: TranslationMap = { 'upsell.usageLimit.resetsIn': '重置时间', 'upsell.usageLimit.upgradePlan': '升级方案', 'upsell.usageLimit.weeklyInference': '{amount}', - 'walkthrough.tooltip.letsGo': "Let's go!", - 'walkthrough.tooltip.next': 'Next →', - 'walkthrough.tooltip.skip': 'Skip tour', - 'walkthrough.tooltip.stepCounter': '{n} of {total}', + 'walkthrough.tooltip.letsGo': '出发吧!', + 'walkthrough.tooltip.next': '下一步 →', + 'walkthrough.tooltip.skip': '跳过引导', + 'walkthrough.tooltip.stepCounter': '{n} / {total}', 'webhooks.activity.empty': '暂无活动', 'webhooks.activity.title': '最近活动', 'webhooks.composioHistory.empty': '暂无记录', @@ -370,25 +366,24 @@ const zhCN5: TranslationMap = { 'webhooks.tunnels.title': 'Webhook 隧道', 'webhooks.tunnels.toggleFailed': '切换回显失败', 'composio.authExpired': '授权已过期', - 'composio.reconnect': 'Reconnect', - 'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.', - 'composio.notYetRouted': 'not yet routed', - 'composio.triggers.loading': 'Loading…', - 'conversations.taskKanban.todo': 'To do', - 'settings.composio.loading': 'Loading…', - 'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet', - 'skills.uninstall.confirmTitle': 'Uninstall {name}?', - 'conversations.taskKanban.blocked': 'Blocked', - 'conversations.taskKanban.done': 'Done', - 'conversations.taskKanban.inProgress': 'In progress', - 'intelligence.memoryChunk.detail.copiedHint': 'copied', - 'settings.composio.notYetRouted': 'not yet routed', - 'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.', + 'composio.reconnect': '重新连接', + 'composio.directModeRequiresKey': '保存失败。直连模式需要非空的 API 密钥。', + 'composio.notYetRouted': '尚未路由', + 'composio.triggers.loading': '加载中…', + 'conversations.taskKanban.todo': '待办', + 'settings.composio.loading': '加载中…', + 'settings.mascot.noCharactersAvailable': '暂无可用的 OpenHuman 角色', + 'skills.uninstall.confirmTitle': '卸载 {name}?', + 'conversations.taskKanban.blocked': '已阻塞', + 'conversations.taskKanban.done': '已完成', + 'conversations.taskKanban.inProgress': '进行中', + 'intelligence.memoryChunk.detail.copiedHint': '已复制', + 'settings.composio.notYetRouted': '尚未路由', + 'settings.localModel.download.manageExternal': '在外部运行时中管理此模型。', 'settings.localModel.status.manageOllamaExternal': - 'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.', - 'settings.localModel.status.ollamaDocs': 'Ollama docs', - 'settings.localModel.status.thenRetry': - 'for setup instructions, then retry after your runtime is reachable.', + '请在 OpenHuman 之外管理 Ollama 进程和模型拉取,然后重新运行诊断。', + 'settings.localModel.status.ollamaDocs': 'Ollama 文档', + 'settings.localModel.status.thenRetry': '获取设置说明,待你的运行时可达后再重试。', }; export default zhCN5; diff --git a/app/src/lib/i18n/it.ts b/app/src/lib/i18n/it.ts new file mode 100644 index 000000000..15cdab7d9 --- /dev/null +++ b/app/src/lib/i18n/it.ts @@ -0,0 +1,12 @@ +import it1 from './chunks/it-1'; +import it2 from './chunks/it-2'; +import it3 from './chunks/it-3'; +import it4 from './chunks/it-4'; +import it5 from './chunks/it-5'; +import type { TranslationMap } from './types'; + +// Italian (Italiano) translations. Each chunk maps to chunks/en-N.ts. +// Missing keys fall back to English via I18nContext.resolveEn(). +const it: TranslationMap = { ...it1, ...it2, ...it3, ...it4, ...it5 }; + +export default it; diff --git a/app/src/lib/i18n/types.ts b/app/src/lib/i18n/types.ts index 928ccb295..14277080b 100644 --- a/app/src/lib/i18n/types.ts +++ b/app/src/lib/i18n/types.ts @@ -1,4 +1,4 @@ -export type Locale = 'en' | 'zh-CN' | 'hi' | 'es' | 'ar' | 'fr' | 'bn' | 'pt' | 'ru' | 'id'; +export type Locale = 'en' | 'zh-CN' | 'hi' | 'es' | 'ar' | 'fr' | 'bn' | 'pt' | 'ru' | 'id' | 'it'; export interface TranslationMap { [key: string]: string; diff --git a/app/src/store/localeSlice.ts b/app/src/store/localeSlice.ts index 40ddb9ef0..ad560fdd8 100644 --- a/app/src/store/localeSlice.ts +++ b/app/src/store/localeSlice.ts @@ -16,6 +16,7 @@ const PREFIX_TO_LOCALE: Array<[string, Locale]> = [ ['ru', 'ru'], ['id', 'id'], ['in', 'id'], + ['it', 'it'], ['en', 'en'], ]; diff --git a/package.json b/package.json index 66489b7ee..3f170e3a3 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,13 @@ "debug": "bash scripts/debug/cli.sh", "test:install-ps1": "pwsh -NoProfile -File scripts/tests/OpenHumanWindowsInstall.Tests.ps1", "rust:check": "pnpm --filter openhuman-app rust:check", - "typecheck": "pnpm --filter openhuman-app compile" + "typecheck": "pnpm --filter openhuman-app compile", + "i18n:check": "tsx scripts/i18n-coverage.ts", + "i18n:dump": "tsx scripts/i18n-coverage.ts --no-unused --out tmp/i18n-coverage" }, "devDependencies": { "husky": "^9.1.7", + "tsx": "^4.20.3", "ws": "^8.20.0" }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7060175a9..93ae62c9a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -18,6 +18,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + tsx: + specifier: ^4.20.3 + version: 4.21.0 ws: specifier: ^8.20.0 version: 8.20.0 diff --git a/scripts/apply-i18n-translations.ts b/scripts/apply-i18n-translations.ts new file mode 100644 index 000000000..ea024220c --- /dev/null +++ b/scripts/apply-i18n-translations.ts @@ -0,0 +1,195 @@ +#!/usr/bin/env -S pnpm exec tsx +/** + * apply-i18n-translations — merge a translations file into chunked locale files. + * + * Input (one file per locale, default dir tmp/i18n-translations/): + * { + * "locale": "es", + * "translations": { "": "", ... } + * } + * + * Behavior: + * - Loads the existing locale chunks (keeps current translations for keys not in input). + * - For each English chunk (1..5), writes -N.ts containing every key in en-N's + * order. Value precedence: new translation → existing translation → English fallback. + * - Single-quoted JS string literals with safe escaping. Header comment preserved per locale. + * + * Usage: + * pnpm exec tsx scripts/apply-i18n-translations.ts [--dir tmp/i18n-translations] [--locale es] + */ + +import { promises as fs } from "node:fs"; +import path from "node:path"; +import { fileURLToPath, pathToFileURL } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const ROOT = path.resolve(path.dirname(__filename), ".."); +const CHUNKS_DIR = path.join(ROOT, "app/src/lib/i18n/chunks"); +const CHUNK_COUNT = 5; + +const LOCALE_HEADERS: Record = { + "zh-CN": "Simplified Chinese (简体中文)", + hi: "Hindi (हिन्दी)", + es: "Spanish (Español)", + ar: "Arabic (العربية)", + fr: "French (Français)", + bn: "Bengali (বাংলা)", + pt: "Portuguese (Português)", + ru: "Russian (Русский)", + id: "Indonesian (Bahasa Indonesia)", + it: "Italian (Italiano)", +}; + +interface InputFile { + locale: string; + translations: Record; +} + +function jsString(s: string): string { + // Single-quoted JS string literal. Escape backslash, single quote, and any + // character that would otherwise break out of the single-line literal: + // \n, \r, \t, U+2028, U+2029, and the rest of the C0 control range. + const escaped = s.replace(/[\\'\n\r\t\u0000-\u001f\u2028\u2029]/g, (ch) => { + switch (ch) { + case "\\": + return "\\\\"; + case "'": + return "\\'"; + case "\n": + return "\\n"; + case "\r": + return "\\r"; + case "\t": + return "\\t"; + default: + return "\\u" + ch.charCodeAt(0).toString(16).padStart(4, "0"); + } + }); + return "'" + escaped + "'"; +} + +function camelVar(locale: string, n: number): string { + // zh-CN → zhCN5, en → en5 + const safe = locale.replace(/-([a-z])/gi, (_, c: string) => c.toUpperCase()); + return `${safe}${n}`; +} + +async function loadChunk( + locale: string, + n: number, +): Promise> { + const p = path.join(CHUNKS_DIR, `${locale}-${n}.ts`); + const mod = await import(pathToFileURL(p).href); + if (!mod.default || typeof mod.default !== "object") { + throw new Error(`${p}: missing default export`); + } + return mod.default as Record; +} + +async function loadEnChunkKeysInOrder(n: number): Promise { + // Object key insertion order is preserved in V8 for string keys, so importing en-N + // and reading Object.keys gives us source order. + const en = await loadChunk("en", n); + return Object.keys(en); +} + +async function writeChunk( + locale: string, + n: number, + keysInOrder: string[], + values: Record, +): Promise { + const langLabel = LOCALE_HEADERS[locale] ?? locale; + const lines: string[] = []; + lines.push(`import type { TranslationMap } from '../types';`); + lines.push(""); + lines.push( + `// ${langLabel} chunk ${n}/${CHUNK_COUNT}. Translated from chunks/en-${n}.ts.`, + ); + lines.push(`const ${camelVar(locale, n)}: TranslationMap = {`); + for (const k of keysInOrder) { + const v = values[k]; + if (v === undefined) continue; // shouldn't happen — English fallback ensures coverage + lines.push(` ${jsString(k)}: ${jsString(v)},`); + } + lines.push(`};`); + lines.push(""); + lines.push(`export default ${camelVar(locale, n)};`); + lines.push(""); + const file = path.join(CHUNKS_DIR, `${locale}-${n}.ts`); + await fs.writeFile(file, lines.join("\n")); +} + +async function applyLocale( + input: InputFile, +): Promise<{ updated: number; total: number }> { + const { locale, translations } = input; + if (locale === "en") throw new Error("refusing to overwrite English source"); + let updated = 0; + let total = 0; + for (let n = 1; n <= CHUNK_COUNT; n++) { + const enKeys = await loadEnChunkKeysInOrder(n); + const enValues = await loadChunk("en", n); + let existing: Record = {}; + try { + existing = await loadChunk(locale, n); + } catch { + existing = {}; + } + const merged: Record = {}; + for (const k of enKeys) { + total++; + if (Object.prototype.hasOwnProperty.call(translations, k)) { + const newVal = translations[k]; + if (newVal !== existing[k]) updated++; + merged[k] = newVal; + } else if (Object.prototype.hasOwnProperty.call(existing, k)) { + merged[k] = existing[k]; + } else { + merged[k] = enValues[k]; // shouldn't trigger if locale is in-sync + } + } + await writeChunk(locale, n, enKeys, merged); + } + return { updated, total }; +} + +async function main() { + let dir = path.join(ROOT, "tmp/i18n-translations"); + let onlyLocale: string | null = null; + const argv = process.argv.slice(2); + for (let i = 0; i < argv.length; i++) { + if (argv[i] === "--dir") dir = path.resolve(argv[++i]); + else if (argv[i] === "--locale") onlyLocale = argv[++i]; + else if (argv[i] === "-h" || argv[i] === "--help") { + console.log( + "Usage: pnpm exec tsx scripts/apply-i18n-translations.ts [--dir ] [--locale ]", + ); + process.exit(0); + } else { + console.error(`Unknown arg: ${argv[i]}`); + process.exit(2); + } + } + const entries = await fs.readdir(dir); + for (const f of entries) { + if (!f.endsWith(".json")) continue; + const locale = f.replace(/\.json$/, ""); + if (onlyLocale && locale !== onlyLocale) continue; + const raw = await fs.readFile(path.join(dir, f), "utf8"); + const input = JSON.parse(raw) as InputFile; + if (input.locale !== locale) { + console.error( + `! ${f}: locale mismatch (${input.locale} vs ${locale}) — skipping`, + ); + continue; + } + const res = await applyLocale(input); + console.log(`${locale}: ${res.updated}/${res.total} entries updated`); + } +} + +main().catch((err) => { + console.error(err); + process.exit(2); +}); diff --git a/scripts/i18n-coverage.ts b/scripts/i18n-coverage.ts new file mode 100644 index 000000000..8dae791c0 --- /dev/null +++ b/scripts/i18n-coverage.ts @@ -0,0 +1,457 @@ +#!/usr/bin/env -S pnpm exec tsx +/** + * i18n-coverage — surface missing / incomplete / unused / drifted translation keys. + * + * Source of truth: app/src/lib/i18n/chunks/en-{1..5}.ts (aggregated by app/src/lib/i18n/en.ts) + * Translations: app/src/lib/i18n/chunks/-{1..5}.ts (aggregated by .ts) + * Locale list: app/src/lib/i18n/types.ts (Locale union) + * + * Reports, per locale: + * - missing chunk files + * - missing keys (in en, absent in locale) — overall + per chunk + * - extra keys (in locale, absent in en) + * - placeholder/untranslated entries (value identical to English) + * - per-chunk drift (key belongs to en-N but locale put it in -M, M≠N) + * + * Repo-wide: + * - unused keys (defined in en, never referenced via t('…') / t("…") in app/src) + * + * Usage: pnpm exec tsx scripts/i18n-coverage.ts [--json] [--locale es,fr] [--no-unused] [--out ] + * + * With --out , writes one JSON per non-English locale (/.json) containing + * categorized work-lists for translators (missing, extra, drift, untranslated with en value). + */ + +import { promises as fs } from "node:fs"; +import path from "node:path"; +import { fileURLToPath, pathToFileURL } from "node:url"; + +const __filename = fileURLToPath(import.meta.url); +const ROOT = path.resolve(path.dirname(__filename), ".."); +const I18N_DIR = path.join(ROOT, "app/src/lib/i18n"); +const CHUNKS_DIR = path.join(I18N_DIR, "chunks"); +const APP_SRC = path.join(ROOT, "app/src"); +const CHUNK_COUNT = 5; + +const ALL_LOCALES = [ + "en", + "zh-CN", + "hi", + "es", + "ar", + "fr", + "bn", + "pt", + "ru", + "id", + "it", +] as const; +type Locale = (typeof ALL_LOCALES)[number]; + +interface CliOptions { + json: boolean; + locales: Locale[]; + scanUnused: boolean; + outDir: string | null; + strictUnused: boolean; +} + +function parseArgs(argv: string[]): CliOptions { + const opts: CliOptions = { + json: false, + locales: [...ALL_LOCALES], + scanUnused: true, + outDir: null, + strictUnused: false, + }; + for (let i = 0; i < argv.length; i++) { + const a = argv[i]; + if (a === "--json") opts.json = true; + else if (a === "--no-unused") opts.scanUnused = false; + else if (a === "--strict-unused") opts.strictUnused = true; + else if (a === "--out") { + const out = argv[++i]; + if (!out || out.startsWith("--")) { + console.error("--out requires a directory path"); + process.exit(2); + } + opts.outDir = out; + } else if (a === "--locale" || a === "--locales") { + const raw = argv[++i]; + if (!raw || raw.startsWith("--")) { + console.error("--locale requires a comma-separated locale list"); + process.exit(2); + } + const list = raw + .split(",") + .map((s) => s.trim()) + .filter(Boolean) as Locale[]; + if (!list.length) { + console.error("--locale cannot be empty"); + process.exit(2); + } + const bad = list.filter((l) => !ALL_LOCALES.includes(l)); + if (bad.length) { + console.error( + `Unknown locales: ${bad.join(", ")}. Known: ${ALL_LOCALES.join(", ")}`, + ); + process.exit(2); + } + opts.locales = list; + } else if (a === "-h" || a === "--help") { + console.log( + "Usage: pnpm exec tsx scripts/i18n-coverage.ts [--json] [--locale es,fr] [--no-unused] [--strict-unused] [--out ]", + ); + process.exit(0); + } else { + console.error(`Unknown arg: ${a}`); + process.exit(2); + } + } + return opts; +} + +async function fileExists(p: string): Promise { + try { + await fs.access(p); + return true; + } catch { + return false; + } +} + +async function loadChunk( + locale: Locale, + n: number, +): Promise | null> { + const p = path.join(CHUNKS_DIR, `${locale}-${n}.ts`); + if (!(await fileExists(p))) return null; + const mod = await import(pathToFileURL(p).href); + const val = mod.default; + if (!val || typeof val !== "object") { + throw new Error(`${p}: default export is not a translation map`); + } + return val as Record; +} + +interface LocaleData { + chunks: Array | null>; // index 0..CHUNK_COUNT-1 + flat: Record; + keyToChunk: Map; // 1-indexed chunk number + missingChunks: number[]; // 1-indexed +} + +async function loadLocale(locale: Locale): Promise { + const chunks: Array | null> = []; + const flat: Record = {}; + const keyToChunk = new Map(); + const missingChunks: number[] = []; + + for (let n = 1; n <= CHUNK_COUNT; n++) { + const chunk = await loadChunk(locale, n); + chunks.push(chunk); + if (chunk === null) { + missingChunks.push(n); + continue; + } + for (const [k, v] of Object.entries(chunk)) { + // Last write wins (matches the runtime spread order in .ts). + flat[k] = v; + keyToChunk.set(k, n); + } + } + return { chunks, flat, keyToChunk, missingChunks }; +} + +async function walkSourceFiles(dir: string, out: string[]): Promise { + const entries = await fs.readdir(dir, { withFileTypes: true }); + for (const e of entries) { + if ( + e.name === "node_modules" || + e.name === "__tests__" || + e.name === "lib/i18n" + ) + continue; + const p = path.join(dir, e.name); + if (e.isDirectory()) { + // Skip the i18n directory itself — we don't count the definitions as usages. + if (p.startsWith(I18N_DIR)) continue; + await walkSourceFiles(p, out); + } else if ( + e.isFile() && + /\.(ts|tsx)$/.test(e.name) && + !/\.test\.tsx?$/.test(e.name) + ) { + out.push(p); + } + } +} + +const T_CALL_RE = /\bt\(\s*(['"`])([^'"`]+?)\1/g; + +async function collectUsedKeys(): Promise> { + const files: string[] = []; + await walkSourceFiles(APP_SRC, files); + const used = new Set(); + for (const f of files) { + const src = await fs.readFile(f, "utf8"); + for (const m of src.matchAll(T_CALL_RE)) { + used.add(m[2]); + } + } + return used; +} + +interface LocaleReport { + locale: Locale; + missingChunks: number[]; + totalKeys: number; + missingKeys: string[]; + extraKeys: string[]; + untranslatedKeys: string[]; // value === english value (excluding intentional brand strings) + driftedKeys: Array<{ + key: string; + expectedChunk: number; + actualChunk: number; + }>; + perChunk: Array<{ chunk: number; missing: number; total: number }>; +} + +function diffKeys( + en: LocaleData, + other: LocaleData, +): { missing: string[]; extra: string[] } { + const enKeys = new Set(Object.keys(en.flat)); + const otherKeys = new Set(Object.keys(other.flat)); + const missing: string[] = []; + const extra: string[] = []; + for (const k of enKeys) if (!otherKeys.has(k)) missing.push(k); + for (const k of otherKeys) if (!enKeys.has(k)) extra.push(k); + missing.sort(); + extra.sort(); + return { missing, extra }; +} + +function findUntranslated(en: LocaleData, other: LocaleData): string[] { + const out: string[] = []; + for (const [k, v] of Object.entries(other.flat)) { + const enV = en.flat[k]; + if (enV === undefined) continue; + if (v === enV && v.trim() !== "") out.push(k); + } + out.sort(); + return out; +} + +function findDrift(en: LocaleData, other: LocaleData) { + const out: Array<{ + key: string; + expectedChunk: number; + actualChunk: number; + }> = []; + for (const [k, actual] of other.keyToChunk) { + const expected = en.keyToChunk.get(k); + if (expected !== undefined && expected !== actual) { + out.push({ key: k, expectedChunk: expected, actualChunk: actual }); + } + } + out.sort((a, b) => a.key.localeCompare(b.key)); + return out; +} + +function perChunkMissing(en: LocaleData, other: LocaleData) { + const out: Array<{ chunk: number; missing: number; total: number }> = []; + for (let n = 1; n <= CHUNK_COUNT; n++) { + const enChunk = en.chunks[n - 1] ?? {}; + const otherChunk = other.chunks[n - 1] ?? {}; + const enKeys = Object.keys(enChunk); + let missing = 0; + for (const k of enKeys) if (!(k in otherChunk)) missing++; + out.push({ chunk: n, missing, total: enKeys.length }); + } + return out; +} + +function formatReport( + reports: LocaleReport[], + unusedKeys: string[] | null, +): string { + const lines: string[] = []; + lines.push("# i18n coverage report"); + lines.push(""); + for (const r of reports) { + lines.push(`## ${r.locale} (${r.totalKeys} keys)`); + if (r.missingChunks.length) { + lines.push( + ` ! missing chunk files: ${r.missingChunks.map((n) => `${r.locale}-${n}.ts`).join(", ")}`, + ); + } + lines.push(` missing: ${r.missingKeys.length}`); + lines.push(` extra: ${r.extraKeys.length}`); + lines.push( + ` untranslated: ${r.untranslatedKeys.length} (value identical to English)`, + ); + lines.push( + ` drifted chunks: ${r.driftedKeys.length} (key in wrong chunk N)`, + ); + const pc = r.perChunk + .map((c) => `${c.chunk}:${c.total - c.missing}/${c.total}`) + .join(" "); + lines.push(` per-chunk: ${pc}`); + if (r.missingKeys.length) { + const preview = r.missingKeys.slice(0, 15).join(", "); + const more = + r.missingKeys.length > 15 + ? `, … (+${r.missingKeys.length - 15} more)` + : ""; + lines.push(` missing[head]: ${preview}${more}`); + } + if (r.extraKeys.length) { + const preview = r.extraKeys.slice(0, 15).join(", "); + const more = + r.extraKeys.length > 15 ? `, … (+${r.extraKeys.length - 15} more)` : ""; + lines.push(` extra[head]: ${preview}${more}`); + } + if (r.driftedKeys.length) { + const sample = r.driftedKeys + .slice(0, 5) + .map( + (d) => + `${d.key} (en-${d.expectedChunk} → ${r.locale}-${d.actualChunk})`, + ) + .join("; "); + lines.push(` drift[head]: ${sample}`); + } + lines.push(""); + } + if (unusedKeys) { + lines.push(`## unused English keys: ${unusedKeys.length}`); + if (unusedKeys.length) { + const preview = unusedKeys.slice(0, 30).join(", "); + const more = + unusedKeys.length > 30 ? `, … (+${unusedKeys.length - 30} more)` : ""; + lines.push(` ${preview}${more}`); + } + lines.push(""); + } + return lines.join("\n"); +} + +async function main() { + const opts = parseArgs(process.argv.slice(2)); + + const en = await loadLocale("en"); + if (en.missingChunks.length) { + console.error( + `! English chunks missing: ${en.missingChunks.join(", ")} — cannot continue.`, + ); + process.exit(2); + } + + // Guard against drift between en.ts (runtime source of truth) and the en-N.ts chunks. + // Both must agree key-for-key or downstream tests / translator workflows will diverge. + const enAggregateModule = (await import( + pathToFileURL(path.join(I18N_DIR, "en.ts")).href + )) as { default: Record }; + const enTsKeys = new Set(Object.keys(enAggregateModule.default)); + const enChunkKeys = new Set(Object.keys(en.flat)); + const inEnTsNotChunks = [...enTsKeys].filter((k) => !enChunkKeys.has(k)); + const inChunksNotEnTs = [...enChunkKeys].filter((k) => !enTsKeys.has(k)); + if (inEnTsNotChunks.length || inChunksNotEnTs.length) { + console.error( + `! Drift between en.ts and en-N.ts chunks:\n` + + ` in en.ts only: ${inEnTsNotChunks.join(", ") || "(none)"}\n` + + ` in chunks only: ${inChunksNotEnTs.join(", ") || "(none)"}`, + ); + process.exit(2); + } + + const reports: LocaleReport[] = []; + for (const locale of opts.locales) { + if (locale === "en") continue; + const data = await loadLocale(locale); + const { missing, extra } = diffKeys(en, data); + reports.push({ + locale, + missingChunks: data.missingChunks, + totalKeys: Object.keys(data.flat).length, + missingKeys: missing, + extraKeys: extra, + untranslatedKeys: findUntranslated(en, data), + driftedKeys: findDrift(en, data), + perChunk: perChunkMissing(en, data), + }); + } + + if (opts.outDir) { + await fs.mkdir(opts.outDir, { recursive: true }); + for (const r of reports) { + const data = await loadLocale(r.locale); + const untranslated = r.untranslatedKeys.map((k) => ({ + key: k, + en: en.flat[k], + current: data.flat[k], + })); + const missing = r.missingKeys.map((k) => ({ key: k, en: en.flat[k] })); + const extra = r.extraKeys.map((k) => ({ key: k, current: data.flat[k] })); + const drift = r.driftedKeys; + const out = { + locale: r.locale, + generatedAt: new Date().toISOString(), + counts: { + total: r.totalKeys, + missing: missing.length, + extra: extra.length, + drift: drift.length, + untranslated: untranslated.length, + }, + missing, + extra, + drift, + untranslated, + }; + const file = path.join(opts.outDir, `${r.locale}.json`); + await fs.writeFile(file, JSON.stringify(out, null, 2)); + if (!opts.json) console.error(` wrote ${path.relative(ROOT, file)}`); + } + } + + let unused: string[] | null = null; + if (opts.scanUnused) { + const used = await collectUsedKeys(); + unused = Object.keys(en.flat) + .filter((k) => !used.has(k)) + .sort(); + } + + if (opts.json) { + console.log( + JSON.stringify( + { + enKeyCount: Object.keys(en.flat).length, + locales: reports, + unusedKeys: unused, + }, + null, + 2, + ), + ); + } else { + console.log(formatReport(reports, unused)); + } + + const localeFailure = reports.some( + (r) => + r.missingChunks.length || + r.missingKeys.length || + r.extraKeys.length || + r.driftedKeys.length, + ); + const unusedFailure = opts.strictUnused && (unused?.length ?? 0) > 0; + process.exit(localeFailure || unusedFailure ? 1 : 0); +} + +main().catch((err) => { + console.error(err); + process.exit(2); +}); diff --git a/scripts/shortcuts/work/start.sh b/scripts/shortcuts/work/start.sh index 7cf2c50d1..edee07323 100755 --- a/scripts/shortcuts/work/start.sh +++ b/scripts/shortcuts/work/start.sh @@ -124,17 +124,25 @@ if [ ! -f "$template" ]; then fi # Use awk for substitution — handles multi-line values (issue body) cleanly. +# Pass values via the environment (ENVIRON[]) because BSD awk on macOS rejects +# literal newlines in `-v var=value`, and the issue body routinely has them. # Escape backslashes and ampersands so gsub doesn't interpret them in the # replacement text. -prompt=$(awk -v issue="$issue" -v repo="$repo" -v branch="$current_branch" \ - -v url="$url" -v title="$title" -v labels="$labels_display" \ - -v body="$body" ' +prompt=$(WORK_ISSUE="$issue" WORK_REPO_NAME="$repo" WORK_BRANCH="$current_branch" \ + WORK_URL="$url" WORK_TITLE="$title" WORK_LABELS="$labels_display" \ + WORK_BODY="$body" \ + awk ' function esc(s) { gsub(/\\/, "\\\\", s); gsub(/&/, "\\\\&", s); return s } BEGIN { - issue=esc(issue); repo=esc(repo); branch=esc(branch); - url=esc(url); title=esc(title); labels=esc(labels); body=esc(body); + issue=esc(ENVIRON["WORK_ISSUE"]); + repo=esc(ENVIRON["WORK_REPO_NAME"]); + branch=esc(ENVIRON["WORK_BRANCH"]); + url=esc(ENVIRON["WORK_URL"]); + title=esc(ENVIRON["WORK_TITLE"]); + labels=esc(ENVIRON["WORK_LABELS"]); + body=esc(ENVIRON["WORK_BODY"]); } { gsub(/__ISSUE__/, issue);